0c9110
From bedb4f5a00ceaff0d55ecfe81ada9d0e983ca347 Mon Sep 17 00:00:00 2001
0c9110
From: Jakub Filak <jfilak@redhat.com>
0c9110
Date: Fri, 19 Dec 2014 00:19:34 +0100
0c9110
Subject: [LIBREPORT PATCH 124/124] ureport: introduce HTTPAuth
0c9110
0c9110
Read HTTP Basic Authentication credentials from the configuration file.
0c9110
0c9110
HTTPAuth has priority to SSLClientAuth. When both are set to some value
0c9110
the latter is ignored.
0c9110
0c9110
HTTPAuth configuration option values:
0c9110
 - "rhts-credentials" : a place holder for Login= and Password= from
0c9110
                        rhtsupport.conf
0c9110
 - "<username>:<password>"
0c9110
 - "<username>" : a prompt will be issue for password (export
0c9110
                  REPORT_CLIENT_NONINTERACTIVE=1 env variable to tell
0c9110
                  libreport that it must not wait for user input).
0c9110
0c9110
Related: #1140224
0c9110
0c9110
Signed-off-by: Jakub Filak <jfilak@redhat.com>
0c9110
---
0c9110
 doc/reporter-ureport.txt                       |  17 +++
0c9110
 src/include/ureport.h                          |  17 +++
0c9110
 src/lib/ureport.c                              |  68 +++++++++++-
0c9110
 src/plugins/reporter-ureport.c                 |  11 +-
0c9110
 src/plugins/ureport.conf                       |  10 +-
0c9110
 tests/Makefile.am                              |   2 +-
0c9110
 tests/ureport-rhts-credentials/rhtsupport.conf |   2 +
0c9110
 tests/ureport.at                               | 145 +++++++++++++++++++++++++
0c9110
 8 files changed, 264 insertions(+), 8 deletions(-)
0c9110
 create mode 100644 tests/ureport-rhts-credentials/rhtsupport.conf
0c9110
0c9110
diff --git a/doc/reporter-ureport.txt b/doc/reporter-ureport.txt
0c9110
index 1a67441..420adcf 100644
0c9110
--- a/doc/reporter-ureport.txt
0c9110
+++ b/doc/reporter-ureport.txt
0c9110
@@ -44,6 +44,19 @@ Configuration file lines should have 'PARAM = VALUE' format. The parameters are:
0c9110
    '<cert_path>:<key_path>';;
0c9110
       Manually supply paths to certificate and the corresponding key in PEM format.
0c9110
 
0c9110
+'HTTPAuth'::
0c9110
+   Use the configured values to as HTTP Basic Authentication credentials.
0c9110
+   Assigning any value to this option changes the default value of
0c9110
+   IncludeAuthData to yes.
0c9110
+
0c9110
+   Possible values are::
0c9110
+
0c9110
+   'rhts-credentials';;
0c9110
+      Uses Login= and Password= values from /etc/libreport/plugins/rhtsupport.conf.
0c9110
+
0c9110
+   '<user_name>:<password>';;
0c9110
+      Manually supply credentials.
0c9110
+
0c9110
 'ContactEmail'::
0c9110
    Email address attached to a bthash on the server.
0c9110
 
0c9110
@@ -93,6 +106,10 @@ OPTIONS
0c9110
    Enables client authentication. See 'SSLClientAuth' configuration file
0c9110
    option for list of possible values.
0c9110
 
0c9110
+-h, --http-auth CREDENTIALS::
0c9110
+   Enables client authentication via HTTP Authentication. See 'HTTPAuth'
0c9110
+   configuration file option for list of possible values.
0c9110
+
0c9110
 -v::
0c9110
    Be more verbose. Can be given multiple times.
0c9110
 
0c9110
diff --git a/src/include/ureport.h b/src/include/ureport.h
0c9110
index 104e8d0..780b898 100644
0c9110
--- a/src/include/ureport.h
0c9110
+++ b/src/include/ureport.h
0c9110
@@ -126,6 +126,23 @@ ureport_server_config_set_basic_auth(struct ureport_server_config *config,
0c9110
                                      const char *username, const char *password);
0c9110
 
0c9110
 /*
0c9110
+ * Configure user name and password for HTTP Basic authentication according to
0c9110
+ * user preferences.
0c9110
+ *
0c9110
+ *  "rhts-credentials" - Uses Login= and Password= from rhtsupport.conf
0c9110
+ *  "<user_name>:<password>" - Manually supply user name and password.
0c9110
+ *  "<user_name>" - Manually supply user name and be asked for password.
0c9110
+ *
0c9110
+ * The function uses ask_password() function from client.h
0c9110
+ *
0c9110
+ * @param config Configured structure
0c9110
+ * @param http_auth_pref User HTTP Authentication preferences
0c9110
+ */
0c9110
+void
0c9110
+ureport_server_config_load_basic_auth(struct ureport_server_config *config,
0c9110
+                                      const char *http_auth_pref);
0c9110
+
0c9110
+/*
0c9110
  * uReport server response
0c9110
  */
0c9110
 struct ureport_server_response
0c9110
diff --git a/src/lib/ureport.c b/src/lib/ureport.c
0c9110
index fef3922..5065a52 100644
0c9110
--- a/src/lib/ureport.c
0c9110
+++ b/src/lib/ureport.c
0c9110
@@ -23,6 +23,7 @@
0c9110
 #include <satyr/report.h>
0c9110
 
0c9110
 #include "internal_libreport.h"
0c9110
+#include "client.h"
0c9110
 #include "ureport.h"
0c9110
 #include "libreport_curl.h"
0c9110
 
0c9110
@@ -249,18 +250,79 @@ ureport_server_config_set_basic_auth(struct ureport_server_config *config,
0c9110
 }
0c9110
 
0c9110
 void
0c9110
+ureport_server_config_load_basic_auth(struct ureport_server_config *config,
0c9110
+                                      const char *http_auth_pref)
0c9110
+{
0c9110
+    if (http_auth_pref == NULL)
0c9110
+        return;
0c9110
+
0c9110
+    map_string_t *settings = NULL;
0c9110
+
0c9110
+    char *tmp_password = NULL;
0c9110
+    char *tmp_username = NULL;
0c9110
+    const char *username = NULL;
0c9110
+    const char *password = NULL;
0c9110
+
0c9110
+    if (strcmp(http_auth_pref, "rhts-credentials") == 0)
0c9110
+    {
0c9110
+        settings = new_map_string();
0c9110
+
0c9110
+        if (!load_plugin_conf_file("rhtsupport.conf", settings, /*skip key w/o values:*/ false))
0c9110
+            error_msg_and_die("Could not get RHTSupport credentials");
0c9110
+
0c9110
+        username = get_map_string_item_or_NULL(settings, "Login");
0c9110
+        password = get_map_string_item_or_NULL(settings, "Password");
0c9110
+
0c9110
+        if (config->ur_url == NULL)
0c9110
+            ureport_server_config_set_url(config, xstrdup(RHSM_WEB_SERVICE_URL));
0c9110
+    }
0c9110
+    else
0c9110
+    {
0c9110
+        username = tmp_username = xstrdup(http_auth_pref);
0c9110
+        password = strchr(tmp_username, ':');
0c9110
+
0c9110
+        if (password != NULL)
0c9110
+            /* It is "char *", see strchr() few lines above. */
0c9110
+            *((char *)(password++)) = '\0';
0c9110
+    }
0c9110
+
0c9110
+    if (password == NULL)
0c9110
+    {
0c9110
+        char *message = xasprintf("Please provide uReport server password for user '%s':", username);
0c9110
+        password = tmp_password = ask_password(message);
0c9110
+        free(message);
0c9110
+
0c9110
+        if (password == NULL)
0c9110
+            error_msg_and_die("Cannot continue without uReport server password!");
0c9110
+    }
0c9110
+
0c9110
+    ureport_server_config_set_basic_auth(config, username, password);
0c9110
+
0c9110
+    free(tmp_password);
0c9110
+    free(tmp_username);
0c9110
+    free_map_string(settings);
0c9110
+}
0c9110
+
0c9110
+void
0c9110
 ureport_server_config_load(struct ureport_server_config *config,
0c9110
                            map_string_t *settings)
0c9110
 {
0c9110
     UREPORT_OPTION_VALUE_FROM_CONF(settings, "URL", config->ur_url, xstrdup);
0c9110
     UREPORT_OPTION_VALUE_FROM_CONF(settings, "SSLVerify", config->ur_ssl_verify, string_to_bool);
0c9110
 
0c9110
+    const char *http_auth_pref = NULL;
0c9110
+    UREPORT_OPTION_VALUE_FROM_CONF(settings, "HTTPAuth", http_auth_pref, (const char *));
0c9110
+    ureport_server_config_load_basic_auth(config, http_auth_pref);
0c9110
+
0c9110
     const char *client_auth = NULL;
0c9110
-    UREPORT_OPTION_VALUE_FROM_CONF(settings, "SSLClientAuth", client_auth, (const char *));
0c9110
-    ureport_server_config_set_client_auth(config, client_auth);
0c9110
+    if (http_auth_pref == NULL)
0c9110
+    {
0c9110
+        UREPORT_OPTION_VALUE_FROM_CONF(settings, "SSLClientAuth", client_auth, (const char *));
0c9110
+        ureport_server_config_set_client_auth(config, client_auth);
0c9110
+    }
0c9110
 
0c9110
     /* If SSLClientAuth is configured, include the auth items by default. */
0c9110
-    bool include_auth = !!config->ur_client_cert;
0c9110
+    bool include_auth = config->ur_client_cert != NULL || config->ur_username != NULL;
0c9110
     UREPORT_OPTION_VALUE_FROM_CONF(settings, "IncludeAuthData", include_auth, string_to_bool);
0c9110
 
0c9110
     if (include_auth)
0c9110
diff --git a/src/plugins/reporter-ureport.c b/src/plugins/reporter-ureport.c
0c9110
index f15d56d..22efb76 100644
0c9110
--- a/src/plugins/reporter-ureport.c
0c9110
+++ b/src/plugins/reporter-ureport.c
0c9110
@@ -43,7 +43,8 @@ int main(int argc, char **argv)
0c9110
         OPT_u = 1 << 2,
0c9110
         OPT_k = 1 << 3,
0c9110
         OPT_t = 1 << 4,
0c9110
-        OPT_i = 1 << 5,
0c9110
+        OPT_h = 1 << 5,
0c9110
+        OPT_i = 1 << 6,
0c9110
     };
0c9110
 
0c9110
     int ret = 1; /* "failure" (for now) */
0c9110
@@ -51,6 +52,7 @@ int main(int argc, char **argv)
0c9110
     const char *conf_file = UREPORT_CONF_FILE_PATH;
0c9110
     const char *arg_server_url = NULL;
0c9110
     const char *client_auth = NULL;
0c9110
+    const char *http_auth = NULL;
0c9110
     GList *auth_items = NULL;
0c9110
     const char *dump_dir_path = ".";
0c9110
     const char *ureport_hash = NULL;
0c9110
@@ -67,6 +69,7 @@ int main(int argc, char **argv)
0c9110
         OPT_BOOL('k', "insecure", &insecure,
0c9110
                           _("Allow insecure connection to ureport server")),
0c9110
         OPT_STRING('t', "auth", &client_auth, "SOURCE", _("Use client authentication")),
0c9110
+        OPT_STRING('h', "http-auth", &http_auth, "CREDENTIALS", _("Use HTTP Authentication")),
0c9110
         OPT_LIST('i', "auth_items", &auth_items, "AUTH_ITEMS", _("Additional files included in 'auth' key")),
0c9110
         OPT_STRING('c', NULL, &conf_file, "FILE", _("Configuration file")),
0c9110
         OPT_STRING('a', "attach", &ureport_hash, "BTHASH",
0c9110
@@ -85,8 +88,8 @@ int main(int argc, char **argv)
0c9110
     };
0c9110
 
0c9110
     const char *program_usage_string = _(
0c9110
-        "& [-v] [-c FILE] [-u URL] [-k] [-t SOURCE] [-A -a bthash -B -b bug-id -E -e email] [-d DIR]\n"
0c9110
-        "& [-v] [-c FILE] [-u URL] [-k] [-t SOURCE] [-i AUTH_ITEMS]\\\n"
0c9110
+        "& [-v] [-c FILE] [-u URL] [-k] [-t SOURCE] [-h CREDENTIALS] [-A -a bthash -B -b bug-id -E -e email] [-d DIR]\n"
0c9110
+        "& [-v] [-c FILE] [-u URL] [-k] [-t SOURCE] [-h CREDENTIALS] [-i AUTH_ITEMS]\\\n"
0c9110
         "  [-A -a bthash -B -b bug-id -E -e email] [-d DIR]\n"
0c9110
         "\n"
0c9110
         "Upload micro report or add an attachment to a micro report\n"
0c9110
@@ -107,6 +110,8 @@ int main(int argc, char **argv)
0c9110
         config.ur_ssl_verify = !insecure;
0c9110
     if (opts & OPT_t)
0c9110
         ureport_server_config_set_client_auth(&config, client_auth);
0c9110
+    if (opts & OPT_h)
0c9110
+        ureport_server_config_load_basic_auth(&config, http_auth);
0c9110
     if (opts & OPT_i)
0c9110
     {
0c9110
         g_list_free_full(config.ur_prefs.urp_auth_items, free);
0c9110
diff --git a/src/plugins/ureport.conf b/src/plugins/ureport.conf
0c9110
index 42323d4..e04bf56 100644
0c9110
--- a/src/plugins/ureport.conf
0c9110
+++ b/src/plugins/ureport.conf
0c9110
@@ -23,8 +23,16 @@ AuthDataItems = hostname, machineid
0c9110
 # None (default):
0c9110
 # SSLClientAuth =
0c9110
 # Using RH subscription management entitlement certificate:
0c9110
-SSLClientAuth = rhsm
0c9110
+# SSLClientAuth = rhsm
0c9110
 # Using Puppet certificate:
0c9110
 # SSLClientAuth = puppet
0c9110
 # Using custom certificate:
0c9110
 # SSLClientAuth = /path/to/cert.pem:/path/to/key.pem
0c9110
+
0c9110
+# HTTP Basic authentication credentials.
0c9110
+# Assingning any value to 'HTTPAuth' changes the default value of
0c9110
+# 'IncludeAuthData' to 'yes'.
0c9110
+# Use Login= and Password= from /etc/libreport/plugins/rhtsupport.conf:
0c9110
+# HTTPAuth = rhts-credentials
0c9110
+# Use username and password:
0c9110
+# HTTPAuth = username:password
0c9110
diff --git a/tests/Makefile.am b/tests/Makefile.am
0c9110
index 1cfc206..a680f05 100644
0c9110
--- a/tests/Makefile.am
0c9110
+++ b/tests/Makefile.am
0c9110
@@ -49,7 +49,7 @@ TESTSUITE = $(srcdir)/testsuite
0c9110
 MAINTAINERCLEANFILES = Makefile.in $(TESTSUITE)
0c9110
 check_DATA = atconfig atlocal $(TESTSUITE)
0c9110
 DISTCLEANFILES = atconfig
0c9110
-EXTRA_DIST += atlocal.in conf ureport
0c9110
+EXTRA_DIST += atlocal.in conf ureport ureport-rhts-credentials
0c9110
 
0c9110
 atconfig: $(top_builddir)/config.status
0c9110
 	(cd ${top_builddir} && ./config.status ${subdir}/atconfig)
0c9110
diff --git a/tests/ureport-rhts-credentials/rhtsupport.conf b/tests/ureport-rhts-credentials/rhtsupport.conf
0c9110
new file mode 100644
0c9110
index 0000000..c30f743
0c9110
--- /dev/null
0c9110
+++ b/tests/ureport-rhts-credentials/rhtsupport.conf
0c9110
@@ -0,0 +1,2 @@
0c9110
+Login = rhn-user-name
0c9110
+Password = rhn-password
0c9110
diff --git a/tests/ureport.at b/tests/ureport.at
0c9110
index 76e2f7a..3a824a2 100644
0c9110
--- a/tests/ureport.at
0c9110
+++ b/tests/ureport.at
0c9110
@@ -109,6 +109,8 @@ AT_TESTFUN([ureport_server_config_load],
0c9110
 #include "ureport.h"
0c9110
 #include <assert.h>
0c9110
 
0c9110
+#define TESTING_CERTS_CORRECT_DIR_PATH "../../ureport/certs/correct"
0c9110
+
0c9110
 int main(void)
0c9110
 {
0c9110
     g_verbose=3;
0c9110
@@ -248,6 +250,73 @@ int main(void)
0c9110
     ureport_server_config_destroy(&config);
0c9110
     free_map_string(settings);
0c9110
 
0c9110
+    /* value from env */
0c9110
+    /* HTTPAuth set to 'username:password' */
0c9110
+    /* SSLClientAuth set to 'rhsm' */
0c9110
+    ureport_server_config_init(&config);
0c9110
+
0c9110
+    settings = new_map_string();
0c9110
+
0c9110
+    setenv("uReport_SSLClientAuth", "rhsm", 1);
0c9110
+    setenv("uReport_HTTPAuth", "username:password", 1);
0c9110
+    setenv("uReport_AuthDataItems", "hostname, time", 1);
0c9110
+
0c9110
+    setenv("LIBREPORT_DEBUG_RHSMENT_PEM_DIR_PATH", TESTING_CERTS_CORRECT_DIR_PATH, 1);
0c9110
+
0c9110
+    ureport_server_config_load(&config, settings);
0c9110
+
0c9110
+    assert(strcmp(config.ur_username, "username") == 0);
0c9110
+    assert(strcmp(config.ur_password, "password") == 0);
0c9110
+
0c9110
+    assert(config.ur_client_cert == NULL);
0c9110
+    assert(config.ur_client_key == NULL);
0c9110
+    assert(size_map_string(config.ur_http_headers) == 0);
0c9110
+
0c9110
+    l = config.ur_prefs.urp_auth_items;
0c9110
+    assert(strcmp(l->data, "hostname") == 0);
0c9110
+    assert(strcmp(l->next->data, "time") == 0);
0c9110
+
0c9110
+    unsetenv("LIBREPORT_DEBUG_RHSMENT_PEM_DIR_PATH");
0c9110
+
0c9110
+    unsetenv("uReport_SSLClientAuth");
0c9110
+    unsetenv("uReport_HTTPAuth");
0c9110
+    unsetenv("uReport_AuthDataItems");
0c9110
+
0c9110
+    free_map_string(settings);
0c9110
+
0c9110
+    ureport_server_config_destroy(&config);
0c9110
+
0c9110
+    /* value from settings */
0c9110
+    /* HTTPAuth set to 'username:password' */
0c9110
+    /* SSLClientAuth set to 'rhsm' */
0c9110
+    ureport_server_config_init(&config);
0c9110
+
0c9110
+    settings = new_map_string();
0c9110
+    insert_map_string(settings, xstrdup("SSLClientAuth"), xstrdup("rhsm"));
0c9110
+    insert_map_string(settings, xstrdup("HTTPAuth"), xstrdup("rhn-username:rhn-password"));
0c9110
+    insert_map_string(settings, xstrdup("AuthDataItems"), xstrdup("hostname, type"));
0c9110
+
0c9110
+    setenv("LIBREPORT_DEBUG_RHSMENT_PEM_DIR_PATH", TESTING_CERTS_CORRECT_DIR_PATH, 1);
0c9110
+
0c9110
+    ureport_server_config_load(&config, settings);
0c9110
+
0c9110
+    assert(strcmp(config.ur_username, "rhn-username") == 0);
0c9110
+    assert(strcmp(config.ur_password, "rhn-password") == 0);
0c9110
+
0c9110
+    assert(config.ur_client_cert == NULL);
0c9110
+    assert(config.ur_client_key == NULL);
0c9110
+    assert(size_map_string(config.ur_http_headers) == 0);
0c9110
+
0c9110
+    l = config.ur_prefs.urp_auth_items;
0c9110
+    assert(strcmp(l->data, "hostname") == 0);
0c9110
+    assert(strcmp(l->next->data, "type") == 0);
0c9110
+
0c9110
+    unsetenv("LIBREPORT_DEBUG_RHSMENT_PEM_DIR_PATH");
0c9110
+
0c9110
+    free_map_string(settings);
0c9110
+
0c9110
+    ureport_server_config_destroy(&config);
0c9110
+
0c9110
     return 0;
0c9110
 }
0c9110
 ]])
0c9110
@@ -1133,3 +1202,79 @@ int main(void)
0c9110
 }
0c9110
 ]])
0c9110
 
0c9110
+
0c9110
+## ------------------------------------- ##
0c9110
+## ureport_server_config_load_basic_auth ##
0c9110
+## ------------------------------------- ##
0c9110
+
0c9110
+AT_TESTFUN([ureport_server_config_load_basic_auth],
0c9110
+[[
0c9110
+#include "internal_libreport.h"
0c9110
+#include "ureport.h"
0c9110
+#include <assert.h>
0c9110
+#include "libreport_curl.h"
0c9110
+#include "problem_data.h"
0c9110
+
0c9110
+int main(void)
0c9110
+{
0c9110
+    g_verbose=3;
0c9110
+
0c9110
+    {
0c9110
+        struct ureport_server_config config;
0c9110
+        ureport_server_config_init(&config);
0c9110
+
0c9110
+        ureport_server_config_load_basic_auth(&config, "username:password");
0c9110
+
0c9110
+        assert(strcmp(config.ur_username, "username") == 0);
0c9110
+        assert(strcmp(config.ur_password, "password") == 0);
0c9110
+
0c9110
+        ureport_server_config_destroy(&config);
0c9110
+    }
0c9110
+
0c9110
+    {
0c9110
+        struct ureport_server_config config;
0c9110
+        ureport_server_config_init(&config);
0c9110
+
0c9110
+        setenv("LIBREPORT_DEBUG_PLUGINS_CONF_DIR", "../../ureport-rhts-credentials/", 1);
0c9110
+
0c9110
+        ureport_server_config_load_basic_auth(&config, "rhts-credentials");
0c9110
+
0c9110
+        assert(strcmp(config.ur_username, "rhn-user-name") == 0);
0c9110
+        assert(strcmp(config.ur_password, "rhn-password") == 0);
0c9110
+        assert(strcmp(config.ur_url, "https://api.access.redhat.com/rs/telemetry/abrt") == 0);
0c9110
+
0c9110
+        unsetenv("LIBREPORT_DEBUG_PLUGINS_CONF_DIR");
0c9110
+        ureport_server_config_destroy(&config);
0c9110
+    }
0c9110
+
0c9110
+    {
0c9110
+        pid_t pid = fork();
0c9110
+        if (pid < 0)
0c9110
+        {
0c9110
+            perror_msg("fork");
0c9110
+            return -1;
0c9110
+        }
0c9110
+
0c9110
+        if (pid == 0)
0c9110
+        {
0c9110
+            struct ureport_server_config config;
0c9110
+            ureport_server_config_init(&config);
0c9110
+
0c9110
+            setenv("REPORT_CLIENT_NONINTERACTIVE", "1", 1);
0c9110
+            ureport_server_config_load_basic_auth(&config, "username");
0c9110
+
0c9110
+            ureport_server_config_destroy(&config);
0c9110
+
0c9110
+            exit(0);
0c9110
+        }
0c9110
+
0c9110
+        int status;
0c9110
+        wait(&status);
0c9110
+
0c9110
+        assert(WIFEXITED(status));
0c9110
+        assert(WEXITSTATUS(status) != 0);
0c9110
+    }
0c9110
+
0c9110
+    return 0;
0c9110
+}
0c9110
+]])
0c9110
-- 
0c9110
1.8.3.1
0c9110