[network-manager-openvpn: 1/7] connection: add support for verify-x509-name property



commit b51b3562ce079cc0be426e968fe1c90faadc0efd
Author: Daniel Miranda <danielkza2 gmail com>
Date:   Mon Sep 5 03:00:54 2016 -0300

    connection: add support for verify-x509-name property
    
    The verify-x509-name option deprecates the tls-remote option starting
    with OpenVPN 2.3. Add support for it in the connection properties, as it
    is an important security feature for avoiding man-in-the-middle attacks.
    
    The connection property is stored as `{type}:{value}`, with type being
    one of (name, name-prefix, subject), and value a comma-separated
    sequence of `key=value` comparisons. It is combined/split-up into the
    two OpenVPN option parameters when import/exporting.

 properties/import-export.c            |   52 ++++++++++++++++++++++++++++++--
 properties/tests/conf/tls.ovpn        |    1 +
 properties/tests/test-import-export.c |    2 +
 shared/nm-service-defines.h           |    6 ++++
 shared/utils.h                        |    1 +
 src/nm-openvpn-service.c              |   40 +++++++++++++++++++++----
 6 files changed, 92 insertions(+), 10 deletions(-)
---
diff --git a/properties/import-export.c b/properties/import-export.c
index 235f088..ea9406a 100644
--- a/properties/import-export.c
+++ b/properties/import-export.c
@@ -1251,6 +1251,32 @@ do_import (const char *path, const char *contents, gsize contents_len, GError **
                        continue;
                }
 
+               if (NM_IN_STRSET (params[0], NMV_OVPN_TAG_VERIFY_X509_NAME)) {
+                       const char *type = "subject";
+                       gs_free char *item = NULL;
+
+                       if (!args_params_check_nargs_minmax (params, 1, 2, &line_error))
+                               goto handle_line_error;
+                       if (!args_params_check_arg_utf8 (params, 1, NULL, &line_error))
+                               goto handle_line_error;
+
+                       if (params[2]) {
+                               if (!NM_IN_STRSET (params[2],
+                                                  NM_OPENVPN_VERIFY_X509_NAME_TYPE_SUBJECT,
+                                                  NM_OPENVPN_VERIFY_X509_NAME_TYPE_NAME,
+                                                  NM_OPENVPN_VERIFY_X509_NAME_TYPE_NAME_PREFIX)) {
+                                       line_error = g_strdup_printf (_("Invalid verify-x509-name type: %s"), 
params[2]);
+                                       goto handle_line_error;
+                               }
+
+                               type = params[2];
+                       }
+
+                       item = g_strdup_printf ("%s:%s", type, params[1]);
+                       setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_VERIFY_X509_NAME, item);
+                       continue;
+               }
+
                if (NM_IN_STRSET (params[0], NMV_OVPN_TAG_REMOTE_CERT_TLS)) {
                        if (!args_params_check_nargs_n (params, 1, &line_error))
                                goto handle_line_error;
@@ -1891,17 +1917,35 @@ do_export_create (NMConnection *connection, const char *path, GError **error)
        if (NM_IN_STRSET (connection_type,
                          NM_OPENVPN_CONTYPE_TLS,
                          NM_OPENVPN_CONTYPE_PASSWORD_TLS)) {
-               args_write_line_setting_value (f, NMV_OVPN_TAG_TLS_REMOTE, s_vpn, NM_OPENVPN_KEY_TLS_REMOTE);
+               const char *x509_name, *ta_key;
+
                args_write_line_setting_value (f, NMV_OVPN_TAG_REMOTE_CERT_TLS, s_vpn, 
NM_OPENVPN_KEY_REMOTE_CERT_TLS);
                args_write_line_setting_value (f, NMV_OVPN_TAG_NS_CERT_TYPE, s_vpn, 
NM_OPENVPN_KEY_NS_CERT_TYPE);
+               args_write_line_setting_value (f, NMV_OVPN_TAG_TLS_REMOTE, s_vpn, NM_OPENVPN_KEY_TLS_REMOTE);
 
-               value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_TA);
-               if (_arg_is_set (value)) {
+               x509_name =  nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_VERIFY_X509_NAME);
+               if (_arg_is_set (x509_name)) {
+                       const char *name;
+                       gs_free char *type = NULL;
+
+                       name = strchr (x509_name, ':');
+                       if (name) {
+                               type = g_strndup (x509_name, name - x509_name);
+                               name++;
+                       } else {
+                               name = x509_name;
+                       }
+
+                       args_write_line (f, NMV_OVPN_TAG_VERIFY_X509_NAME, name, type);
+               }
+
+               ta_key = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_TA);
+               if (_arg_is_set (ta_key)) {
                        gs_free char *s_free = NULL;
 
                        args_write_line (f,
                                         NMV_OVPN_TAG_TLS_AUTH,
-                                        nmv_utils_str_utf8safe_unescape_c (value, &s_free),
+                                        nmv_utils_str_utf8safe_unescape_c (ta_key, &s_free),
                                         _arg_is_set (nm_setting_vpn_get_data_item (s_vpn, 
NM_OPENVPN_KEY_TA_DIR)));
                }
        }
diff --git a/properties/tests/conf/tls.ovpn b/properties/tests/conf/tls.ovpn
index f79bb5e..f1be325 100644
--- a/properties/tests/conf/tls.ovpn
+++ b/properties/tests/conf/tls.ovpn
@@ -19,6 +19,7 @@ key keys/clee.key
 tls-auth keys/46.key 1
 remote-cert-tls server
 tls-remote "/CN=myvpn.company.com"
+verify-x509-name "C=US, L=Cambridge, CN=GNOME, emailAddress=networkmanager-list gnome org" subject
 
 comp-lzo
 verb 3
diff --git a/properties/tests/test-import-export.c b/properties/tests/test-import-export.c
index a78d2d2..6463b10 100644
--- a/properties/tests/test-import-export.c
+++ b/properties/tests/test-import-export.c
@@ -244,6 +244,8 @@ test_tls_import (void)
        _check_item (s_vpn, NM_OPENVPN_KEY_REMOTE_IP, NULL);
        _check_item (s_vpn, NM_OPENVPN_KEY_AUTH, NULL);
        _check_item (s_vpn, NM_OPENVPN_KEY_TLS_REMOTE, "/CN=myvpn.company.com");
+       _check_item (s_vpn, NM_OPENVPN_KEY_VERIFY_X509_NAME,
+                    "subject:C=US, L=Cambridge, CN=GNOME, emailAddress=networkmanager-list gnome org");
        _check_item (s_vpn, NM_OPENVPN_KEY_REMOTE_CERT_TLS, "server");
 
        expected_path = g_strdup_printf ("%s/keys/mg8.ca", SRCDIR);
diff --git a/shared/nm-service-defines.h b/shared/nm-service-defines.h
index 906fde5..a70201b 100644
--- a/shared/nm-service-defines.h
+++ b/shared/nm-service-defines.h
@@ -66,6 +66,7 @@
 #define NM_OPENVPN_KEY_TUN_IPV6 "tun-ipv6"
 #define NM_OPENVPN_KEY_TLS_CIPHER "tls-cipher"
 #define NM_OPENVPN_KEY_TLS_REMOTE "tls-remote"
+#define NM_OPENVPN_KEY_VERIFY_X509_NAME "verify-x509-name"
 #define NM_OPENVPN_KEY_REMOTE_CERT_TLS "remote-cert-tls"
 #define NM_OPENVPN_KEY_MAX_ROUTES "max-routes"
 
@@ -102,6 +103,11 @@
 #define NM_OPENVPN_NS_CERT_TYPE_CLIENT "client"
 #define NM_OPENVPN_NS_CERT_TYPE_SERVER "server"
 
+/* possible types for verify-x509-name */
+#define NM_OPENVPN_VERIFY_X509_NAME_TYPE_SUBJECT     "subject"
+#define NM_OPENVPN_VERIFY_X509_NAME_TYPE_NAME        "name"
+#define NM_OPENVPN_VERIFY_X509_NAME_TYPE_NAME_PREFIX "name-prefix"
+
 /* User name and group to run nm-openvpn-service under */
 #define NM_OPENVPN_USER   "nm-openvpn"
 #define NM_OPENVPN_GROUP  "nm-openvpn"
diff --git a/shared/utils.h b/shared/utils.h
index 71038b9..5a1323e 100644
--- a/shared/utils.h
+++ b/shared/utils.h
@@ -72,6 +72,7 @@
 #define NMV_OVPN_TAG_TUN_MTU            "tun-mtu"
 #define NMV_OVPN_TAG_TUN_IPV6           "tun-ipv6"
 #define NMV_OVPN_TAG_USER               "user"
+#define NMV_OVPN_TAG_VERIFY_X509_NAME   "verify-x509-name"
 
 gboolean is_pkcs12 (const char *filepath);
 
diff --git a/src/nm-openvpn-service.c b/src/nm-openvpn-service.c
index 6f24985..d2b2075 100644
--- a/src/nm-openvpn-service.c
+++ b/src/nm-openvpn-service.c
@@ -142,6 +142,7 @@ static ValidProperty valid_properties[] = {
        { NM_OPENVPN_KEY_TUN_IPV6,             G_TYPE_STRING, 0, 0, FALSE },
        { NM_OPENVPN_KEY_TLS_CIPHER,           G_TYPE_STRING, 0, 0, FALSE },
        { NM_OPENVPN_KEY_TLS_REMOTE,           G_TYPE_STRING, 0, 0, FALSE },
+       { NM_OPENVPN_KEY_VERIFY_X509_NAME,     G_TYPE_STRING, 0, 0, FALSE },
        { NM_OPENVPN_KEY_REMOTE_CERT_TLS,      G_TYPE_STRING, 0, 0, FALSE },
        { NM_OPENVPN_KEY_NS_CERT_TYPE,         G_TYPE_STRING, 0, 0, FALSE },
        { NM_OPENVPN_KEY_TUNNEL_MTU,           G_TYPE_INT, 0, G_MAXINT, FALSE },
@@ -1424,22 +1425,49 @@ nm_openvpn_start_openvpn_binary (NMOpenvpnPlugin *plugin,
        /* tls-remote */
        tmp = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_TLS_REMOTE);
        if (tmp && strlen (tmp)) {
-                add_openvpn_arg (args, "--tls-remote");
-                add_openvpn_arg (args, tmp);
+               add_openvpn_arg (args, "--tls-remote");
+               add_openvpn_arg (args, tmp);
+       }
+
+       /* verify-x509-name */
+       tmp = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_VERIFY_X509_NAME);
+       if (tmp && strlen (tmp)) {
+               const char *name;
+               gs_free char *type = NULL;
+
+               name = strchr (tmp, ':');
+               if (name) {
+                       type = g_strndup (tmp, name - tmp);
+                       name++;
+               } else {
+                       name = tmp;
+               }
+
+               if (!name[0] || !g_utf8_validate(name, -1, NULL)) {
+                       g_set_error (error, NM_VPN_PLUGIN_ERROR,
+                                    NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
+                                    _("Invalid verify-x509-name."));
+                       free_openvpn_args (args);
+                       return FALSE;
+               }
+
+               add_openvpn_arg (args, "--verify-x509-name");
+               add_openvpn_arg (args, name);
+               add_openvpn_arg (args, type ?: "subject");
        }
 
        /* remote-cert-tls */
        tmp = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_REMOTE_CERT_TLS);
        if (tmp && strlen (tmp)) {
-                add_openvpn_arg (args, "--remote-cert-tls");
-                add_openvpn_arg (args, tmp);
+               add_openvpn_arg (args, "--remote-cert-tls");
+               add_openvpn_arg (args, tmp);
        }
 
        /* ns-cert-type */
        tmp = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_NS_CERT_TYPE);
        if (tmp && tmp[0]) {
-                add_openvpn_arg (args, "--ns-cert-type");
-                add_openvpn_arg (args, tmp);
+               add_openvpn_arg (args, "--ns-cert-type");
+               add_openvpn_arg (args, tmp);
        }
 
        /* Reneg seconds */


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