[network-manager-openvpn: 2/7] properties: add support for verify-x509-name
- From: Thomas Haller <thaller src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [network-manager-openvpn: 2/7] properties: add support for verify-x509-name
- Date: Thu, 8 Sep 2016 10:33:59 +0000 (UTC)
commit b6385dfae733039705281f351664b55a487ad2f4
Author: Daniel Miranda <danielkza2 gmail com>
Date: Mon Sep 5 05:22:44 2016 -0300
properties: add support for verify-x509-name
Expose the verify-x590-name option in the editor UI by reusing the
tls-remote subject entry, and adding a combo box for selecting a
verification mode.
Selectable modes map to their respective verify-x509-name types
('subject', 'name' or 'name-prefix'), except for 'legacy', which sets
tls-remote and omits verify-x509-name, and 'none', which omits both.
Descriptions and tooltips are updated to attempt to describe the
different modes in a straightforward way, but their actual operation is
unfortunately not very simple.
Updates to translations will be necessary later.
properties/auth-helpers.c | 176 +++++++++++++++++++++++++++++++++++++--
properties/nm-openvpn-dialog.ui | 83 +++++++++++++------
2 files changed, 225 insertions(+), 34 deletions(-)
---
diff --git a/properties/auth-helpers.c b/properties/auth-helpers.c
index 60f0925..8a62d5e 100644
--- a/properties/auth-helpers.c
+++ b/properties/auth-helpers.c
@@ -69,6 +69,25 @@ setup_secret_widget (GtkBuilder *builder,
return widget;
}
+/* From gnome-control-center/panels/network/connection-editor/ui-helpers.c */
+
+static void
+widget_set_error (GtkWidget *widget)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ gtk_style_context_add_class (gtk_widget_get_style_context (widget), "error");
+}
+
+static void
+widget_unset_error (GtkWidget *widget)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ gtk_style_context_remove_class (gtk_widget_get_style_context (widget), "error");
+}
+
+
typedef struct {
GtkWidget *widget1;
GtkWidget *widget2;
@@ -889,6 +908,7 @@ static const char *advanced_keys[] = {
NM_OPENVPN_KEY_TA,
NM_OPENVPN_KEY_RENEG_SECONDS,
NM_OPENVPN_KEY_TLS_REMOTE,
+ NM_OPENVPN_KEY_VERIFY_X509_NAME,
NM_OPENVPN_KEY_REMOTE_RANDOM,
NM_OPENVPN_KEY_TUN_IPV6,
NM_OPENVPN_KEY_REMOTE_CERT_TLS,
@@ -1139,6 +1159,126 @@ populate_hmacauth_combo (GtkComboBox *box, const char *hmacauth)
g_object_unref (store);
}
+#define TLS_REMOTE_MODE_NONE "none"
+#define TLS_REMOTE_MODE_SUBJECT NM_OPENVPN_VERIFY_X509_NAME_TYPE_SUBJECT
+#define TLS_REMOTE_MODE_NAME NM_OPENVPN_VERIFY_X509_NAME_TYPE_NAME
+#define TLS_REMOTE_MODE_NAME_PREFIX NM_OPENVPN_VERIFY_X509_NAME_TYPE_NAME_PREFIX
+#define TLS_REMOTE_MODE_LEGACY "legacy"
+
+#define TLS_REMOTE_MODE_COL_NAME 0
+#define TLS_REMOTE_MODE_COL_VALUE 1
+
+static void
+populate_tls_remote_mode_entry_combo (GtkEntry* entry, GtkComboBox *box,
+ const char *tls_remote, const char *x509_name)
+{
+ GtkListStore *store;
+ GtkTreeIter iter;
+ const char *subject_name = NULL;
+
+ 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,
+ TLS_REMOTE_MODE_COL_NAME, _("Don't verify certificate identification"),
+ TLS_REMOTE_MODE_COL_VALUE, TLS_REMOTE_MODE_NONE,
+ -1);
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ TLS_REMOTE_MODE_COL_NAME, _("Verify whole subject exactly"),
+ TLS_REMOTE_MODE_COL_VALUE, TLS_REMOTE_MODE_SUBJECT,
+ -1);
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ TLS_REMOTE_MODE_COL_NAME, _("Verify name exactly"),
+ TLS_REMOTE_MODE_COL_VALUE, TLS_REMOTE_MODE_NAME,
+ -1);
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ TLS_REMOTE_MODE_COL_NAME, _("Verify name by prefix"),
+ TLS_REMOTE_MODE_COL_VALUE, TLS_REMOTE_MODE_NAME_PREFIX,
+ -1);
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ TLS_REMOTE_MODE_COL_NAME, _("Verify subject partially (legacy mode)"),
+ TLS_REMOTE_MODE_COL_VALUE, TLS_REMOTE_MODE_LEGACY,
+ -1);
+
+ if (x509_name && strlen (x509_name)) {
+ if (g_str_has_prefix (x509_name, "name:"))
+ gtk_combo_box_set_active (box, 2);
+ else if (g_str_has_prefix (x509_name, "name-prefix:"))
+ gtk_combo_box_set_active (box, 3);
+ else
+ gtk_combo_box_set_active (box, 1);
+
+ subject_name = strchr (x509_name, ':');
+ if (subject_name)
+ subject_name++;
+ else
+ subject_name = x509_name;
+ } else if (tls_remote && strlen (tls_remote)) {
+ gtk_combo_box_set_active (box, 4);
+
+ subject_name = tls_remote;
+ } else {
+ gtk_combo_box_set_active (box, 0);
+
+ subject_name = "";
+ }
+
+ gtk_entry_set_text (entry, subject_name);
+
+ g_object_unref (store);
+}
+
+static void
+tls_remote_changed (GtkWidget *widget, gpointer user_data)
+{
+ GtkBuilder *builder = (GtkBuilder *) user_data;
+ GtkWidget *entry, *combo, *ok_button;
+ GtkTreeIter iter;
+ gboolean entry_enabled = TRUE, entry_has_error = FALSE;
+
+ entry = GTK_WIDGET (gtk_builder_get_object (builder, "tls_remote_entry"));
+ combo = GTK_WIDGET (gtk_builder_get_object (builder, "tls_remote_mode_combo"));
+ ok_button = GTK_WIDGET (gtk_builder_get_object (builder, "ok_button"));
+
+ if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter)) {
+ gs_free char *tls_remote_mode = NULL;
+ GtkTreeModel *combo_model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
+
+ gtk_tree_model_get (combo_model, &iter, TLS_REMOTE_MODE_COL_VALUE, &tls_remote_mode, -1);
+ g_return_if_fail (tls_remote_mode);
+
+ /* If a mode of 'none' is selected, disable the subject entry control.
+ Otherwise, enable the entry, and set up it's error state based on
+ whether it is empty or not (it should not be). */
+ if (!strcmp (tls_remote_mode, TLS_REMOTE_MODE_NONE)) {
+ entry_enabled = FALSE;
+ } else {
+ const char *subject = gtk_entry_get_text (GTK_ENTRY (entry));
+
+ entry_enabled = TRUE;
+ entry_has_error = !subject || !subject[0];
+ }
+ }
+
+ gtk_widget_set_sensitive (entry, entry_enabled);
+ if(entry_has_error) {
+ widget_set_error (entry);
+ gtk_widget_set_sensitive (ok_button, FALSE);
+ } else {
+ widget_unset_error (entry);
+ gtk_widget_set_sensitive (ok_button, TRUE);
+ }
+}
+
static void
remote_tls_cert_toggled_cb (GtkWidget *widget, gpointer user_data)
{
@@ -1669,9 +1809,14 @@ advanced_dialog_new (GHashTable *hash, const char *contype)
value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_AUTH);
populate_hmacauth_combo (GTK_COMBO_BOX (widget), value);
- widget = GTK_WIDGET (gtk_builder_get_object (builder, "tls_remote_entry"));
- value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_TLS_REMOTE);
- gtk_entry_set_text (GTK_ENTRY (widget), value ?: "");
+ entry = GTK_WIDGET (gtk_builder_get_object (builder, "tls_remote_entry"));
+ combo = GTK_WIDGET (gtk_builder_get_object (builder, "tls_remote_mode_combo"));
+ populate_tls_remote_mode_entry_combo (GTK_ENTRY (entry), GTK_COMBO_BOX (combo),
+ g_hash_table_lookup (hash, NM_OPENVPN_KEY_TLS_REMOTE),
+ g_hash_table_lookup (hash, NM_OPENVPN_KEY_VERIFY_X509_NAME));
+ g_signal_connect (G_OBJECT (entry), "changed", G_CALLBACK (tls_remote_changed), builder);
+ g_signal_connect (G_OBJECT (combo), "changed", G_CALLBACK (tls_remote_changed), builder);
+ tls_remote_changed (entry, builder);
widget = GTK_WIDGET (gtk_builder_get_object (builder, "remote_cert_tls_checkbutton"));
value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_REMOTE_CERT_TLS);
@@ -1796,7 +1941,7 @@ GHashTable *
advanced_dialog_new_hash_from_dialog (GtkWidget *dialog, GError **error)
{
GHashTable *hash;
- GtkWidget *widget;
+ GtkWidget *widget, *entry, *combo;
GtkBuilder *builder;
const char *contype = NULL;
const char *value;
@@ -1994,10 +2139,25 @@ advanced_dialog_new_hash_from_dialog (GtkWidget *dialog, GError **error)
|| !strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD_TLS)
|| !strcmp (contype, NM_OPENVPN_CONTYPE_PASSWORD)) {
- widget = GTK_WIDGET (gtk_builder_get_object (builder, "tls_remote_entry"));
- value = gtk_entry_get_text (GTK_ENTRY(widget));
- if (value && strlen (value))
- g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_TLS_REMOTE), g_strdup (value));
+ entry = GTK_WIDGET (gtk_builder_get_object (builder, "tls_remote_entry"));
+ value = gtk_entry_get_text (GTK_ENTRY (entry));
+
+ combo = GTK_WIDGET (gtk_builder_get_object (builder, "tls_remote_mode_combo"));
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
+
+ if (value && strlen (value) && gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter)) {
+ gs_free char *tls_remote_mode = NULL;
+ gtk_tree_model_get (model, &iter, TLS_REMOTE_MODE_COL_VALUE, &tls_remote_mode, -1);
+
+ if (!g_strcmp0 (tls_remote_mode, TLS_REMOTE_MODE_NONE)) {
+ // pass
+ } else if (!g_strcmp0 (tls_remote_mode, TLS_REMOTE_MODE_LEGACY)) {
+ g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_TLS_REMOTE),
g_strdup(value));
+ } else {
+ char *x509_name = g_strdup_printf ("%s:%s", tls_remote_mode, value);
+ g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_VERIFY_X509_NAME),
x509_name);
+ }
+ }
widget = GTK_WIDGET (gtk_builder_get_object (builder, "remote_cert_tls_checkbutton"));
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
diff --git a/properties/nm-openvpn-dialog.ui b/properties/nm-openvpn-dialog.ui
index d0007c1..d65d0d0 100644
--- a/properties/nm-openvpn-dialog.ui
+++ b/properties/nm-openvpn-dialog.ui
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.19.0 -->
+<!-- Generated with glade 3.20.0 -->
<interface>
<requires lib="gtk+" version="3.4"/>
<object class="GtkAdjustment" id="adjustment1">
@@ -1064,6 +1064,17 @@ config: static <file> [direction]</property>
</row>
</data>
</object>
+ <object class="GtkListStore" id="model9">
+ <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>
@@ -1846,6 +1857,8 @@ config: auth</property>
<object class="GtkGrid" id="table10">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="valign">start</property>
+ <property name="hexpand">True</property>
<property name="row_spacing">6</property>
<property name="column_spacing">12</property>
<child>
@@ -1855,32 +1868,22 @@ config: auth</property>
<property name="label" translatable="yes">_Subject Match:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">tls_remote_entry</property>
- <property name="xalign">0</property>
+ <property name="xalign">1</property>
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">0</property>
+ <property name="top_attach">1</property>
</packing>
</child>
<child>
- <object class="GtkAlignment" id="alignment26">
+ <object class="GtkEntry" id="tls_remote_entry">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="xalign">0</property>
- <property name="xscale">0</property>
- <child>
- <object class="GtkLabel" id="label33">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="valign">start</property>
- <property name="label" translatable="yes"><i>Connect only to servers
whose certificate matches the given subject.
-Example: /CN=myvpn.company.com</i></property>
- <property name="use_markup">True</property>
- <property name="wrap">True</property>
- <property name="width_chars">30</property>
- <property name="xalign">0</property>
- </object>
- </child>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="tooltip_text" translatable="yes">Subject or Common Name to
verify server certificate information against.
+
+config: verify-x509-name subject-or-name [mode]
+config (legacy modew): tls-remote subject-or-name</property>
</object>
<packing>
<property name="left_attach">1</property>
@@ -1888,11 +1891,39 @@ Example: /CN=myvpn.company.com</i></property>
</packing>
</child>
<child>
- <object class="GtkEntry" id="tls_remote_entry">
+ <object class="GtkLabel" id="tls_remote_mode_label">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="tooltip_text" translatable="yes">Accept connections only from a
host with X509 name or common name equal to the specified one.
-config: tls-remote</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Server _Certificate Check:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">tls_remote_mode_combo</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="tls_remote_mode_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="tooltip_text" translatable="yes">Verify server certificate
identification.
+
+When enabled, connection will only succeed if the server certificate matches some expected properties.
+Matching can either apply to the whole certificate subject (all the fields),
+or just the Common Name (CN field).
+
+config: verify-x509-name subject-or-name [mode]
+config (legacy mode): tls-remote subject-or-name</property>
+ <property name="model">model9</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer12"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
</object>
<packing>
<property name="left_attach">1</property>
@@ -2082,7 +2113,7 @@ config: ns-cert-type client|server</property>
<property name="label" translatable="yes">Key _Direction:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">direction_combo</property>
- <property name="xalign">0</property>
+ <property name="xalign">1</property>
</object>
<packing>
<property name="left_attach">0</property>
@@ -2129,7 +2160,7 @@ config: tls-auth <file> [direction]</property>
<property name="label" translatable="yes">Key _File:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">tls_auth_chooser</property>
- <property name="xalign">0</property>
+ <property name="xalign">1</property>
</object>
<packing>
<property name="left_attach">0</property>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]