[network-manager-openvpn] service, properties: support the --crl-verify option



commit 214815f72054544298ef8b44544606844f117616
Author: Beniamino Galvani <bgalvani redhat com>
Date:   Wed Mar 28 09:29:26 2018 +0200

    service,properties: support the --crl-verify option
    
    https://bugzilla.gnome.org/show_bug.cgi?id=782309

 Makefile.am                           |    2 +
 properties/import-export.c            |   32 +++++++++++++
 properties/nm-openvpn-dialog.ui       |   55 +++++++++++++++++++++++-
 properties/nm-openvpn-editor.c        |   78 +++++++++++++++++++++++++++++++++
 properties/tests/conf/crl-dir.ovpn    |   22 +++++++++
 properties/tests/conf/crl-file.ovpn   |   22 +++++++++
 properties/tests/test-import-export.c |   37 +++++++++++++++
 shared/nm-service-defines.h           |    2 +
 shared/utils.h                        |    1 +
 src/nm-openvpn-service.c              |   11 +++++
 10 files changed, 261 insertions(+), 1 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 6cc7807..c38cc5e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -308,6 +308,8 @@ EXTRA_DIST += \
        properties/tests/conf/ping-with-restart.ovpn \
        properties/tests/conf/route.ovpn \
        properties/tests/conf/server-poll-timeout.ovpn \
+       properties/tests/conf/crl-file.ovpn \
+       properties/tests/conf/crl-dir.ovpn \
        properties/tests/conf/tls-inline.ovpn \
        properties/tests/conf/tls-inline-ca.pem \
        properties/tests/conf/tls-inline-cert.pem \
diff --git a/properties/import-export.c b/properties/import-export.c
index 5c4a792..e70433c 100644
--- a/properties/import-export.c
+++ b/properties/import-export.c
@@ -934,6 +934,29 @@ do_import (const char *path, const char *contents, gsize contents_len, GError **
                        continue;
                }
 
+               if (NM_IN_STRSET (params[0], NMV_OVPN_TAG_CRL_VERIFY)) {
+                       const char *file;
+                       gs_free char *file_free = NULL;
+
+                       if (!args_params_check_nargs_minmax (params, 1, 2, &line_error))
+                               goto handle_line_error;
+                       if (!args_params_check_arg_nonempty (params, 1, NULL, &line_error))
+                               goto handle_line_error;
+                       if (params[2] && !nm_streq (params[2], "dir")) {
+                               line_error = g_strdup_printf (_("unsupported crl-verify argument"));
+                               goto handle_line_error;
+                       }
+
+                       file = params[1];
+                       if (!g_path_is_absolute (file))
+                               file = file_free = g_build_filename (default_path, file, NULL);
+
+                       if (params[2])
+                               setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_CRL_VERIFY_DIR, file);
+                       else
+                               setting_vpn_add_data_item (s_vpn, NM_OPENVPN_KEY_CRL_VERIFY_FILE, file);
+               }
+
                if (NM_IN_STRSET (params[0], NMV_OVPN_TAG_NS_CERT_TYPE)) {
                        if (!args_params_check_nargs_n (params, 1, &line_error))
                                goto handle_line_error;
@@ -1939,6 +1962,15 @@ do_export_create (NMConnection *connection, const char *path, GError **error)
 
        args_write_line_setting_value_int (f, NMV_OVPN_TAG_FRAGMENT, s_vpn, NM_OPENVPN_KEY_FRAGMENT_SIZE);
 
+       value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_CRL_VERIFY_FILE);
+       if (value)
+               args_write_line (f, NMV_OVPN_TAG_CRL_VERIFY, value);
+       else {
+               value = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_CRL_VERIFY_DIR);
+               if (value)
+                       args_write_line (f, NMV_OVPN_TAG_CRL_VERIFY, value, "dir");
+       }
+
        {
                gs_free char *device_free = NULL;
                const char *device_type, *device;
diff --git a/properties/nm-openvpn-dialog.ui b/properties/nm-openvpn-dialog.ui
index 93068a4..e89e53f 100644
--- a/properties/nm-openvpn-dialog.ui
+++ b/properties/nm-openvpn-dialog.ui
@@ -1614,6 +1614,59 @@ config: auth</property>
                         <property name="top_attach">2</property>
                       </packing>
                     </child>
+                    <child>
+                      <object class="GtkCheckButton" id="crl_file_check">
+                        <property name="label" translatable="yes">Verify CRL from file</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="tooltip_text" translatable="yes">Check peer certificate against the 
specified file in PEM format. A CRL (certificate revocation list) is used when a particular key is 
compromised but when the overall PKI is still intact.</property>
+                        <property name="draw_indicator">True</property>
+                      </object>
+                      <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">3</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkCheckButton" id="crl_dir_check">
+                        <property name="label" translatable="yes">Verify CRL from directory</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="tooltip_text" translatable="yes">Check peer certificate by looking 
at files in the specified directory. The directory must contain files named as revoked serial numbers (the 
files may be empty, the contents are never read).</property>
+                        <property name="draw_indicator">True</property>
+                      </object>
+                      <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">4</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkFileChooserButton" id="crl_file_chooser">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="tooltip_text" translatable="yes">Check peer certificate against the 
specified file in PEM format. A CRL (certificate revocation list) is used when a particular key is 
compromised but when the overall PKI is still intact.</property>
+                        <property name="title" translatable="yes">Choose CRL file</property>
+                      </object>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="top_attach">3</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkFileChooserButton" id="crl_dir_chooser">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="tooltip_text" translatable="yes">Check peer certificate by looking 
at files in the specified directory. The directory must contain files named as revoked serial numbers (the 
files may be empty, the contents are never read).</property>
+                        <property name="action">select-folder</property>
+                        <property name="title" translatable="yes">Choose CRL directory</property>
+                      </object>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="top_attach">4</property>
+                      </packing>
+                    </child>
                   </object>
                 </child>
               </object>
@@ -2369,9 +2422,9 @@ config: http-proxy-retry or socks-proxy-retry</property>
                         <property name="label" translatable="yes">Connect timeout</property>
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
                         <property name="tooltip_text" translatable="yes">The timeout in seconds before 
trying the next server. This timeout includes proxy and TCP connect timeouts.
 config: connect-timeout &lt;n&gt; | server-poll-timeout &lt;n&gt;</property>
-                        <property name="receives_default">False</property>
                         <property name="draw_indicator">True</property>
                       </object>
                       <packing>
diff --git a/properties/nm-openvpn-editor.c b/properties/nm-openvpn-editor.c
index 5ba33ef..c548c1c 100644
--- a/properties/nm-openvpn-editor.c
+++ b/properties/nm-openvpn-editor.c
@@ -686,6 +686,8 @@ static const char *advanced_keys[] = {
        NM_OPENVPN_KEY_CIPHER,
        NM_OPENVPN_KEY_COMP_LZO,
        NM_OPENVPN_KEY_CONNECT_TIMEOUT,
+       NM_OPENVPN_KEY_CRL_VERIFY_DIR,
+       NM_OPENVPN_KEY_CRL_VERIFY_FILE,
        NM_OPENVPN_KEY_DEV,
        NM_OPENVPN_KEY_DEV_TYPE,
        NM_OPENVPN_KEY_EXTRA_CERTS,
@@ -1333,6 +1335,36 @@ device_name_changed_cb (GtkEntry *entry,
 }
 
 static void
+crl_file_checkbox_toggled_cb (GtkWidget *check, gpointer user_data)
+{
+       GtkBuilder *builder = (GtkBuilder *) user_data;
+       GtkWidget *other, *combo;
+
+       other = GTK_WIDGET (gtk_builder_get_object (builder, "crl_dir_check"));
+       combo = GTK_WIDGET (gtk_builder_get_object (builder, "crl_file_chooser"));
+       if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check))) {
+               gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (other), FALSE);
+               gtk_widget_set_sensitive (combo, TRUE);
+       } else
+               gtk_widget_set_sensitive (combo, FALSE);
+}
+
+static void
+crl_dir_checkbox_toggled_cb (GtkWidget *check, gpointer user_data)
+{
+       GtkBuilder *builder = (GtkBuilder *) user_data;
+       GtkWidget *other, *combo;
+
+       other = GTK_WIDGET (gtk_builder_get_object (builder, "crl_file_check"));
+       combo = GTK_WIDGET (gtk_builder_get_object (builder, "crl_dir_chooser"));
+       if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check))) {
+               gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (other), FALSE);
+               gtk_widget_set_sensitive (combo, TRUE);
+       } else
+               gtk_widget_set_sensitive (combo, FALSE);
+}
+
+static void
 dev_checkbox_toggled_cb (GtkWidget *check, gpointer user_data)
 {
        GtkBuilder *builder = (GtkBuilder *) user_data;
@@ -1756,6 +1788,29 @@ advanced_dialog_new (GHashTable *hash, const char *contype)
        g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (mtu_disc_toggled_cb), builder);
        mtu_disc_toggled_cb (widget, builder);
 
+       /* CRL */
+       value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_CRL_VERIFY_FILE);
+       if (value) {
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "crl_file_check"));
+               gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "crl_file_chooser"));
+               gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), value);
+       } else {
+               value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_CRL_VERIFY_DIR);
+               if (value) {
+                       widget = GTK_WIDGET (gtk_builder_get_object (builder, "crl_dir_check"));
+                       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
+                       widget = GTK_WIDGET (gtk_builder_get_object (builder, "crl_dir_chooser"));
+                       gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), value);
+               }
+       }
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "crl_file_check"));
+       g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (crl_file_checkbox_toggled_cb), builder);
+       crl_file_checkbox_toggled_cb (widget, builder);
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "crl_dir_check"));
+       g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (crl_dir_checkbox_toggled_cb), builder);
+       crl_dir_checkbox_toggled_cb (widget, builder);
+
        value = g_hash_table_lookup (hash, NM_OPENVPN_KEY_MAX_ROUTES);
        _builder_init_optional_spinbutton (builder, "max_routes_checkbutton", "max_routes_spinbutton", 
!!value,
                                           _nm_utils_ascii_str_to_int64 (value, 10, 0, 100000000, 100));
@@ -2126,6 +2181,29 @@ advanced_dialog_new_hash_from_dialog (GtkWidget *dialog, GError **error)
                }
        }
 
+       /* CRL */
+       widget = GTK_WIDGET (gtk_builder_get_object (builder, "crl_file_check"));
+       if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
+               char *filename;
+
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "crl_file_chooser"));
+               filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+               if (filename && filename[0])
+                       g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_CRL_VERIFY_FILE), g_strdup 
(filename));
+               g_free (filename);
+       } else {
+               widget = GTK_WIDGET (gtk_builder_get_object (builder, "crl_dir_check"));
+               if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
+                       char *filename;
+
+                       widget = GTK_WIDGET (gtk_builder_get_object (builder, "crl_dir_chooser"));
+                       filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+                       if (filename && filename[0])
+                               g_hash_table_insert (hash, g_strdup (NM_OPENVPN_KEY_CRL_VERIFY_DIR), g_strdup 
(filename));
+                       g_free (filename);
+               }
+       }
+
        return hash;
 }
 
diff --git a/properties/tests/conf/crl-dir.ovpn b/properties/tests/conf/crl-dir.ovpn
new file mode 100644
index 0000000..d27220a
--- /dev/null
+++ b/properties/tests/conf/crl-dir.ovpn
@@ -0,0 +1,22 @@
+port 2345
+
+remote 173.8.149.245
+resolv-retry infinite
+
+dev tun
+persist-key
+persist-tun
+link-mtu 1400
+proto udp
+nobind
+pull
+tls-client
+
+ca keys/mg8.ca
+cert keys/clee.crt
+key keys/clee.key
+
+comp-lzo
+verb 3
+
+crl-verify /home/user/.cert/crls/ dir
\ No newline at end of file
diff --git a/properties/tests/conf/crl-file.ovpn b/properties/tests/conf/crl-file.ovpn
new file mode 100644
index 0000000..2054b21
--- /dev/null
+++ b/properties/tests/conf/crl-file.ovpn
@@ -0,0 +1,22 @@
+port 2345
+
+remote 173.8.149.245
+resolv-retry infinite
+
+dev tun
+persist-key
+persist-tun
+link-mtu 1400
+proto udp
+nobind
+pull
+tls-client
+
+ca keys/mg8.ca
+cert keys/clee.crt
+key keys/clee.key
+
+comp-lzo
+verb 3
+
+crl-verify /home/user/.cert/crl.pem
\ No newline at end of file
diff --git a/properties/tests/test-import-export.c b/properties/tests/test-import-export.c
index e28acee..8a137aa 100644
--- a/properties/tests/test-import-export.c
+++ b/properties/tests/test-import-export.c
@@ -980,6 +980,37 @@ test_mtu_disc_import (gconstpointer test_data)
        g_object_unref (connection);
 }
 
+
+static void
+test_crl_verify_import (gconstpointer test_data)
+{
+       _CREATE_PLUGIN (plugin);
+       NMConnection *connection;
+       NMSettingVpn *s_vpn;
+       const char *file, *expected_val;
+       gpointer is_file;
+
+       nmtst_test_data_unpack (test_data, &file, &is_file, &expected_val);
+
+       connection = get_basic_connection (plugin, SRCDIR, file);
+       g_assert (connection);
+
+       /* VPN setting */
+       s_vpn = nm_connection_get_setting_vpn (connection);
+       g_assert (s_vpn);
+
+       /* Data items */
+       if (GPOINTER_TO_INT (is_file)) {
+               _check_item (s_vpn, NM_OPENVPN_KEY_CRL_VERIFY_FILE, expected_val);
+               _check_item (s_vpn, NM_OPENVPN_KEY_CRL_VERIFY_DIR, NULL);
+       } else {
+               _check_item (s_vpn, NM_OPENVPN_KEY_CRL_VERIFY_DIR, expected_val);
+               _check_item (s_vpn, NM_OPENVPN_KEY_CRL_VERIFY_FILE, NULL);
+       }
+
+       g_object_unref (connection);
+}
+
 static void
 test_route_import (void)
 {
@@ -1252,6 +1283,12 @@ int main (int argc, char **argv)
        _add_test_func ("mtu-disc-import", test_mtu_disc_import, "mtu-disc.ovpn", "yes");
        _add_test_func ("mtu-disc-export", test_export_compare, "mtu-disc.ovpn", "mtu-disc.ovpntest");
 
+       _add_test_func ("crl-verify-file-import", test_crl_verify_import, "crl-file.ovpn", GINT_TO_POINTER 
(TRUE), "/home/user/.cert/crl.pem");
+       _add_test_func ("crl-verify-file-export", test_export_compare, "crl-file.ovpn", "crl-file.ovpntest");
+
+       _add_test_func ("crl-verify-dir-import", test_crl_verify_import, "crl-dir.ovpn", GINT_TO_POINTER 
(FALSE), "/home/user/.cert/crls/");
+       _add_test_func ("crl-verify-dir-export", test_export_compare, "crl-dir.ovpn", "crl-dir.ovpntest");
+
        _add_test_func_simple (test_route_import);
        _add_test_func ("route-export", test_export_compare, "route.ovpn", "route.ovpntest");
 
diff --git a/shared/nm-service-defines.h b/shared/nm-service-defines.h
index 2b4e150..9fb50a0 100644
--- a/shared/nm-service-defines.h
+++ b/shared/nm-service-defines.h
@@ -35,6 +35,8 @@
 #define NM_OPENVPN_KEY_COMP_LZO "comp-lzo"
 #define NM_OPENVPN_KEY_CONNECTION_TYPE "connection-type"
 #define NM_OPENVPN_KEY_CONNECT_TIMEOUT "connect-timeout"
+#define NM_OPENVPN_KEY_CRL_VERIFY_FILE "crl-verify-file"
+#define NM_OPENVPN_KEY_CRL_VERIFY_DIR "crl-verify-dir"
 #define NM_OPENVPN_KEY_DEV "dev"
 #define NM_OPENVPN_KEY_DEV_TYPE "dev-type"
 #define NM_OPENVPN_KEY_EXTRA_CERTS "extra-certs"
diff --git a/shared/utils.h b/shared/utils.h
index 00e8470..b459160 100644
--- a/shared/utils.h
+++ b/shared/utils.h
@@ -31,6 +31,7 @@
 #define NMV_OVPN_TAG_CLIENT             "client"
 #define NMV_OVPN_TAG_COMP_LZO           "comp-lzo"
 #define NMV_OVPN_TAG_CONNECT_TIMEOUT    "connect-timeout"
+#define NMV_OVPN_TAG_CRL_VERIFY         "crl-verify"
 #define NMV_OVPN_TAG_DEV                "dev"
 #define NMV_OVPN_TAG_DEV_TYPE           "dev-type"
 #define NMV_OVPN_TAG_EXTRA_CERTS        "extra-certs"
diff --git a/src/nm-openvpn-service.c b/src/nm-openvpn-service.c
index 1774762..79de8ed 100644
--- a/src/nm-openvpn-service.c
+++ b/src/nm-openvpn-service.c
@@ -148,6 +148,8 @@ static const ValidProperty valid_properties[] = {
        { NM_OPENVPN_KEY_COMP_LZO,             G_TYPE_STRING, 0, 0, FALSE },
        { NM_OPENVPN_KEY_CONNECT_TIMEOUT,      G_TYPE_INT, 0, G_MAXINT, FALSE },
        { NM_OPENVPN_KEY_CONNECTION_TYPE,      G_TYPE_STRING, 0, 0, FALSE },
+       { NM_OPENVPN_KEY_CRL_VERIFY_FILE,      G_TYPE_STRING, 0, 0, FALSE },
+       { NM_OPENVPN_KEY_CRL_VERIFY_DIR,       G_TYPE_STRING, 0, 0, FALSE },
        { NM_OPENVPN_KEY_EXTRA_CERTS,          G_TYPE_STRING, 0, 0, FALSE },
        { NM_OPENVPN_KEY_FLOAT,                G_TYPE_BOOLEAN, 0, 0, FALSE },
        { NM_OPENVPN_KEY_FRAGMENT_SIZE,        G_TYPE_INT, 0, G_MAXINT, FALSE },
@@ -1795,6 +1797,15 @@ nm_openvpn_start_openvpn_binary (NMOpenvpnPlugin *plugin,
        if (NM_IN_STRSET (tmp, "no", "maybe", "yes"))
                args_add_strv (args, "--mtu-disc", tmp);
 
+       tmp = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_CRL_VERIFY_FILE);
+       if (tmp)
+               args_add_strv (args, "--crl-verify", tmp);
+       else {
+               tmp = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_CRL_VERIFY_DIR);
+               if (tmp)
+                       args_add_strv (args, "--crl-verify", tmp, "dir");
+       }
+
        tmp = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_LOCAL_IP);
        tmp2 = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_REMOTE_IP);
        if (tmp && tmp2)


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