[network-manager-openvpn/bgo685790] core/ui: add 'remote-cert-tls' option (bgo #685790)



commit 93ba531cd375cd35c8e7942a97989f5223971846
Author: JiÅÃ KlimeÅ <jklimes redhat com>
Date:   Fri Nov 2 13:17:38 2012 +0100

    core/ui: add 'remote-cert-tls' option (bgo #685790)
    
    We already support 'tls-remote', i.e. verifying server's X509/common name.
    However, it make sense to support 'remote-cert-tls' as well.  It's another
    important security option to protect against MITM attacks. For more info see
    http://openvpn.net/index.php/open-source/documentation/howto.html#mitm

 properties/auth-helpers.c             |   74 ++++++++++++++++++++++++++++
 properties/import-export.c            |   23 +++++++++
 properties/nm-openvpn-dialog.ui       |   87 ++++++++++++++++++++++++++++++++-
 properties/tests/conf/tls.ovpn        |    1 +
 properties/tests/test-import-export.c |    1 +
 src/nm-openvpn-service.c              |   10 +++-
 src/nm-openvpn-service.h              |    5 ++
 7 files changed, 199 insertions(+), 2 deletions(-)
---
diff --git a/properties/auth-helpers.c b/properties/auth-helpers.c
index 8ced138..2aef793 100644
--- a/properties/auth-helpers.c
+++ b/properties/auth-helpers.c
@@ -947,6 +947,7 @@ static const char *advanced_keys[] = {
 	NM_OPENVPN_KEY_RENEG_SECONDS,
 	NM_OPENVPN_KEY_TLS_REMOTE,
 	NM_OPENVPN_KEY_REMOTE_RANDOM,
+	NM_OPENVPN_KEY_REMOTE_CERT_TLS,
 	NULL
 };
 
@@ -1205,6 +1206,53 @@ populate_hmacauth_combo (GtkComboBox *box, const char *hmacauth)
 }
 
 static void
+remote_tls_cert_toggled_cb (GtkWidget *widget, gpointer user_data)
+{
+	GtkBuilder *builder = (GtkBuilder *) user_data;
+	gboolean use_remote_cert_tls = FALSE;
+
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, "remote_cert_tls_checkbutton"));
+	use_remote_cert_tls = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, "remote_cert_tls_label"));
+	gtk_widget_set_sensitive (widget, use_remote_cert_tls);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, "remote_cert_tls_combo"));
+	gtk_widget_set_sensitive (widget, use_remote_cert_tls);
+}
+
+#define REMOTE_CERT_COL_NAME 0
+#define REMOTE_CERT_COL_VALUE 1
+
+static void
+populate_remote_cert_tls_combo (GtkComboBox *box, const char *remote_cert)
+{
+	GtkListStore *store;
+	GtkTreeIter iter;
+
+	store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
+	gtk_combo_box_set_model (box, GTK_TREE_MODEL (store));
+
+	gtk_list_store_append (store, &iter);
+	gtk_list_store_set (store, &iter,
+	                    REMOTE_CERT_COL_NAME, _("Server"),
+	                    REMOTE_CERT_COL_VALUE, NM_OPENVPN_REM_CERT_TLS_SERVER,
+	                    -1);
+	gtk_list_store_append (store, &iter);
+	gtk_list_store_set (store, &iter,
+	                    REMOTE_CERT_COL_NAME, _("Client"),
+	                    REMOTE_CERT_COL_VALUE, NM_OPENVPN_REM_CERT_TLS_CLIENT,
+	                    -1);
+
+	if (g_strcmp0 (remote_cert, NM_OPENVPN_REM_CERT_TLS_CLIENT) == 0)
+		gtk_combo_box_set_active (box, 1);
+	else
+		gtk_combo_box_set_active (box, 0);
+
+	g_object_unref (store);
+}
+
+static void
 tls_auth_toggled_cb (GtkWidget *widget, gpointer user_data)
 {
 	GtkBuilder *builder = (GtkBuilder *) user_data;
@@ -1550,6 +1598,17 @@ advanced_dialog_new (GHashTable *hash, const char *contype)
 		gtk_entry_set_text (GTK_ENTRY(widget), value);
 	}
 
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, "remote_cert_tls_checkbutton"));
+	value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_REMOTE_CERT_TLS);
+	if (value && strlen (value))
+		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
+	g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (remote_tls_cert_toggled_cb), builder);
+	remote_tls_cert_toggled_cb (widget, builder);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, "remote_cert_tls_combo"));
+	value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_REMOTE_CERT_TLS);
+	populate_remote_cert_tls_combo (GTK_COMBO_BOX (widget), value);
+
 	if (   !strcmp (contype, NM_OPENVPN_CONTYPE_TLS)
 	    || !strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD_TLS)
 	    || !strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD)) {
@@ -1777,6 +1836,21 @@ advanced_dialog_new_hash_from_dialog (GtkWidget *dialog, GError **error)
 		if (value && strlen (value))
 			g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_TLS_REMOTE), g_strdup (value));
 
+		widget = GTK_WIDGET (gtk_builder_get_object (builder, "remote_cert_tls_checkbutton"));
+		if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
+			widget = GTK_WIDGET (gtk_builder_get_object (builder, "remote_cert_tls_combo"));
+			model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+			if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter)) {
+				char *remote_cert = NULL;
+
+				gtk_tree_model_get (model, &iter, REMOTE_CERT_COL_VALUE, &remote_cert, -1);
+				if (remote_cert)
+					g_hash_table_insert (hash,
+					                     g_strdup (NM_OPENVPN_KEY_REMOTE_CERT_TLS),
+					                     remote_cert);
+			}
+		}
+
 		widget = GTK_WIDGET (gtk_builder_get_object (builder, "tls_auth_checkbutton"));
 		if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
 			char *filename;
diff --git a/properties/import-export.c b/properties/import-export.c
index 8a451cf..9fc6e0e 100644
--- a/properties/import-export.c
+++ b/properties/import-export.c
@@ -70,6 +70,7 @@
 #define TLS_AUTH_TAG "tls-auth "
 #define TLS_CLIENT_TAG "tls-client"
 #define TLS_REMOTE_TAG "tls-remote "
+#define REMOTE_CERT_TLS_TAG "remote-cert-tls "
 #define TUNMTU_TAG "tun-mtu "
 
 
@@ -605,6 +606,20 @@ do_import (const char *path, char **lines, GError **error)
 			continue;
 		}
 
+		if (!strncmp (*line, REMOTE_CERT_TLS_TAG, strlen (REMOTE_CERT_TLS_TAG))) {
+			items = get_args (*line + strlen (REMOTE_CERT_TLS_TAG), &nitems);
+			if (nitems == 1) {
+				if (   !strcmp (items[0], NM_OPENVPN_REM_CERT_TLS_CLIENT)
+				    || !strcmp (items[0], NM_OPENVPN_REM_CERT_TLS_SERVER)) {
+					nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_REMOTE_CERT_TLS, items[0]);
+				} else
+					g_warning ("%s: unknown %s option '%s'", __func__, REMOTE_CERT_TLS_TAG, *line);
+			}
+
+			g_strfreev (items);
+			continue;
+		}
+
 		if (!strncmp (*line, IFCONFIG_TAG, strlen (IFCONFIG_TAG))) {
 			items = get_args (*line + strlen (IFCONFIG_TAG), &nitems);
 			if (nitems == 2) {
@@ -726,6 +741,7 @@ do_export (const char *path, NMConnection *connection, GError **error)
 	const char *local_ip = NULL;
 	const char *remote_ip = NULL;
 	const char *tls_remote = NULL;
+	const char *remote_cert_tls = NULL;
 	const char *tls_auth = NULL;
 	const char *tls_auth_dir = NULL;
 	gboolean success = FALSE;
@@ -841,6 +857,10 @@ do_export (const char *path, NMConnection *connection, GError **error)
 	if (value && strlen (value))
 		tls_auth_dir = value;
 
+	value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_REMOTE_CERT_TLS);
+	if (value && strlen (value))
+		remote_cert_tls = value;
+
 	/* Advanced values end */
 
 	fprintf (f, "client\n");
@@ -910,6 +930,9 @@ do_export (const char *path, NMConnection *connection, GError **error)
 		if (tls_remote)
 			fprintf (f,"tls-remote \"%s\"\n", tls_remote);
 
+		if (remote_cert_tls)
+			fprintf (f,"remote-cert-tls %s\n", remote_cert_tls);
+
 		if (tls_auth) {
 			fprintf (f, "tls-auth %s%s%s\n",
 			         tls_auth,
diff --git a/properties/nm-openvpn-dialog.ui b/properties/nm-openvpn-dialog.ui
index 35d905a..6c32e7f 100644
--- a/properties/nm-openvpn-dialog.ui
+++ b/properties/nm-openvpn-dialog.ui
@@ -100,6 +100,17 @@
       </row>
     </data>
   </object>
+  <object class="GtkListStore" id="model7">
+    <columns>
+      <!-- column-name gchararray -->
+      <column type="gchararray"/>
+    </columns>
+    <data>
+      <row>
+        <col id="0" translatable="yes"> </col>
+      </row>
+    </data>
+  </object>
   <object class="GtkDialog" id="openvpn-advanced-dialog">
     <property name="can_focus">False</property>
     <property name="border_width">5</property>
@@ -645,6 +656,80 @@ config: tls-remote</property>
                       </packing>
                     </child>
                     <child>
+                      <object class="GtkTable" id="table12">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="valign">start</property>
+                        <property name="n_rows">2</property>
+                        <property name="n_columns">2</property>
+                        <property name="column_spacing">12</property>
+                        <property name="row_spacing">3</property>
+                        <child>
+                          <object class="GtkCheckButton" id="remote_cert_tls_checkbutton">
+                            <property name="label" translatable="yes">_Verify peer (server) certificate usage signature</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">False</property>
+                            <property name="use_action_appearance">False</property>
+                            <property name="use_underline">True</property>
+                            <property name="draw_indicator">True</property>
+                            <property name="tooltip_text" translatable="yes">Require that peer certificate was signed with an explicit key usage and extended key usage based on RFC3280 TLS rules.</property>
+                          </object>
+                          <packing>
+                            <property name="right_attach">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="remote_cert_tls_label">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">_Remote peer certificate TLS type:</property>
+                            <property name="use_underline">True</property>
+                            <property name="mnemonic_widget">remote_cert_tls_combo</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="right_attach">1</property>
+                            <property name="top_attach">1</property>
+                            <property name="bottom_attach">2</property>
+                            <property name="x_options">GTK_FILL</property>
+                            <property name="x_padding">12</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkComboBox" id="remote_cert_tls_combo">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="model">model7</property>
+                            <property name="tooltip_text" translatable="yes">Require that peer certificate was signed with an explicit key usage and extended key usage based on RFC3280 TLS rules.
+config: remote-cert-tls client|server</property>
+                            <child>
+                              <object class="GtkCellRendererText" id="renderer9"/>
+                              <attributes>
+                                <attribute name="text">0</attribute>
+                              </attributes>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">1</property>
+                            <property name="bottom_attach">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <placeholder/>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
+                        <property name="padding">6</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child>
                       <object class="GtkTable" id="table7">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
@@ -778,7 +863,7 @@ config: tls-auth &lt;file&gt; [direction]</property>
                       <packing>
                         <property name="expand">True</property>
                         <property name="fill">True</property>
-                        <property name="position">1</property>
+                        <property name="position">2</property>
                       </packing>
                     </child>
                   </object>
diff --git a/properties/tests/conf/tls.ovpn b/properties/tests/conf/tls.ovpn
index 2748519..8309c89 100644
--- a/properties/tests/conf/tls.ovpn
+++ b/properties/tests/conf/tls.ovpn
@@ -15,6 +15,7 @@ cert keys/clee.crt
 key keys/clee.key
 
 tls-auth keys/46.key 1
+remote-cert-tls server
 tls-remote "/CN=myvpn.company.com"
 
 comp-lzo
diff --git a/properties/tests/test-import-export.c b/properties/tests/test-import-export.c
index 025b12d..5f0c92e 100644
--- a/properties/tests/test-import-export.c
+++ b/properties/tests/test-import-export.c
@@ -284,6 +284,7 @@ test_tls_import (NMVpnPluginUiInterface *plugin, const char *dir)
 	test_item ("tls-import-data", s_vpn, NM_OPENVPN_KEY_REMOTE_IP, NULL);
 	test_item ("tls-import-data", s_vpn, NM_OPENVPN_KEY_AUTH, NULL);
 	test_item ("tls-import-data", s_vpn, NM_OPENVPN_KEY_TLS_REMOTE, "/CN=myvpn.company.com");
+	test_item ("tls-import-data", s_vpn, NM_OPENVPN_KEY_REMOTE_CERT_TLS, "server");
 
 	expected_path = g_strdup_printf ("%s/keys/mg8.ca", dir);
 	test_item ("tls-import-data", s_vpn, NM_OPENVPN_KEY_CA, expected_path);
diff --git a/src/nm-openvpn-service.c b/src/nm-openvpn-service.c
index 660fd2f..5eaed74 100644
--- a/src/nm-openvpn-service.c
+++ b/src/nm-openvpn-service.c
@@ -119,7 +119,8 @@ static ValidProperty valid_properties[] = {
 	{ NM_OPENVPN_KEY_TA,                   G_TYPE_STRING, 0, 0, FALSE },
 	{ NM_OPENVPN_KEY_TA_DIR,               G_TYPE_INT, 0, 1, FALSE },
 	{ NM_OPENVPN_KEY_TAP_DEV,              G_TYPE_BOOLEAN, 0, 0, FALSE },
-	{ NM_OPENVPN_KEY_TLS_REMOTE,	       G_TYPE_STRING, 0, 0, FALSE },
+	{ NM_OPENVPN_KEY_TLS_REMOTE,           G_TYPE_STRING, 0, 0, FALSE },
+	{ NM_OPENVPN_KEY_REMOTE_CERT_TLS,      G_TYPE_STRING, 0, 0, FALSE },
 	{ NM_OPENVPN_KEY_TUNNEL_MTU,           G_TYPE_INT, 0, G_MAXINT, FALSE },
 	{ NM_OPENVPN_KEY_USERNAME,             G_TYPE_STRING, 0, 0, FALSE },
 	{ NM_OPENVPN_KEY_PASSWORD"-flags",     G_TYPE_STRING, 0, 0, FALSE },
@@ -890,6 +891,13 @@ nm_openvpn_start_openvpn_binary (NMOpenvpnPlugin *plugin,
                 add_openvpn_arg (args, tmp);
 	}
 
+	/* 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);
+	}
+
 	/* Reneg seconds */
 	tmp = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_RENEG_SECONDS);
 	if (tmp && strlen (tmp)) {
diff --git a/src/nm-openvpn-service.h b/src/nm-openvpn-service.h
index 9266a64..a60fa89 100644
--- a/src/nm-openvpn-service.h
+++ b/src/nm-openvpn-service.h
@@ -66,6 +66,7 @@
 #define NM_OPENVPN_KEY_USERNAME "username"
 #define NM_OPENVPN_KEY_TAP_DEV "tap-dev"
 #define NM_OPENVPN_KEY_TLS_REMOTE "tls-remote"
+#define NM_OPENVPN_KEY_REMOTE_CERT_TLS "remote-cert-tls"
 
 #define NM_OPENVPN_KEY_PASSWORD "password"
 #define NM_OPENVPN_KEY_CERTPASS "cert-pass"
@@ -92,6 +93,10 @@
 #define NM_OPENVPN_CONTYPE_PASSWORD     "password"
 #define NM_OPENVPN_CONTYPE_PASSWORD_TLS "password-tls"
 
+/* arguments of "--remote-cert-tls" */
+#define NM_OPENVPN_REM_CERT_TLS_CLIENT "client"
+#define NM_OPENVPN_REM_CERT_TLS_SERVER "server"
+
 typedef struct {
 	NMVPNPlugin parent;
 } NMOpenvpnPlugin;



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