[network-manager-openvpn/nm-1-0] import: allow importing configurations with inline certificates (rh #1157817)



commit dcf7f4d956cb13379d813c4911d1f972b27f5193
Author: Jiří Klimeš <jklimes redhat com>
Date:   Thu Oct 22 10:07:08 2015 +0100

    import: allow importing configurations with inline certificates (rh #1157817)
    
    Configuration files for openvpn can contain inline files (certificates).
    http://sourceforge.net/p/openvpn/openvpn/ci/0979ec7e9109da95ad56e9365a89701fee11c72c
    http://sourceforge.net/p/openvpn/openvpn/ci/d40f2b204b78ace5c2c9c3007887571ca5a2ec11
    
    Let's support inline certificates while importing openvpn configuration.
    
    Example config:
    https://www.frootvpn.com/files/frootvpn.ovpn
    
    https://bugzilla.redhat.com/show_bug.cgi?id=1157817
    
    (cherry picked from commit 4a9d93a0c8c5ae7d7367ab6f721028593d8f77e0)

 properties/import-export.c |  110 +++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 109 insertions(+), 1 deletions(-)
---
diff --git a/properties/import-export.c b/properties/import-export.c
index 6b1dad7..451f475 100644
--- a/properties/import-export.c
+++ b/properties/import-export.c
@@ -47,7 +47,11 @@
 #define AUTH_TAG "auth "
 #define AUTH_USER_PASS_TAG "auth-user-pass"
 #define CA_TAG "ca "
+#define CA_BLOB_START_TAG "<ca>"
+#define CA_BLOB_END_TAG "</ca>"
 #define CERT_TAG "cert "
+#define CERT_BLOB_START_TAG "<cert>"
+#define CERT_BLOB_END_TAG "</cert>"
 #define CIPHER_TAG "cipher "
 #define KEYSIZE_TAG "keysize "
 #define CLIENT_TAG "client"
@@ -57,6 +61,8 @@
 #define FRAGMENT_TAG "fragment "
 #define IFCONFIG_TAG "ifconfig "
 #define KEY_TAG "key "
+#define KEY_BLOB_START_TAG "<key>"
+#define KEY_BLOB_END_TAG "</key>"
 #define MSSFIX_TAG "mssfix"
 #define PKCS12_TAG "pkcs12 "
 #define PORT_TAG "port "
@@ -156,6 +162,99 @@ handle_path_item (const char *line,
        return TRUE;
 }
 
+#define CERT_BEGIN  "-----BEGIN CERTIFICATE-----"
+#define CERT_END    "-----END CERTIFICATE-----"
+#define PRIV_KEY_BEGIN  "-----BEGIN PRIVATE KEY-----"
+#define PRIV_KEY_END    "-----END PRIVATE KEY-----"
+
+static gboolean
+handle_blob_item (const char ***line,
+                  const char *key,
+                  NMSettingVPN *s_vpn,
+                  const char *name,
+                  GError **error)
+{
+       gboolean success = FALSE;
+       const char *blob_mark_start, *blob_mark_end;
+       const char *start_tag, *end_tag;
+       char *filename = NULL;
+       char *dirname = NULL;
+       char *path = NULL;
+       GString *in_file = NULL;
+       const char **p;
+
+       if (!strcmp (key, NM_OPENVPN_KEY_CA)) {
+               start_tag = CA_BLOB_START_TAG;
+               end_tag = CA_BLOB_END_TAG;
+               blob_mark_start = CERT_BEGIN;
+               blob_mark_end = CERT_END;
+       } else if (!strcmp (key, NM_OPENVPN_KEY_CERT)) {
+               start_tag = CERT_BLOB_START_TAG;
+               end_tag = CERT_BLOB_END_TAG;
+               blob_mark_start = CERT_BEGIN;
+               blob_mark_end = CERT_END;
+       } else if (!strcmp (key, NM_OPENVPN_KEY_KEY)) {
+               start_tag = KEY_BLOB_START_TAG;
+               end_tag = KEY_BLOB_END_TAG;
+               blob_mark_start = PRIV_KEY_BEGIN;
+               blob_mark_end = PRIV_KEY_END;
+       } else
+               g_return_val_if_reached (FALSE);
+
+       p = *line;
+       if (strncmp (*p, start_tag, strlen (start_tag)))
+               goto finish;
+       p++;
+       if (strcmp (*p, blob_mark_start))
+               goto finish;
+       p++;
+
+       in_file = g_string_new (NULL);
+
+       while (*p && strcmp (*p, blob_mark_end)) {
+               g_string_append (in_file, *p);
+               g_string_append_c (in_file, '\n');
+               p++;
+       }
+       if (!*p || strncmp (*(p+1), end_tag, strlen (end_tag)))
+               goto finish;
+       p++;
+
+       /* Construct file name to write the data in */
+       filename = g_strdup_printf ("%s-%s.pem", name, key);
+       dirname = g_build_filename (g_get_home_dir (), ".cert", NULL);
+       path = g_build_filename (dirname, filename, NULL);
+
+       /* Check that dirname exists and is a directory, otherwise create it */
+       if (!g_file_test (dirname, G_FILE_TEST_IS_DIR)) {
+               if (!g_file_test (dirname, G_FILE_TEST_EXISTS)) {
+                       if (mkdir (dirname, 0755) < 0)
+                               goto finish;  /* dirname could not be created */
+               } else
+                       goto finish;  /* dirname is not a directory */
+       }
+
+       /* Write the new file */
+       g_string_prepend_c (in_file, '\n');
+       g_string_prepend (in_file, blob_mark_start);
+       g_string_append_printf (in_file, "%s", blob_mark_end);
+       success = g_file_set_contents (path, in_file->str, -1, error);
+       if (!success)
+               goto finish;
+
+       nm_setting_vpn_add_data_item (s_vpn, key, path);
+
+finish:
+       line = &p;
+       g_free (filename);
+       g_free (dirname);
+       g_free (path);
+       if (in_file)
+               g_string_free (in_file, TRUE);
+       return success;
+
+}
+
 static char **
 get_args (const char *line, int *nitems)
 {
@@ -305,7 +404,6 @@ do_import (const char *path, char **lines, GError **error)
        if (last_dot)
                *last_dot = '\0';
        g_object_set (s_con, NM_SETTING_CONNECTION_ID, basename, NULL);
-       g_free (basename);
 
        for (line = lines; *line; line++) {
                char *comment, **items = NULL, *leftover = NULL;
@@ -574,6 +672,15 @@ do_import (const char *path, char **lines, GError **error)
                if (handle_path_item (*line, KEY_TAG, NM_OPENVPN_KEY_KEY, s_vpn, default_path, NULL))
                        continue;
 
+               if (handle_blob_item ((const char ***)&line, NM_OPENVPN_KEY_CA, s_vpn, basename, NULL))
+                       continue;
+
+               if (handle_blob_item ((const char ***)&line, NM_OPENVPN_KEY_CERT, s_vpn, basename, NULL))
+                       continue;
+
+               if (handle_blob_item ((const char ***)&line, NM_OPENVPN_KEY_KEY, s_vpn, basename, NULL))
+                       continue;
+
                if (handle_path_item (*line, SECRET_TAG, NM_OPENVPN_KEY_STATIC_KEY,
                                      s_vpn, default_path, &leftover)) {
                        handle_direction ("secret",
@@ -744,6 +851,7 @@ do_import (const char *path, char **lines, GError **error)
        }
 
        g_free (default_path);
+       g_free (basename);
 
        if (connection)
                nm_connection_add_setting (connection, NM_SETTING (s_vpn));


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]