[NetworkManager-openvpn] Handle the various pkcs12/cert/key/ca combinations.



commit 34a0c9257aac9ed6e3ac7cdad6f6cc7d8107eef1
Author: Katelyn Schiesser <katelyn schiesser gmail com>
Date:   Wed Jul 8 11:32:32 2020 -0700

    Handle the various pkcs12/cert/key/ca combinations.
    
    OpenVPN allows supplying PKCS#12 client cert/key *or* PEM client cert/key, as
    well as a PEM CA cert in either case. When supplying --pkcs12, the args --cert
    and --key can not be used. So, you can have one of the following:
    
        - PKCS#12 combined cert/key/ca (one file): --pkcs12
        - PKCS#12 combined cert/key/ca with PEM CA: --pkcs12, --ca
        - PEM cert/key, PEM CA: --cert, --key, --ca
    
    If a user tries to import an invalid config, they will be met with the appropriate
    error message. The editor dialog also enforces the PKCS#12/PEM restrictions.
    
    https://gitlab.gnome.org/GNOME/NetworkManager-openvpn/-/merge_requests/29

 Makefile.am                                  |   1 +
 properties/import-export.c                   | 153 +++++++++++++++++++--------
 properties/nm-openvpn-editor.c               |  73 +++++++++----
 properties/tests/conf/compress.ovpn          |   1 +
 properties/tests/conf/pkcs12-with-ca.ovpn    |  18 ++++
 properties/tests/conf/proto-tcp-client.ovpn  |   1 +
 properties/tests/conf/proto-tcp.ovpn         |   1 +
 properties/tests/conf/proto-tcp4-client.ovpn |   1 +
 properties/tests/conf/proto-tcp4.ovpn        |   1 +
 properties/tests/conf/proto-tcp6-client.ovpn |   1 +
 properties/tests/conf/proto-tcp6.ovpn        |   1 +
 properties/tests/conf/proto-udp.ovpn         |   1 +
 properties/tests/conf/proto-udp4.ovpn        |   1 +
 properties/tests/conf/proto-udp6.ovpn        |   1 +
 properties/tests/conf/push-peer-info.ovpn    |   1 +
 properties/tests/test-import-export.c        |  44 ++++++++
 src/nm-openvpn-service.c                     |  18 ++--
 17 files changed, 240 insertions(+), 78 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 37748b1..1b7fda5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -290,6 +290,7 @@ EXTRA_DIST += \
        properties/tests/conf/mtu-disc.ovpn \
        properties/tests/conf/password.conf \
        properties/tests/conf/pkcs12.ovpn \
+       properties/tests/conf/pkcs12-with-ca.ovpn \
        properties/tests/conf/port.ovpn \
        properties/tests/conf/rport.ovpn \
        properties/tests/conf/static.key \
diff --git a/properties/import-export.c b/properties/import-export.c
index c1fe6db..ad9505d 100644
--- a/properties/import-export.c
+++ b/properties/import-export.c
@@ -791,7 +791,8 @@ do_import (const char *path, const char *contents, gsize contents_len, GError **
        char *tmp, *tmp2;
        const char *ta_direction = NULL, *secret_direction = NULL;
        gboolean allow_ta_direction = FALSE, allow_secret_direction = FALSE;
-       gboolean have_certs, have_ca;
+       gboolean have_cert = FALSE, have_key = FALSE, have_ca = FALSE, have_pkcs12 = FALSE;
+       const char *cert_path = NULL, *key_path = NULL, *ca_path = NULL;
        GSList *inline_blobs = NULL;
        GSList *sl_iter;
 
@@ -1241,7 +1242,7 @@ do_import (const char *path, const char *contents, gsize contents_len, GError **
                        continue;
                }
 
-               if (NM_IN_STRSET (params[0], NMV_OVPN_TAG_TLS_VERSION_MIN)){
+               if (NM_IN_STRSET (params[0], NMV_OVPN_TAG_TLS_VERSION_MIN)) {
                        if (!args_params_check_nargs_n (params, 1, &line_error))
                                goto handle_line_error;
                        if (!args_params_check_arg_utf8 (params, 1, NULL, &line_error))
@@ -1250,7 +1251,7 @@ do_import (const char *path, const char *contents, gsize contents_len, GError **
                        continue;
                }
 
-               if (NM_IN_STRSET (params[0], NMV_OVPN_TAG_TLS_VERSION_MAX)){
+               if (NM_IN_STRSET (params[0], NMV_OVPN_TAG_TLS_VERSION_MAX)) {
                        if (!args_params_check_nargs_n (params, 1, &line_error))
                                goto handle_line_error;
                        if (!args_params_check_arg_utf8 (params, 1, NULL, &line_error))
@@ -1293,18 +1294,24 @@ do_import (const char *path, const char *contents, gsize contents_len, GError **
                                file = file_free = g_build_filename (default_path, file, NULL);
 
                        if (NM_IN_STRSET (params[0], NMV_OVPN_TAG_PKCS12)) {
-                               setting_vpn_add_data_item_path (s_vpn, NM_OPENVPN_KEY_CA, file);
+                                /* OpenVPN allows --pkcs12 with external (PEM) --ca. Don't overwrite it with 
the PKCS#12 file. */
+                               if (!have_ca) {
+                                       setting_vpn_add_data_item_path (s_vpn, NM_OPENVPN_KEY_CA, file);
+                                       have_ca = TRUE;
+                               }
                                setting_vpn_add_data_item_path (s_vpn, NM_OPENVPN_KEY_CERT, file);
                                setting_vpn_add_data_item_path (s_vpn, NM_OPENVPN_KEY_KEY, file);
-                       } else if (NM_IN_STRSET (params[0], NMV_OVPN_TAG_CA))
+                               have_pkcs12 = TRUE;
+                       } else if (NM_IN_STRSET (params[0], NMV_OVPN_TAG_CA)) {
                                setting_vpn_add_data_item_path (s_vpn, NM_OPENVPN_KEY_CA, file);
-                       else if (NM_IN_STRSET (params[0], NMV_OVPN_TAG_EXTRA_CERTS))
-                               setting_vpn_add_data_item_path (s_vpn, NM_OPENVPN_KEY_EXTRA_CERTS, file);
-                       else if (NM_IN_STRSET (params[0], NMV_OVPN_TAG_CERT))
+                               have_ca = TRUE;
+                       } else if (NM_IN_STRSET (params[0], NMV_OVPN_TAG_CERT)) {
                                setting_vpn_add_data_item_path (s_vpn, NM_OPENVPN_KEY_CERT, file);
-                       else if (NM_IN_STRSET (params[0], NMV_OVPN_TAG_KEY))
+                               have_cert = TRUE;
+                       } else if (NM_IN_STRSET (params[0], NMV_OVPN_TAG_KEY)) {
                                setting_vpn_add_data_item_path (s_vpn, NM_OPENVPN_KEY_KEY, file);
-                       else if (NM_IN_STRSET (params[0], NMV_OVPN_TAG_SECRET)) {
+                               have_key = TRUE;
+                       } else if (NM_IN_STRSET (params[0], NMV_OVPN_TAG_SECRET)) {
                                setting_vpn_add_data_item_path (s_vpn, NM_OPENVPN_KEY_STATIC_KEY, file);
                                if (s_direction)
                                        secret_direction = s_direction;
@@ -1317,6 +1324,8 @@ do_import (const char *path, const char *contents, gsize contents_len, GError **
                                allow_ta_direction = TRUE;
                        } else if (NM_IN_STRSET (params[0], NMV_OVPN_TAG_TLS_CRYPT))
                                setting_vpn_add_data_item_path (s_vpn, NM_OPENVPN_KEY_TLS_CRYPT, file);
+                       else if (NM_IN_STRSET (params[0], NMV_OVPN_TAG_EXTRA_CERTS))
+                               setting_vpn_add_data_item_path (s_vpn, NM_OPENVPN_KEY_EXTRA_CERTS, file);
                        else
                                g_assert_not_reached ();
                        continue;
@@ -1510,20 +1519,24 @@ do_import (const char *path, const char *contents, gsize contents_len, GError **
                        GString *blob_data;
                        InlineBlobData *inline_blob_data;
 
-                       if (nm_streq (token, INLINE_BLOB_CA))
+                       if (nm_streq (token, INLINE_BLOB_CA)) {
                                key = NM_OPENVPN_KEY_CA;
-                       else if (nm_streq (token, INLINE_BLOB_CERT))
+                               have_ca = TRUE;
+                       } else if (nm_streq (token, INLINE_BLOB_CERT)) {
                                key = NM_OPENVPN_KEY_CERT;
-                       else if (nm_streq (token, INLINE_BLOB_KEY))
+                               have_cert = TRUE;
+                       } else if (nm_streq (token, INLINE_BLOB_KEY)) {
                                key = NM_OPENVPN_KEY_KEY;
-                       else if (nm_streq (token, INLINE_BLOB_EXTRA_CERTS))
+                               have_key = TRUE;
+                       } else if (nm_streq (token, INLINE_BLOB_PKCS12)) {
+                               is_base64 = TRUE;
+                               key = NULL;
+                               have_pkcs12 = TRUE;
+                       } else if (nm_streq (token, INLINE_BLOB_EXTRA_CERTS))
                                key = NM_OPENVPN_KEY_EXTRA_CERTS;
                        else if (nm_streq (token, INLINE_BLOB_CRL_VERIFY))
                                key = NM_OPENVPN_KEY_CRL_VERIFY_FILE;
-                       else if (nm_streq (token, INLINE_BLOB_PKCS12)) {
-                               is_base64 = TRUE;
-                               key = NULL;
-                       } else if (nm_streq (token, INLINE_BLOB_TLS_CRYPT))
+                       else if (nm_streq (token, INLINE_BLOB_TLS_CRYPT))
                                key = NM_OPENVPN_KEY_TLS_CRYPT;
                        else if (nm_streq (token, INLINE_BLOB_TLS_AUTH)) {
                                key = NM_OPENVPN_KEY_TA;
@@ -1641,28 +1654,77 @@ handle_line_error:
                g_set_error_literal (error,
                                     NMV_EDITOR_PLUGIN_ERROR,
                                     NMV_EDITOR_PLUGIN_ERROR_FILE_NOT_VPN,
-                                    _("The file to import wasn’t a valid OpenVPN configure (no remote)"));
+                                    _("The file to import wasn’t a valid OpenVPN configuration (no 
remote)"));
                goto out_error;
        }
 
-       have_certs = FALSE;
-       have_ca = FALSE;
+       /* Validate PKCS#12/PEM/CA settings. PKCS#12 and PEM cannot be mixed,
+        * with the exception of PKCS#12 cert + PEM CA. */
+       if (have_client && have_pkcs12) {
+               if (have_cert || have_key) {
+                       g_set_error_literal (error,
+                                            NMV_EDITOR_PLUGIN_ERROR,
+                                            NMV_EDITOR_PLUGIN_ERROR_FILE_NOT_VPN,
+                                            _("The file to import wasn’t a valid OpenVPN configuration 
(--pkcs12 can not be used with --cert or --key)"));
+                       goto out_error;
+               }
+
+               if (have_ca) {
+                       ca_path = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_CA);
+                       if (is_pkcs12 (ca_path)) {
+                               g_set_error_literal (error,
+                                                    NMV_EDITOR_PLUGIN_ERROR,
+                                                    NMV_EDITOR_PLUGIN_ERROR_FILE_NOT_VPN,
+                                                    _("The file to import wasn’t a valid OpenVPN 
configuration (--ca can not be PKCS#12 format)"));
+                               goto out_error;
+                       }
+               }
+       } else if (have_client && !have_pkcs12) {
+               if (!have_ca) {
+                       g_set_error_literal (error,
+                                            NMV_EDITOR_PLUGIN_ERROR,
+                                            NMV_EDITOR_PLUGIN_ERROR_FILE_NOT_VPN,
+                                            _("The file to import wasn’t a valid OpenVPN configuration 
(missing --ca)"));
+                       goto out_error;
+               }
+
+               ca_path = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_CA);
 
-       if (nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_CA))
-               have_ca = TRUE;
+               if ((have_cert || have_key) && !(have_cert && have_key)) {
+                       g_set_error_literal (error,
+                                            NMV_EDITOR_PLUGIN_ERROR,
+                                            NMV_EDITOR_PLUGIN_ERROR_FILE_NOT_VPN,
+                                            _("The file to import wasn’t a valid OpenVPN configuration (if 
you use one of --cert or --key, you must use them both)"));
+                       goto out_error;
+               }
 
-       if (   have_ca
-           && nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_CERT)
-           && nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_KEY))
-               have_certs = TRUE;
+               cert_path = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_CERT);
+               key_path = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_KEY);
+
+               if (cert_path && is_pkcs12 (cert_path)) {
+                       g_set_error_literal (error,
+                                            NMV_EDITOR_PLUGIN_ERROR,
+                                            NMV_EDITOR_PLUGIN_ERROR_FILE_NOT_VPN,
+                                            _("The file to import wasn’t a valid OpenVPN configuration 
(--cert can not be PKCS#12 format.)"));
+                       goto out_error;
+               }
+
+               if (key_path && is_pkcs12 (key_path)) {
+                       g_set_error_literal (error,
+                                            NMV_EDITOR_PLUGIN_ERROR,
+                                            NMV_EDITOR_PLUGIN_ERROR_FILE_NOT_VPN,
+                                            _("The file to import wasn’t a valid OpenVPN configuration 
(--key can not be PKCS#12 format.)"));
+                       goto out_error;
+               }
+       }
 
        /* Determine connection type */
        if (have_pass) {
-               if (have_certs)
+               if (have_cert || have_pkcs12)
                        ctype = NM_OPENVPN_CONTYPE_PASSWORD_TLS;
                else if (have_ca)
                        ctype = NM_OPENVPN_CONTYPE_PASSWORD;
-       } else if (have_certs) {
+       } else if (have_cert || have_pkcs12) {
                ctype = NM_OPENVPN_CONTYPE_TLS;
        } else if (have_sk)
                ctype = NM_OPENVPN_CONTYPE_STATIC_KEY;
@@ -1679,15 +1741,12 @@ handle_line_error:
                                             NM_SETTING_SECRET_FLAG_AGENT_OWNED,
                                             NULL);
        }
-       if (have_certs) {
+       if (have_key || have_pkcs12) {
                gs_free char *key_path_free = NULL;
-               const char *key_path;
 
-               key_path = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_KEY);
                if (is_encrypted (nm_utils_str_utf8safe_unescape (key_path, &key_path_free))) {
                        /* If there should be a private key password, default it to
-                        * being agent-owned.
-                        */
+                        * being agent-owned. */
                        nm_setting_set_secret_flags (NM_SETTING (s_vpn),
                                                     NM_OPENVPN_KEY_CERTPASS,
                                                     NM_SETTING_SECRET_FLAG_AGENT_OWNED,
@@ -1933,7 +1992,10 @@ do_export_create (NMConnection *connection, const char *path, GError **error)
 
        f = g_string_sized_new (512);
 
-       args_write_line (f, NMV_OVPN_TAG_CLIENT);
+       if (NM_IN_STRSET (connection_type, NM_OPENVPN_CONTYPE_TLS,
+                                          NM_OPENVPN_CONTYPE_PASSWORD,
+                                          NM_OPENVPN_CONTYPE_PASSWORD_TLS))
+               args_write_line (f, NMV_OVPN_TAG_CLIENT);
 
        /* 'remote' */
        gw_list = g_strsplit_set (gateways, " \t,", 0);
@@ -1996,18 +2058,21 @@ do_export_create (NMConnection *connection, const char *path, GError **error)
                                private_key = nm_utils_str_utf8safe_unescape (value, &private_key_free);
                }
 
-               if (   cacert && user_cert && private_key
-                   && nm_streq (cacert, user_cert) && nm_streq (cacert, private_key)) {
-                       /* Handle PKCS#12 (all certs are the same file) */
-                       args_write_line (f, NMV_OVPN_TAG_PKCS12, cacert);
-               } else {
-                       if (cacert)
-                               args_write_line (f, NMV_OVPN_TAG_CA, cacert);
-                       if (user_cert)
+               if (user_cert && private_key) {
+                       if (   nm_streq (user_cert, private_key)
+                           && is_pkcs12 (user_cert))
+                               args_write_line (f, NMV_OVPN_TAG_PKCS12, user_cert);
+                       else {
                                args_write_line (f, NMV_OVPN_TAG_CERT, user_cert);
-                       if (private_key)
                                args_write_line (f, NMV_OVPN_TAG_KEY, private_key);
+                       }
                }
+
+               /* The CA can be included in a PKCS#12 file above, or a separate file (PEM format).
+                * If it's pkcs12 we can't use --ca as it only accepts PEM format. */
+               if (   cacert
+                   && !is_pkcs12 (cacert))
+                       args_write_line (f, NMV_OVPN_TAG_CA, cacert);
        }
 
        if (NM_IN_STRSET (connection_type, NM_OPENVPN_CONTYPE_PASSWORD,
diff --git a/properties/nm-openvpn-editor.c b/properties/nm-openvpn-editor.c
index 2d0f204..4f82ab3 100644
--- a/properties/nm-openvpn-editor.c
+++ b/properties/nm-openvpn-editor.c
@@ -73,28 +73,57 @@ widget_unset_error (GtkWidget *widget)
 /*****************************************************************************/
 
 static void
-tls_cert_changed_cb (NMACertChooser *this, gpointer user_data)
+tls_ca_changed_cb (NMACertChooser *this, gpointer user_data)
 {
        NMACertChooser *other = user_data;
        NMSetting8021xCKScheme scheme;
-       gs_free char *this_cert = NULL;
-       gs_free char *other_cert = NULL;
-       gs_free char *this_key = NULL;
-       gs_free char *other_key = NULL;
-
-       other_key = nma_cert_chooser_get_key (other, &scheme);
-       this_key = nma_cert_chooser_get_key (this, &scheme);
-       other_cert = nma_cert_chooser_get_cert (other, &scheme);
-       this_cert = nma_cert_chooser_get_cert (this, &scheme);
+       gs_free char *ca_cert = NULL;
+       gs_free char *client_cert = NULL;
+       gs_free char *client_key = NULL;
+
+       client_key = nma_cert_chooser_get_key (other, &scheme);
+       client_cert = nma_cert_chooser_get_cert (other, &scheme);
+       ca_cert = nma_cert_chooser_get_cert (this, &scheme);
+
+       /* OpenVPN allows --pkcs12 with --ca, but if the provided CA is a PKCS#12 file,
+        * we have to also set the cert/key to the same file - since OpenVPN does not
+        * allow mixing of --pkcs12 and --cert/--key. */
        if (   scheme == NM_SETTING_802_1X_CK_SCHEME_PATH
-           && is_pkcs12 (this_cert)) {
-               if (!this_key)
-                       nma_cert_chooser_set_key (this, this_cert, NM_SETTING_802_1X_CK_SCHEME_PATH);
-               if (!other_cert) {
-                       nma_cert_chooser_set_cert (other, this_cert, NM_SETTING_802_1X_CK_SCHEME_PATH);
-                       if (!other_key)
-                               nma_cert_chooser_set_key (other, this_cert, NM_SETTING_802_1X_CK_SCHEME_PATH);
+           && is_pkcs12 (ca_cert)) {
+               nma_cert_chooser_set_cert (other, ca_cert, NM_SETTING_802_1X_CK_SCHEME_PATH);
+               nma_cert_chooser_set_key (other, ca_cert, NM_SETTING_802_1X_CK_SCHEME_PATH);
+       }
+}
+
+static void
+tls_cert_changed_cb (NMACertChooser *this, gpointer user_data)
+{
+       NMACertChooser *other = user_data;
+       NMSetting8021xCKScheme scheme;
+       gs_free char *ca_cert = NULL;
+       gs_free char *client_cert = NULL;
+       gs_free char *client_key = NULL;
+
+       ca_cert = nma_cert_chooser_get_cert (other, &scheme);
+       client_key = nma_cert_chooser_get_key (this, &scheme);
+       client_cert = nma_cert_chooser_get_cert (this, &scheme);
+
+       /* OpenVPN does not allow a combination of --cert/--key and --pkcs12; however,
+        * it does allow --pkcs12 with --ca. */
+       if (client_cert && is_pkcs12 (client_cert)) {
+               if (!ca_cert)
+                       nma_cert_chooser_set_cert (other, client_cert, NM_SETTING_802_1X_CK_SCHEME_PATH);
+               if (   ca_cert
+                   && is_pkcs12 (ca_cert)
+                   && !nm_streq (client_cert, ca_cert))
+                       nma_cert_chooser_set_cert (other, client_cert, NM_SETTING_802_1X_CK_SCHEME_PATH);
+       } else if (client_cert && !is_pkcs12 (client_cert)) {
+               if (client_key && is_pkcs12 (client_key)) {
+                       nma_cert_chooser_set_key (this, NULL, NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
+                       nma_cert_chooser_set_cert_password (this, "");
                }
+               if (ca_cert && is_pkcs12 (ca_cert))
+                       nma_cert_chooser_set_cert (other, NULL, NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
        }
 }
 
@@ -132,8 +161,8 @@ tls_setup (GtkBuilder *builder,
        nma_cert_chooser_setup_key_password_storage (cert, 0, (NMSetting *) s_vpn,
                                                     NM_OPENVPN_KEY_CERTPASS, TRUE, FALSE);
 
-       /* Link choosers to the PKCS#12 changer callback */
-       g_signal_connect_object (ca_chooser, "changed", G_CALLBACK (tls_cert_changed_cb), cert, 0);
+       /* Link choosers to the PKCS#12 changer callbacks */
+       g_signal_connect_object (ca_chooser, "changed", G_CALLBACK (tls_ca_changed_cb), cert, 0);
        g_signal_connect_object (cert, "changed", G_CALLBACK (tls_cert_changed_cb), ca_chooser, 0);
 }
 
@@ -815,8 +844,7 @@ populate_cipher_combo (GtkComboBox *box, const char *user_cipher)
 
                /* Don't add anything until after the first blank line. Also,
                 * any blank line indicates the start of a comment, ended by
-                * another blank line.
-                */
+                * another blank line. */
                if (!strlen (*item)) {
                        ignore_lines = !ignore_lines;
                        continue;
@@ -1224,8 +1252,7 @@ proxy_type_changed (GtkComboBox *combo, gpointer user_data)
        }
 
        /* Proxy options require TCP; but don't reset the TCP checkbutton
-        * to false when the user disables HTTP proxy; leave it checked.
-        */
+        * to false when the user disables HTTP proxy; leave it checked. */
        widget = GTK_WIDGET (gtk_builder_get_object (builder, "tcp_checkbutton"));
        if (sensitive == TRUE)
                gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
diff --git a/properties/tests/conf/compress.ovpn b/properties/tests/conf/compress.ovpn
index 4c2a4ab..72a06b1 100644
--- a/properties/tests/conf/compress.ovpn
+++ b/properties/tests/conf/compress.ovpn
@@ -1,6 +1,7 @@
 remote 173.8.149.245 666
 dev tun
 client
+ca ca.crt
 
 comp-lzo
 compress lzo
diff --git a/properties/tests/conf/pkcs12-with-ca.ovpn b/properties/tests/conf/pkcs12-with-ca.ovpn
new file mode 100644
index 0000000..cfbeb79
--- /dev/null
+++ b/properties/tests/conf/pkcs12-with-ca.ovpn
@@ -0,0 +1,18 @@
+remote 173.8.149.245 1194
+resolv-retry infinite
+
+dev tun
+persist-key
+persist-tun
+link-mtu 1400
+proto udp
+nobind
+pull
+tls-client
+
+ca ca.crt
+pkcs12 keys/mine.p12
+
+compress
+verb 3
+
diff --git a/properties/tests/conf/proto-tcp-client.ovpn b/properties/tests/conf/proto-tcp-client.ovpn
index fcce845..daaab75 100644
--- a/properties/tests/conf/proto-tcp-client.ovpn
+++ b/properties/tests/conf/proto-tcp-client.ovpn
@@ -1,5 +1,6 @@
 remote 173.8.149.245 666
 dev tun
 client
+ca cacert.pem
 
 proto tcp-client
diff --git a/properties/tests/conf/proto-tcp.ovpn b/properties/tests/conf/proto-tcp.ovpn
index e7c6977..dfd36fb 100644
--- a/properties/tests/conf/proto-tcp.ovpn
+++ b/properties/tests/conf/proto-tcp.ovpn
@@ -1,5 +1,6 @@
 remote 173.8.149.245 666
 dev tun
 client
+ca cacert.pem
 
 proto tcp
diff --git a/properties/tests/conf/proto-tcp4-client.ovpn b/properties/tests/conf/proto-tcp4-client.ovpn
index 6f5d833..bb126bf 100644
--- a/properties/tests/conf/proto-tcp4-client.ovpn
+++ b/properties/tests/conf/proto-tcp4-client.ovpn
@@ -1,5 +1,6 @@
 remote 173.8.149.245 666
 dev tun
 client
+ca cacert.pem
 
 proto tcp4-client
diff --git a/properties/tests/conf/proto-tcp4.ovpn b/properties/tests/conf/proto-tcp4.ovpn
index 6f8a5c0..85c3b46 100644
--- a/properties/tests/conf/proto-tcp4.ovpn
+++ b/properties/tests/conf/proto-tcp4.ovpn
@@ -1,5 +1,6 @@
 remote 173.8.149.245 666
 dev tun
 client
+ca cacert.pem
 
 proto tcp4
diff --git a/properties/tests/conf/proto-tcp6-client.ovpn b/properties/tests/conf/proto-tcp6-client.ovpn
index aeb16df..2c24d24 100644
--- a/properties/tests/conf/proto-tcp6-client.ovpn
+++ b/properties/tests/conf/proto-tcp6-client.ovpn
@@ -1,5 +1,6 @@
 remote 173.8.149.245 666
 dev tun
 client
+ca cacert.pem
 
 proto tcp6-client
diff --git a/properties/tests/conf/proto-tcp6.ovpn b/properties/tests/conf/proto-tcp6.ovpn
index 454b8e3..00d4a89 100644
--- a/properties/tests/conf/proto-tcp6.ovpn
+++ b/properties/tests/conf/proto-tcp6.ovpn
@@ -1,5 +1,6 @@
 remote 173.8.149.245 666
 dev tun
 client
+ca cacert.pem
 
 proto tcp6
diff --git a/properties/tests/conf/proto-udp.ovpn b/properties/tests/conf/proto-udp.ovpn
index c68b4c7..20fa007 100644
--- a/properties/tests/conf/proto-udp.ovpn
+++ b/properties/tests/conf/proto-udp.ovpn
@@ -1,5 +1,6 @@
 remote 173.8.149.245 666
 dev tun
 client
+ca cacert.pem
 
 proto udp
diff --git a/properties/tests/conf/proto-udp4.ovpn b/properties/tests/conf/proto-udp4.ovpn
index 21d309e..533448a 100644
--- a/properties/tests/conf/proto-udp4.ovpn
+++ b/properties/tests/conf/proto-udp4.ovpn
@@ -1,5 +1,6 @@
 remote 173.8.149.245 666
 dev tun
 client
+ca cacert.pem
 
 proto udp4
diff --git a/properties/tests/conf/proto-udp6.ovpn b/properties/tests/conf/proto-udp6.ovpn
index 14b1d69..ad169a6 100644
--- a/properties/tests/conf/proto-udp6.ovpn
+++ b/properties/tests/conf/proto-udp6.ovpn
@@ -1,5 +1,6 @@
 remote 173.8.149.245 666
 dev tun
 client
+ca cacert.pem
 
 proto udp6
diff --git a/properties/tests/conf/push-peer-info.ovpn b/properties/tests/conf/push-peer-info.ovpn
index fb439c4..3e289d4 100644
--- a/properties/tests/conf/push-peer-info.ovpn
+++ b/properties/tests/conf/push-peer-info.ovpn
@@ -1,5 +1,6 @@
 remote 173.8.149.245 666
 dev tun
 client
+ca ca.crt
 
 push-peer-info
diff --git a/properties/tests/test-import-export.c b/properties/tests/test-import-export.c
index 260e353..c8b43e8 100644
--- a/properties/tests/test-import-export.c
+++ b/properties/tests/test-import-export.c
@@ -545,6 +545,47 @@ test_pkcs12_import (void)
        _check_secret (s_vpn, NM_OPENVPN_KEY_CERTPASS, NULL);
 }
 
+static void
+test_pkcs12_with_ca_import (void)
+{
+       _CREATE_PLUGIN (plugin);
+       gs_unref_object NMConnection *connection = NULL;
+       NMSettingConnection *s_con;
+       NMSettingVpn *s_vpn;
+       const char *expected_id = "pkcs12-with-ca";
+
+       connection = get_basic_connection (plugin, SRCDIR, "pkcs12-with-ca.ovpn");
+
+       s_con = _get_setting_connection (connection);
+       g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
+       g_assert (!nm_setting_connection_get_uuid (s_con));
+
+       s_vpn = _get_setting_vpn (connection);
+
+       _check_item (s_vpn, NM_OPENVPN_KEY_CONNECTION_TYPE, NM_OPENVPN_CONTYPE_TLS);
+       _check_item (s_vpn, NM_OPENVPN_KEY_DEV, "tun");
+       _check_item (s_vpn, NM_OPENVPN_KEY_PROTO_TCP, NULL);
+       _check_item (s_vpn, NM_OPENVPN_KEY_COMP_LZO, NULL);
+       _check_item (s_vpn, NM_OPENVPN_KEY_COMPRESS, "yes");
+       _check_item (s_vpn, NM_OPENVPN_KEY_FLOAT, NULL);
+       _check_item (s_vpn, NM_OPENVPN_KEY_RENEG_SECONDS, NULL);
+       _check_item (s_vpn, NM_OPENVPN_KEY_REMOTE, "173.8.149.245:1194");
+       _check_item (s_vpn, NM_OPENVPN_KEY_PORT, NULL);
+       _check_item (s_vpn, NM_OPENVPN_KEY_STATIC_KEY, NULL);
+       _check_item (s_vpn, NM_OPENVPN_KEY_STATIC_KEY_DIRECTION, NULL);
+       _check_item (s_vpn, NM_OPENVPN_KEY_CIPHER, NULL);
+       _check_item (s_vpn, NM_OPENVPN_KEY_LOCAL_IP, NULL);
+       _check_item (s_vpn, NM_OPENVPN_KEY_REMOTE_IP, NULL);
+       _check_item (s_vpn, NM_OPENVPN_KEY_AUTH, NULL);
+
+       _check_item (s_vpn, NM_OPENVPN_KEY_CA,   SRCDIR"/ca.crt");
+       _check_item (s_vpn, NM_OPENVPN_KEY_CERT, SRCDIR"/keys/mine.p12");
+       _check_item (s_vpn, NM_OPENVPN_KEY_KEY,  SRCDIR"/keys/mine.p12");
+
+       _check_secret (s_vpn, NM_OPENVPN_KEY_PASSWORD, NULL);
+       _check_secret (s_vpn, NM_OPENVPN_KEY_CERTPASS, NULL);
+}
+
 static void
 test_non_utf8_import (void)
 {
@@ -1248,6 +1289,9 @@ int main (int argc, char **argv)
        _add_test_func_simple (test_pkcs12_import);
        _add_test_func ("pkcs12-export", test_export_compare, "pkcs12.ovpn", "pkcs12.ovpntest");
 
+       _add_test_func_simple (test_pkcs12_with_ca_import);
+       _add_test_func ("pkcs12-with-ca-export", test_export_compare, "pkcs12-with-ca.ovpn", 
"pkcs12-with-ca.ovpntest");
+
        _add_test_func_simple (test_non_utf8_import);
 
        _add_test_func ("static-import-1", test_static_key_import, "static.ovpn", "static", "1");
diff --git a/src/nm-openvpn-service.c b/src/nm-openvpn-service.c
index e9fa084..034556f 100644
--- a/src/nm-openvpn-service.c
+++ b/src/nm-openvpn-service.c
@@ -357,18 +357,14 @@ args_add_vpn_certs (GPtrArray *args, NMSettingVpn *s_vpn)
        key  = nm_utils_str_utf8safe_unescape (key,  &key_free);
 
        if (   nmovpn_arg_is_set (ca)
-           && nmovpn_arg_is_set (cert)
-           && nmovpn_arg_is_set (key)
-           && nm_streq (ca, cert)
-           && nm_streq (ca, key))
-               args_add_strv (args, "--pkcs12", ca);
+           && !is_pkcs12 (ca))
+               args_add_strv (args, "--ca", ca);
+
+       if (nmovpn_arg_is_set (cert) && is_pkcs12 (cert))
+               args_add_strv (args, "--pkcs12", cert);
        else {
-               if (nmovpn_arg_is_set (ca))
-                       args_add_strv (args, "--ca", ca);
-               if (nmovpn_arg_is_set (cert))
-                       args_add_strv (args, "--cert", cert);
-               if (nmovpn_arg_is_set (key))
-                       args_add_strv (args, "--key", key);
+               args_add_strv (args, "--cert", cert);
+               args_add_strv (args, "--key", key);
        }
 }
 


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