[network-manager-openvpn/jklimes/bgo706775-keysize: 1/2] core/ui: add '--keysize' option to handle non-default key sizes (bgo #706775)



commit 3d10af0947ed6eb02d9812b120a33508d68c7b86
Author: Jiří Klimeš <jklimes redhat com>
Date:   Mon Sep 9 13:20:29 2013 +0200

    core/ui: add '--keysize' option to handle non-default key sizes (bgo #706775)
    
    If openvpn server is configured with a non-default key size, clients have to use
    the same size too. We add an option to use custom key size in GUI and handle that
    in the service and properties code including import/export too.
    However, note that using key sizes different from cipher-specific defaults is
    not recommended. List available ciphers and default key sizes by
    'openvpn --show-ciphers'.
    
    man openvpn: search --keysize
    
    https://bugzilla.gnome.org/show_bug.cgi?id=706775

 properties/auth-helpers.c             |   45 +++++++++++++++++++++++
 properties/import-export.c            |   31 ++++++++++++++++
 properties/nm-openvpn-dialog.ui       |   59 ++++++++++++++++++++++++++++--
 properties/tests/conf/Makefile.am     |    3 +-
 properties/tests/conf/keysize.ovpn    |   20 ++++++++++
 properties/tests/test-import-export.c |   63 +++++++++++++++++++++++++++++++++
 src/nm-openvpn-service.c              |   16 ++++++++
 src/nm-openvpn-service.h              |    1 +
 8 files changed, 233 insertions(+), 5 deletions(-)
---
diff --git a/properties/auth-helpers.c b/properties/auth-helpers.c
index 2aef793..cfc8ec2 100644
--- a/properties/auth-helpers.c
+++ b/properties/auth-helpers.c
@@ -941,6 +941,7 @@ static const char *advanced_keys[] = {
        NM_OPENVPN_KEY_PROXY_RETRY,
        NM_OPENVPN_KEY_HTTP_PROXY_USERNAME,
        NM_OPENVPN_KEY_CIPHER,
+       NM_OPENVPN_KEY_KEYSIZE,
        NM_OPENVPN_KEY_AUTH,
        NM_OPENVPN_KEY_TA_DIR,
        NM_OPENVPN_KEY_TA,
@@ -1029,6 +1030,16 @@ reneg_toggled_cb (GtkWidget *check, gpointer user_data)
        gtk_widget_set_sensitive (widget, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check)));
 }
 
+static void
+keysize_toggled_cb (GtkWidget *check, gpointer user_data)
+{
+       GtkBuilder *builder = (GtkBuilder *) user_data;
+       GtkWidget *widget;
+
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "keysize_spinbutton"));
+       gtk_widget_set_sensitive (widget, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check)));
+}
+
 static const char *
 nm_find_openvpn (void)
 {
@@ -1588,6 +1599,31 @@ advanced_dialog_new (GHashTable *hash, const char *contype)
        value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_CIPHER);
        populate_cipher_combo (GTK_COMBO_BOX (widget), value);
 
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "keysize_checkbutton"));
+       g_assert (widget);
+       g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (keysize_toggled_cb), builder);
+
+       value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_KEYSIZE);
+       if (value && strlen (value)) {
+               long int tmp;
+
+               errno = 0;
+               tmp = strtol (value, NULL, 10);
+               if (errno == 0 && tmp > 0 && tmp < 65536) {
+                       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
+
+                       widget = GTK_WIDGET (gtk_builder_get_object (builder, "keysize_spinbutton"));
+                       gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), (gdouble) tmp);
+                       gtk_widget_set_sensitive (widget, TRUE);
+               }
+       } else {
+               gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
+
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "keysize_spinbutton"));
+               gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), 128.0);
+               gtk_widget_set_sensitive (widget, FALSE);
+       }
+
        widget = GTK_WIDGET (gtk_builder_get_object (builder, "hmacauth_combo"));
        value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_AUTH);
        populate_hmacauth_combo (GTK_COMBO_BOX (widget), value);
@@ -1812,6 +1848,15 @@ advanced_dialog_new_hash_from_dialog (GtkWidget *dialog, GError **error)
                }
        }
 
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "keysize_checkbutton"));
+       if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
+               int keysize_val;
+
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "keysize_spinbutton"));
+               keysize_val = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (widget));
+               g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_KEYSIZE), g_strdup_printf ("%d", 
keysize_val));
+       }
+
        widget = GTK_WIDGET (gtk_builder_get_object (builder, "hmacauth_combo"));
        model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter)) {
diff --git a/properties/import-export.c b/properties/import-export.c
index 5312e36..804fc3c 100644
--- a/properties/import-export.c
+++ b/properties/import-export.c
@@ -49,6 +49,7 @@
 #define CA_TAG "ca "
 #define CERT_TAG "cert "
 #define CIPHER_TAG "cipher "
+#define KEYSIZE_TAG "keysize "
 #define CLIENT_TAG "client"
 #define COMP_TAG "comp-lzo"
 #define DEV_TAG "dev "
@@ -597,6 +598,25 @@ do_import (const char *path, char **lines, GError **error)
                        continue;
                }
 
+               if (!strncmp (*line, KEYSIZE_TAG, strlen (KEYSIZE_TAG))) {
+                       items = get_args (*line + strlen (KEYSIZE_TAG), &nitems);
+                       if (nitems == 1) {
+                               glong key_size;
+
+                               errno = 0;
+                               key_size = strtol (items[0], NULL, 10);
+                               if ((errno == 0) && (key_size > 0) && (key_size <= 65535)) {
+                                       tmp = g_strdup_printf ("%d", (guint32) key_size);
+                                       nm_setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_KEYSIZE, tmp);
+                                       g_free (tmp);
+                               } else
+                                       g_warning ("%s: invalid key size in option '%s'", __func__, *line);
+                       } else
+                               g_warning ("%s: invalid number of arguments in option '%s'", __func__, *line);
+                       g_strfreev (items);
+                       continue;
+               }
+
                if (!strncmp (*line, TLS_REMOTE_TAG, strlen (TLS_REMOTE_TAG))) {
                        char *unquoted = unquote (*line + strlen (TLS_REMOTE_TAG), NULL);
 
@@ -754,6 +774,8 @@ do_export (const char *path, NMConnection *connection, GError **error)
        gboolean use_lzo = FALSE;
        gboolean reneg_exists = FALSE;
        guint32 reneg = 0;
+       gboolean keysize_exists = FALSE;
+       guint32 keysize = 0;
        const char *proxy_type = NULL;
        const char *proxy_server = NULL;
        const char *proxy_port = NULL;
@@ -845,6 +867,12 @@ do_export (const char *path, NMConnection *connection, GError **error)
        if (value && strlen (value))
                cipher = value;
 
+       value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_KEYSIZE);
+       if (value && strlen (value)) {
+               keysize_exists = TRUE;
+               keysize = strtol (value, NULL, 10);
+       }
+
        value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_LOCAL_IP);
        if (value && strlen (value))
                local_ip = value;
@@ -913,6 +941,9 @@ do_export (const char *path, NMConnection *connection, GError **error)
        if (cipher)
                fprintf (f, "cipher %s\n", cipher);
 
+       if (keysize_exists)
+               fprintf (f, "keysize %d\n", keysize);
+
        if (use_lzo)
                fprintf (f, "comp-lzo yes\n");
 
diff --git a/properties/nm-openvpn-dialog.ui b/properties/nm-openvpn-dialog.ui
index 6c32e7f..c8a8a67 100644
--- a/properties/nm-openvpn-dialog.ui
+++ b/properties/nm-openvpn-dialog.ui
@@ -32,6 +32,13 @@
     <property name="step_increment">1</property>
     <property name="page_increment">10</property>
   </object>
+  <object class="GtkAdjustment" id="adjustment6">
+    <property name="lower">1</property>
+    <property name="upper">65535</property>
+    <property name="value">128</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
   <object class="GtkListStore" id="liststore1"/>
   <object class="GtkListStore" id="liststore2"/>
   <object class="GtkListStore" id="model1">
@@ -507,6 +514,50 @@ config: cipher</property>
                       </packing>
                     </child>
                     <child>
+                      <object class="GtkCheckButton" id="keysize_checkbutton">
+                        <property name="label" translatable="yes">Use custom _size of cipher key:</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">Set cipher key size to a custom 
value. If unspecified, it defaults to cipher-specific size.
+config: keysize &lt;n&gt;</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                        <property name="left_attach">0</property>
+                        <property name="right_attach">1</property>
+                        <property name="top_attach">1</property>
+                        <property name="bottom_attach">2</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkSpinButton" id="keysize_spinbutton">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="invisible_char">●</property>
+                        <property name="adjustment">adjustment6</property>
+                        <property name="climb_rate">1</property>
+                        <property name="numeric">True</property>
+                        <property name="tooltip_text" translatable="yes">Set cipher key size to a custom 
value. If unspecified, it defaults to cipher-specific size.
+config: keysize &lt;n&gt;</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">1</property>
+                        <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>
                       <object class="GtkComboBox" id="hmacauth_combo">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
@@ -523,8 +574,8 @@ config: auth</property>
                       <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>
+                        <property name="top_attach">2</property>
+                        <property name="bottom_attach">3</property>
                       </packing>
                     </child>
                     <child>
@@ -549,8 +600,8 @@ config: auth</property>
                         <property name="mnemonic_widget">hmacauth_combo</property>
                       </object>
                       <packing>
-                        <property name="top_attach">1</property>
-                        <property name="bottom_attach">2</property>
+                        <property name="top_attach">2</property>
+                        <property name="bottom_attach">3</property>
                       </packing>
                     </child>
                   </object>
diff --git a/properties/tests/conf/Makefile.am b/properties/tests/conf/Makefile.am
index 25398ea..1698ffd 100644
--- a/properties/tests/conf/Makefile.am
+++ b/properties/tests/conf/Makefile.am
@@ -11,6 +11,7 @@ EXTRA_DIST = \
        proxy-http.ovpn \
        httpauthfile \
        proxy-socks.ovpn \
-       proxy-http-with-auth.ovpn
+       proxy-http-with-auth.ovpn \
+       keysize.ovpn \
 
 
diff --git a/properties/tests/conf/keysize.ovpn b/properties/tests/conf/keysize.ovpn
new file mode 100644
index 0000000..8d83d89
--- /dev/null
+++ b/properties/tests/conf/keysize.ovpn
@@ -0,0 +1,20 @@
+client
+dev tun
+proto tcp
+remote miami.proxpn.com 443 
+resolv-retry infinite
+nobind
+persist-key
+persist-tun
+comp-lzo
+tun-mtu 1500
+mssfix 1450
+auth-user-pass
+reneg-sec 0
+
+ca ssl/ca.crt
+cert ssl/client.crt
+key ssl/client.key
+cipher BF-CBC
+keysize 512
+
diff --git a/properties/tests/test-import-export.c b/properties/tests/test-import-export.c
index 3932ce7..8031f65 100644
--- a/properties/tests/test-import-export.c
+++ b/properties/tests/test-import-export.c
@@ -945,6 +945,66 @@ test_proxy_socks_export (NMVpnPluginUiInterface *plugin, const char *dir, const
        g_free (path);
 }
 
+static void
+test_keysize_import (NMVpnPluginUiInterface *plugin, const char *dir)
+{
+       NMConnection *connection;
+       NMSettingVPN *s_vpn;
+
+       connection = get_basic_connection ("keysize-import", plugin, dir, "keysize.ovpn");
+       ASSERT (connection != NULL, "keysize-import", "failed to import connection");
+
+       /* VPN setting */
+       s_vpn = (NMSettingVPN *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN);
+       ASSERT (s_vpn != NULL,
+               "keysize-import", "missing 'vpn' setting");
+
+       /* Data items */
+       test_item ("keysize-import-data", s_vpn, NM_OPENVPN_KEY_KEYSIZE, "512");
+
+       g_object_unref (connection);
+}
+
+#define KEYSIZE_EXPORTED_NAME "keysize.ovpntest"
+static void
+test_keysize_export (NMVpnPluginUiInterface *plugin, const char *dir, const char *tmpdir)
+{
+       NMConnection *connection;
+       NMConnection *reimported;
+       char *path;
+       gboolean success;
+       GError *error = NULL;
+
+       connection = get_basic_connection ("keysize-export", plugin, dir, "keysize.ovpn");
+       ASSERT (connection != NULL, "keysize-export", "failed to import connection");
+
+       path = g_build_path ("/", tmpdir, KEYSIZE_EXPORTED_NAME, NULL);
+       success = nm_vpn_plugin_ui_interface_export (plugin, path, connection, &error);
+       if (!success) {
+               if (!error)
+                       FAIL ("keysize-export", "export failed with missing error");
+               else
+                       FAIL ("keysize-export", "export failed: %s", error->message);
+       }
+
+       /* Now re-import it and compare the connections to ensure they are the same */
+       reimported = get_basic_connection ("keysize-export", plugin, tmpdir, KEYSIZE_EXPORTED_NAME);
+       (void) unlink (path);
+       ASSERT (reimported != NULL, "keysize-export", "failed to re-import connection");
+
+       /* Clear secrets first, since they don't get exported, and thus would
+        * make the connection comparison below fail.
+        */
+       remove_secrets (connection);
+
+       ASSERT (nm_connection_compare (connection, reimported, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
+               "keysize-export", "original and reimported connection differ");
+
+       g_object_unref (reimported);
+       g_object_unref (connection);
+       g_free (path);
+}
+
 int main (int argc, char **argv)
 {
        GError *error = NULL;
@@ -1013,6 +1073,9 @@ int main (int argc, char **argv)
        test_proxy_socks_import (plugin, test_dir);
        test_proxy_socks_export (plugin, test_dir, argv[2]);
 
+       test_keysize_import (plugin, test_dir);
+       test_keysize_export (plugin, test_dir, argv[2]);
+
        g_object_unref (plugin);
 
        basename = g_path_get_basename (argv[0]);
diff --git a/src/nm-openvpn-service.c b/src/nm-openvpn-service.c
index 54be7d5..8589b57 100644
--- a/src/nm-openvpn-service.c
+++ b/src/nm-openvpn-service.c
@@ -101,6 +101,7 @@ static ValidProperty valid_properties[] = {
        { NM_OPENVPN_KEY_CA,                   G_TYPE_STRING, 0, 0, FALSE },
        { NM_OPENVPN_KEY_CERT,                 G_TYPE_STRING, 0, 0, FALSE },
        { NM_OPENVPN_KEY_CIPHER,               G_TYPE_STRING, 0, 0, FALSE },
+       { NM_OPENVPN_KEY_KEYSIZE,              G_TYPE_INT, 1, 65535, FALSE },
        { NM_OPENVPN_KEY_COMP_LZO,             G_TYPE_BOOLEAN, 0, 0, FALSE },
        { NM_OPENVPN_KEY_CONNECTION_TYPE,      G_TYPE_STRING, 0, 0, FALSE },
        { NM_OPENVPN_KEY_FRAGMENT_SIZE,        G_TYPE_INT, 0, G_MAXINT, FALSE },
@@ -993,6 +994,21 @@ nm_openvpn_start_openvpn_binary (NMOpenvpnPlugin *plugin,
                add_openvpn_arg (args, tmp);
        }
 
+       /* Keysize */
+       tmp = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_KEYSIZE);
+       if (tmp && strlen (tmp)) {
+               add_openvpn_arg (args, "--keysize");
+               if (!add_openvpn_arg_int (args, tmp)) {
+                       g_set_error (error,
+                                    NM_VPN_PLUGIN_ERROR,
+                                    NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
+                                    _("Invalid keysize '%s'."),
+                                    tmp);
+                       free_openvpn_args (args);
+                       return FALSE;
+               }
+       }
+
        /* Auth */
        if (auth) {
                add_openvpn_arg (args, "--auth");
diff --git a/src/nm-openvpn-service.h b/src/nm-openvpn-service.h
index a60fa89..09e7e63 100644
--- a/src/nm-openvpn-service.h
+++ b/src/nm-openvpn-service.h
@@ -42,6 +42,7 @@
 #define NM_OPENVPN_KEY_CA "ca"
 #define NM_OPENVPN_KEY_CERT "cert"
 #define NM_OPENVPN_KEY_CIPHER "cipher"
+#define NM_OPENVPN_KEY_KEYSIZE "keysize"
 #define NM_OPENVPN_KEY_COMP_LZO "comp-lzo"
 #define NM_OPENVPN_KEY_CONNECTION_TYPE "connection-type"
 #define NM_OPENVPN_KEY_FRAGMENT_SIZE "fragment-size"


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