Blame SOURCES/0067-ureport-use-additional-HTTP-headers-with-rhsm-entitl.patch

4b6aa8
From 4f61f5d9eec75e471c8176dac0c21f4361e40ee6 Mon Sep 17 00:00:00 2001
4b6aa8
From: Jakub Filak <jfilak@redhat.com>
4b6aa8
Date: Thu, 11 Sep 2014 12:33:05 +0200
4b6aa8
Subject: [LIBREPORT PATCH 67/93] ureport: use additional HTTP headers with
4b6aa8
 'rhsm-entitlement' cert auth
4b6aa8
4b6aa8
Related to rhbz#1140224
4b6aa8
4b6aa8
Signed-off-by: Jakub Filak <jfilak@redhat.com>
4b6aa8
4b6aa8
Conflicts:
4b6aa8
	src/plugins/ureport.conf
4b6aa8
---
4b6aa8
 src/lib/json.c           | 29 +++++++++++----
4b6aa8
 src/lib/ureport.h        |  1 +
4b6aa8
 src/plugins/ureport.c    | 94 +++++++++++++++++++++++++++++++++++++++++++++++-
4b6aa8
 src/plugins/ureport.conf |  4 ++-
4b6aa8
 4 files changed, 119 insertions(+), 9 deletions(-)
4b6aa8
4b6aa8
diff --git a/src/lib/json.c b/src/lib/json.c
4b6aa8
index 8935ef8..6fbbf39 100644
4b6aa8
--- a/src/lib/json.c
4b6aa8
+++ b/src/lib/json.c
4b6aa8
@@ -113,14 +113,25 @@ struct post_state *post_ureport(const char *json, struct ureport_server_config *
4b6aa8
         post_state->client_key_path = config->ur_client_key;
4b6aa8
     }
4b6aa8
 
4b6aa8
-    static const char *headers[] = {
4b6aa8
-        "Accept: application/json",
4b6aa8
-        "Connection: close",
4b6aa8
-        NULL,
4b6aa8
-    };
4b6aa8
+    char **headers = xmalloc(sizeof(char *) * (3 + size_map_string(config->ur_http_headers)));
4b6aa8
+    headers[0] = (char *)"Accept: application/json";
4b6aa8
+    headers[1] = (char *)"Connection: close";
4b6aa8
+    headers[2] = NULL;
4b6aa8
+
4b6aa8
+    if (config->ur_http_headers != NULL)
4b6aa8
+    {
4b6aa8
+        unsigned i = 2;
4b6aa8
+        const char *header;
4b6aa8
+        const char *value;
4b6aa8
+        map_string_iter_t iter;
4b6aa8
+        init_map_string_iter(&iter, config->ur_http_headers);
4b6aa8
+        while (next_map_string_iter(&iter, &header, &value))
4b6aa8
+            headers[i++] = xasprintf("%s: %s", header, value);
4b6aa8
+        headers[i] = NULL;
4b6aa8
+    }
4b6aa8
 
4b6aa8
     post_string_as_form_data(post_state, config->ur_url, "application/json",
4b6aa8
-                     headers, json);
4b6aa8
+                    (const char **)headers, json);
4b6aa8
 
4b6aa8
     /* Client authentication failed. Try again without client auth.
4b6aa8
      * CURLE_SSL_CONNECT_ERROR - cert not found/server doesnt trust the CA
4b6aa8
@@ -135,10 +146,14 @@ struct post_state *post_ureport(const char *json, struct ureport_server_config *
4b6aa8
         post_state = new_post_state(flags);
4b6aa8
 
4b6aa8
         post_string_as_form_data(post_state, config->ur_url, "application/json",
4b6aa8
-                         headers, json);
4b6aa8
+                         (const char **)headers, json);
4b6aa8
 
4b6aa8
     }
4b6aa8
 
4b6aa8
+    for (unsigned i = size_map_string(config->ur_http_headers); i != 0; --i)
4b6aa8
+        free(headers[i + 1]);
4b6aa8
+    free(headers);
4b6aa8
+
4b6aa8
     return post_state;
4b6aa8
 }
4b6aa8
 
4b6aa8
diff --git a/src/lib/ureport.h b/src/lib/ureport.h
4b6aa8
index ca1d538..319aca9 100644
4b6aa8
--- a/src/lib/ureport.h
4b6aa8
+++ b/src/lib/ureport.h
4b6aa8
@@ -43,6 +43,7 @@ struct ureport_server_config
4b6aa8
     char *ur_client_cert; ///< Path to certificate used for client
4b6aa8
                           ///< authentication (or NULL)
4b6aa8
     char *ur_client_key;  ///< Private key for the certificate
4b6aa8
+    map_string_t *ur_http_headers; ///< Additional HTTP headers
4b6aa8
 
4b6aa8
     struct ureport_preferences ur_prefs; ///< configuration for uReport generation
4b6aa8
 };
4b6aa8
diff --git a/src/plugins/ureport.c b/src/plugins/ureport.c
4b6aa8
index d23cc79..9c69cad 100644
4b6aa8
--- a/src/plugins/ureport.c
4b6aa8
+++ b/src/plugins/ureport.c
4b6aa8
@@ -31,6 +31,12 @@
4b6aa8
 #define RHSM_CERT_PATH "/etc/pki/consumer/cert.pem"
4b6aa8
 #define RHSM_KEY_PATH "/etc/pki/consumer/key.pem"
4b6aa8
 
4b6aa8
+#define RHAP_PEM_DIR_PATH "/etc/pki/entitlement"
4b6aa8
+#define RHAP_ENT_DATA_BEGIN_TAG "-----BEGIN ENTITLEMENT DATA-----"
4b6aa8
+#define RHAP_ENT_DATA_END_TAG "-----END ENTITLEMENT DATA-----"
4b6aa8
+#define RHAP_SIG_DATA_BEGIN_TAG "-----BEGIN RSA SIGNATURE-----"
4b6aa8
+#define RHAP_SIG_DATA_END_TAG "-----END RSA SIGNATURE-----"
4b6aa8
+
4b6aa8
 #define VALUE_FROM_CONF(opt, var, tr) do { const char *value = getenv("uReport_"opt); \
4b6aa8
         if (!value) { value = get_map_string_item_or_NULL(settings, opt); } if (value) { var = tr(value); } \
4b6aa8
     } while(0)
4b6aa8
@@ -72,6 +78,88 @@ static void parse_client_auth_paths(struct ureport_server_config *config, const
4b6aa8
         config->ur_client_cert = xstrdup(RHSM_CERT_PATH);
4b6aa8
         config->ur_client_key = xstrdup(RHSM_KEY_PATH);
4b6aa8
     }
4b6aa8
+    else if (strcmp(client_auth, "rhsm-entitlement") == 0)
4b6aa8
+    {
4b6aa8
+        GList *certs = get_file_list(RHAP_PEM_DIR_PATH, "pem");
4b6aa8
+        if (g_list_length(certs) != 2)
4b6aa8
+        {
4b6aa8
+            log_notice(RHAP_PEM_DIR_PATH" does not contain unique cert-key files pair");
4b6aa8
+            log_notice("Not using client authentication");
4b6aa8
+            return;
4b6aa8
+        }
4b6aa8
+
4b6aa8
+        const char *cert = NULL;
4b6aa8
+        const char *key = NULL;
4b6aa8
+
4b6aa8
+        file_obj_t *fst = (file_obj_t *)certs->data;
4b6aa8
+        file_obj_t *scn = (file_obj_t *)certs->next->data;
4b6aa8
+
4b6aa8
+        if (strlen(fo_get_filename(fst)) < strlen(fo_get_filename(scn)))
4b6aa8
+        {
4b6aa8
+            cert = fo_get_filename(fst);
4b6aa8
+            key = fo_get_filename(scn);
4b6aa8
+
4b6aa8
+            config->ur_client_cert = xstrdup(fo_get_fullpath(fst));
4b6aa8
+            config->ur_client_key = xstrdup(fo_get_fullpath(scn));
4b6aa8
+        }
4b6aa8
+        else
4b6aa8
+        {
4b6aa8
+            cert = fo_get_filename(scn);
4b6aa8
+            key = fo_get_filename(fst);
4b6aa8
+
4b6aa8
+            config->ur_client_cert = xstrdup(fo_get_fullpath(scn));
4b6aa8
+            config->ur_client_key = xstrdup(fo_get_fullpath(fst));
4b6aa8
+        }
4b6aa8
+
4b6aa8
+        const bool iscomplement = prefixcmp(key, cert) != 0 || strcmp("-key", key + strlen(cert)) != 0;
4b6aa8
+        g_list_free_full(certs, (GDestroyNotify)free_file_obj);
4b6aa8
+
4b6aa8
+        if (iscomplement)
4b6aa8
+        {
4b6aa8
+            log_notice("Key file '%s' isn't complement to cert file '%s'",
4b6aa8
+                    config->ur_client_key, config->ur_client_cert);
4b6aa8
+            log_notice("Not using client authentication");
4b6aa8
+
4b6aa8
+            free(config->ur_client_cert);
4b6aa8
+            free(config->ur_client_key);
4b6aa8
+            config->ur_client_cert = NULL;
4b6aa8
+            config->ur_client_key = NULL;
4b6aa8
+
4b6aa8
+            return;
4b6aa8
+        }
4b6aa8
+
4b6aa8
+        char *certdata = xmalloc_open_read_close(config->ur_client_cert, /*no size limit*/NULL);
4b6aa8
+        if (certdata != NULL)
4b6aa8
+        {
4b6aa8
+            char *ent_data = xstrdup_between(certdata,
4b6aa8
+                    RHAP_ENT_DATA_BEGIN_TAG, RHAP_ENT_DATA_END_TAG);
4b6aa8
+
4b6aa8
+            char *sig_data = xstrdup_between(certdata,
4b6aa8
+                    RHAP_SIG_DATA_BEGIN_TAG, RHAP_SIG_DATA_END_TAG);
4b6aa8
+
4b6aa8
+            if (ent_data != NULL && sig_data != NULL)
4b6aa8
+            {
4b6aa8
+                ent_data = strremovech(ent_data, '\n');
4b6aa8
+                insert_map_string(config->ur_http_headers,
4b6aa8
+                        xstrdup("X-RH-Entitlement-Data"),
4b6aa8
+                        xasprintf(RHAP_ENT_DATA_BEGIN_TAG"%s"RHAP_ENT_DATA_END_TAG, ent_data));
4b6aa8
+
4b6aa8
+                sig_data = strremovech(sig_data, '\n');
4b6aa8
+                insert_map_string(config->ur_http_headers,
4b6aa8
+                        xstrdup("X-RH-Entitlement-Sig"),
4b6aa8
+                        xasprintf(RHAP_SIG_DATA_BEGIN_TAG"%s"RHAP_SIG_DATA_END_TAG, sig_data));
4b6aa8
+            }
4b6aa8
+            else
4b6aa8
+            {
4b6aa8
+                log_notice("Cert file '%s' doesn't contain Entitlement and RSA Signature sections", config->ur_client_cert);
4b6aa8
+                log_notice("Not using HTTP authentication headers");
4b6aa8
+            }
4b6aa8
+
4b6aa8
+            free(sig_data);
4b6aa8
+            free(ent_data);
4b6aa8
+            free(certdata);
4b6aa8
+        }
4b6aa8
+    }
4b6aa8
     else if (strcmp(client_auth, "puppet") == 0)
4b6aa8
     {
4b6aa8
         config->ur_client_cert = puppet_config_print("hostcert");
4b6aa8
@@ -83,7 +171,6 @@ static void parse_client_auth_paths(struct ureport_server_config *config, const
4b6aa8
         config->ur_client_cert = xstrdup(strtok(scratch, ":"));
4b6aa8
         config->ur_client_key = xstrdup(strtok(NULL, ":"));
4b6aa8
         free(scratch);
4b6aa8
-
4b6aa8
         if (config->ur_client_cert == NULL || config->ur_client_key == NULL)
4b6aa8
             error_msg_and_die("Invalid client authentication specification");
4b6aa8
     }
4b6aa8
@@ -426,11 +513,14 @@ int main(int argc, char **argv)
4b6aa8
         .ur_ssl_verify = true,
4b6aa8
         .ur_client_cert = NULL,
4b6aa8
         .ur_client_key = NULL,
4b6aa8
+        .ur_http_headers = NULL,
4b6aa8
         {
4b6aa8
             .urp_auth_items = NULL,
4b6aa8
         },
4b6aa8
     };
4b6aa8
 
4b6aa8
+    config.ur_http_headers = new_map_string();
4b6aa8
+
4b6aa8
     enum {
4b6aa8
         OPT_v = 1 << 0,
4b6aa8
         OPT_d = 1 << 1,
4b6aa8
@@ -677,6 +767,8 @@ finalize:
4b6aa8
     if (config.ur_prefs.urp_auth_items != auth_items)
4b6aa8
         g_list_free_full(config.ur_prefs.urp_auth_items, free);
4b6aa8
 
4b6aa8
+    free_map_string(config.ur_http_headers);
4b6aa8
+
4b6aa8
     free_map_string(settings);
4b6aa8
     free(config.ur_client_cert);
4b6aa8
     free(config.ur_client_key);
4b6aa8
diff --git a/src/plugins/ureport.conf b/src/plugins/ureport.conf
4b6aa8
index 8abeb26..fc0dc21 100644
4b6aa8
--- a/src/plugins/ureport.conf
4b6aa8
+++ b/src/plugins/ureport.conf
4b6aa8
@@ -19,7 +19,9 @@ AuthDataItems = hostname, machineid
4b6aa8
 # None (default):
4b6aa8
 # SSLClientAuth =
4b6aa8
 # Using RH subscription management certificate:
4b6aa8
-SSLClientAuth = rhsm
4b6aa8
+# SSLClientAuth = rhsm
4b6aa8
+# Using RH subscription management entitlement certificate:
4b6aa8
+# SSLClientAuth = rhsm-entitlement
4b6aa8
 # Using Puppet certificate:
4b6aa8
 # SSLClientAuth = puppet
4b6aa8
 # Using custom certificate:
4b6aa8
-- 
4b6aa8
1.8.3.1
4b6aa8