[network-manager-openvpn: 2/7] properties: add support for verify-x509-name



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 &lt;file&gt; [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">&lt;i&gt;Connect only to servers 
whose certificate matches the given subject.
-Example: /CN=myvpn.company.com&lt;/i&gt;</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&lt;/i&gt;</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 &lt;file&gt; [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]