[network-manager-openvpn/lr/p11-forward: 4/4] service: add support for p11-kit remoting



commit 9604f3310f7f165a552ef786489656ae0646cd3b
Author: Lubomir Rintel <lkundrak v3 sk>
Date:   Mon Jun 20 13:52:09 2016 +0200

    service: add support for p11-kit remoting

 configure.ac                |    4 +-
 shared/nm-service-defines.h |    1 +
 shared/utils.h              |    1 +
 src/nm-openvpn-service.c    |  162 +++++++++++++++++++++++++++++++++++++++----
 4 files changed, 152 insertions(+), 16 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index fd34617..6641a63 100644
--- a/configure.ac
+++ b/configure.ac
@@ -101,13 +101,13 @@ if test x"$with_gnome" != xno; then
                        libnm-glib-vpn >= 1.2.0);
 
                LIBNM_GLIB_CFLAGS="$LIBNM_GLIB_CFLAGS -DNM_VERSION_MIN_REQUIRED=NM_VERSION_1_2"
-               LIBNM_GLIB_CFLAGS="$LIBNM_GLIB_CFLAGS -DNM_VERSION_MAX_ALLOWED=NM_VERSION_1_2"
+               LIBNM_GLIB_CFLAGS="$LIBNM_GLIB_CFLAGS -DNM_VERSION_MAX_ALLOWED=NM_VERSION_1_4"
        fi
 fi
 
 PKG_CHECK_MODULES(LIBNM, libnm >= 1.2.0)
 LIBNM_CFLAGS="$LIBNM_CFLAGS -DNM_VERSION_MIN_REQUIRED=NM_VERSION_1_2"
-LIBNM_CFLAGS="$LIBNM_CFLAGS -DNM_VERSION_MAX_ALLOWED=NM_VERSION_1_2"
+LIBNM_CFLAGS="$LIBNM_CFLAGS -DNM_VERSION_MAX_ALLOWED=NM_VERSION_1_4"
 
 NM_VPN_SERVICE_DIR=`$PKG_CONFIG --define-variable prefix='\${prefix}' --variable vpnservicedir libnm`
 AC_SUBST(NM_VPN_SERVICE_DIR)
diff --git a/shared/nm-service-defines.h b/shared/nm-service-defines.h
index 92706ef..d5579a8 100644
--- a/shared/nm-service-defines.h
+++ b/shared/nm-service-defines.h
@@ -44,6 +44,7 @@
 #define NM_OPENVPN_KEY_PING "ping"
 #define NM_OPENVPN_KEY_PING_EXIT "ping-exit"
 #define NM_OPENVPN_KEY_PING_RESTART "ping-restart"
+#define NM_OPENVPN_KEY_PKCS11_ID "pkcs11-id"
 #define NM_OPENVPN_KEY_PORT "port"
 #define NM_OPENVPN_KEY_PROTO_TCP "proto-tcp"
 #define NM_OPENVPN_KEY_PROXY_TYPE "proxy-type"
diff --git a/shared/utils.h b/shared/utils.h
index 6370871..890599b 100644
--- a/shared/utils.h
+++ b/shared/utils.h
@@ -50,6 +50,7 @@
 #define NMV_OVPN_TAG_PING_EXIT          "ping-exit"
 #define NMV_OVPN_TAG_PING               "ping"
 #define NMV_OVPN_TAG_PING_RESTART       "ping-restart"
+#define NMV_OVPN_TAG_PKCS11_ID          "pkcs11-id"
 #define NMV_OVPN_TAG_PKCS12             "pkcs12"
 #define NMV_OVPN_TAG_PORT               "port"
 #define NMV_OVPN_TAG_PROTO              "proto"
diff --git a/src/nm-openvpn-service.c b/src/nm-openvpn-service.c
index 37eb4a0..2efb6c6 100644
--- a/src/nm-openvpn-service.c
+++ b/src/nm-openvpn-service.c
@@ -90,6 +90,7 @@ typedef struct {
        NMOpenvpnPluginIOData *io_data;
        gboolean interactive;
        char *mgt_path;
+       int p11_fd;
 } NMOpenvpnPluginPrivate;
 
 typedef struct {
@@ -123,6 +124,7 @@ static ValidProperty valid_properties[] = {
        { NM_OPENVPN_KEY_PING,                 G_TYPE_INT, 0, G_MAXINT, FALSE },
        { NM_OPENVPN_KEY_PING_EXIT,            G_TYPE_INT, 0, G_MAXINT, FALSE },
        { NM_OPENVPN_KEY_PING_RESTART,         G_TYPE_INT, 0, G_MAXINT, FALSE },
+       { NM_OPENVPN_KEY_PKCS11_ID,            G_TYPE_STRING, 0, 0, FALSE },
        { NM_OPENVPN_KEY_PROTO_TCP,            G_TYPE_BOOLEAN, 0, 0, FALSE },
        { NM_OPENVPN_KEY_PORT,                 G_TYPE_INT, 1, 65535, FALSE },
        { NM_OPENVPN_KEY_PROXY_TYPE,           G_TYPE_STRING, 0, 0, FALSE },
@@ -152,6 +154,7 @@ static ValidProperty valid_properties[] = {
        { NM_OPENVPN_KEY_CERTPASS"-flags",     G_TYPE_STRING, 0, 0, FALSE },
        { NM_OPENVPN_KEY_NOSECRET,             G_TYPE_STRING, 0, 0, FALSE },
        { NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD"-flags", G_TYPE_STRING, 0, 0, FALSE },
+       { NM_OPENVPN_KEY_PKCS11_PIN"-flags",   G_TYPE_STRING, 0, 0, FALSE },
        { NULL,                                G_TYPE_NONE, FALSE }
 };
 
@@ -160,6 +163,7 @@ static ValidProperty valid_secrets[] = {
        { NM_OPENVPN_KEY_CERTPASS,             G_TYPE_STRING, 0, 0, FALSE },
        { NM_OPENVPN_KEY_NOSECRET,             G_TYPE_STRING, 0, 0, FALSE },
        { NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD,  G_TYPE_STRING, 0, 0, FALSE },
+       { NM_OPENVPN_KEY_PKCS11_PIN,           G_TYPE_STRING, 0, 0, FALSE },
        { NULL,                                G_TYPE_NONE, FALSE }
 };
 
@@ -976,14 +980,14 @@ add_openvpn_arg_int (GPtrArray *args, const char *arg)
        return TRUE;
 }
 
-static void
-add_cert_args (GPtrArray *args, NMSettingVpn *s_vpn)
+static gboolean
+add_cert_args (GPtrArray *args, NMSettingVpn *s_vpn, GError **error)
 {
-       const char *ca, *cert, *key;
+       const char *ca, *cert, *key, *pkcs11_id;
        gs_free char *ca_free = NULL, *cert_free = NULL, *key_free = NULL;
 
-       g_return_if_fail (args != NULL);
-       g_return_if_fail (s_vpn != NULL);
+       g_return_val_if_fail (args != NULL, FALSE);
+       g_return_val_if_fail (s_vpn != NULL, FALSE);
 
        ca   = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_CA);
        cert = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_CERT);
@@ -993,6 +997,31 @@ add_cert_args (GPtrArray *args, NMSettingVpn *s_vpn)
        cert = nmv_utils_str_utf8safe_unescape_c (cert, &cert_free);
        key  = nmv_utils_str_utf8safe_unescape_c (key,  &key_free);
 
+       pkcs11_id = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_PKCS11_ID);
+       if (pkcs11_id) {
+               if (!g_getenv ("P11_REMOTE_FD")) {
+                       g_set_error_literal (error,
+                                            NM_VPN_PLUGIN_ERROR,
+                                            NM_VPN_PLUGIN_ERROR_FAILED,
+                                            _("PKCS#11 remoting not available."));
+                       return FALSE;
+               }
+
+               /* The openvpn might not be configured to default to use p11-kit. */
+               add_openvpn_arg (args, "--pkcs11-providers");
+               add_openvpn_arg (args, "p11-kit-proxy.so");
+
+               if (ca && strlen (ca)) {
+                       add_openvpn_arg (args, "--ca");
+                       add_openvpn_arg (args, ca);
+               }
+
+               add_openvpn_arg (args, "--pkcs11-id");
+               add_openvpn_arg (args, pkcs11_id);
+
+               return TRUE;
+       }
+
        if (   ca && strlen (ca)
            && cert && strlen (cert)
            && key && strlen (key)
@@ -1016,6 +1045,8 @@ add_cert_args (GPtrArray *args, NMSettingVpn *s_vpn)
                        add_openvpn_arg (args, key);
                }
        }
+
+       return TRUE;
 }
 
 static void
@@ -1552,7 +1583,10 @@ nm_openvpn_start_openvpn_binary (NMOpenvpnPlugin *plugin,
        /* Now append configuration options which are dependent on the configuration type */
        if (!strcmp (connection_type, NM_OPENVPN_CONTYPE_TLS)) {
                add_openvpn_arg (args, "--client");
-               add_cert_args (args, s_vpn);
+               if (!add_cert_args (args, s_vpn, error)) {
+                       free_openvpn_args (args);
+                       return FALSE;
+               }
        } else if (!strcmp (connection_type, NM_OPENVPN_CONTYPE_STATIC_KEY)) {
                tmp = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_STATIC_KEY);
                if (tmp && strlen (tmp)) {
@@ -1602,7 +1636,10 @@ nm_openvpn_start_openvpn_binary (NMOpenvpnPlugin *plugin,
                }
        } else if (!strcmp (connection_type, NM_OPENVPN_CONTYPE_PASSWORD_TLS)) {
                add_openvpn_arg (args, "--client");
-               add_cert_args (args, s_vpn);
+               if (!add_cert_args (args, s_vpn, error)) {
+                       free_openvpn_args (args);
+                       return FALSE;
+               }
                /* Use user/path authentication */
                add_openvpn_arg (args, "--auth-user-pass");
        } else {
@@ -1672,7 +1709,8 @@ nm_openvpn_start_openvpn_binary (NMOpenvpnPlugin *plugin,
        }
 
        if (!g_spawn_async (NULL, (char **) args->pdata, NULL,
-                           G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, error)) {
+                           G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_LEAVE_DESCRIPTORS_OPEN,
+                           NULL, NULL, &pid, error)) {
                free_openvpn_args (args);
                return FALSE;
        }
@@ -1781,9 +1819,12 @@ _connect_common (NMVpnServicePlugin   *plugin,
                  GVariant      *details,
                  GError       **error)
 {
+       NMOpenvpnPluginPrivate *priv = NM_OPENVPN_PLUGIN_GET_PRIVATE (plugin);
        NMSettingVpn *s_vpn;
        const char *connection_type;
        const char *user_name;
+       gboolean success = FALSE;
+       gs_free gchar *fd_str = NULL;
 
        if (!real_disconnect (plugin, error)) {
                _LOGW ("Could not clean up previous daemon run: %s", (*error)->message);
@@ -1796,7 +1837,7 @@ _connect_common (NMVpnServicePlugin   *plugin,
                                     NM_VPN_PLUGIN_ERROR,
                                     NM_VPN_PLUGIN_ERROR_INVALID_CONNECTION,
                                     _("Could not process the request because the VPN connection settings 
were invalid."));
-               return FALSE;
+               goto out;
        }
 
        connection_type = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_CONNECTION_TYPE);
@@ -1805,16 +1846,28 @@ _connect_common (NMVpnServicePlugin   *plugin,
                                     NM_VPN_PLUGIN_ERROR,
                                     NM_VPN_PLUGIN_ERROR_INVALID_CONNECTION,
                                     _("Could not process the request because the openvpn connection type was 
invalid."));
-               return FALSE;
+               goto out;
        }
 
        /* Validate the properties */
        if (!nm_openvpn_properties_validate (s_vpn, error))
-               return FALSE;
+               goto out;
 
        /* Validate secrets */
        if (!nm_openvpn_secrets_validate (s_vpn, error))
-               return FALSE;
+               goto out;
+
+       if (priv->p11_fd) {
+               fd_str = g_strdup_printf ("%d", priv->p11_fd);
+
+               if (!g_setenv ("P11_REMOTE_FD", fd_str, 1)) {
+                       g_set_error (error,
+                                    NM_VPN_PLUGIN_ERROR,
+                                    NM_VPN_PLUGIN_ERROR_FAILED,
+                                    _("Could not set variable P11_REMOTE_FD=%s"), fd_str);
+                       goto out;
+               }
+       }
 
        /* Finally try to start OpenVPN */
        user_name = nm_setting_vpn_get_user_name (s_vpn);
@@ -1823,9 +1876,16 @@ _connect_common (NMVpnServicePlugin   *plugin,
                                              user_name,
                                              nm_connection_get_uuid (connection),
                                              error))
-               return FALSE;
+               goto out;
 
-       return TRUE;
+       success = TRUE;
+
+out:
+       g_unsetenv ("P11_REMOTE_FD");
+       close (priv->p11_fd);
+       priv->p11_fd = 0;
+
+       return success;
 }
 
 static gboolean
@@ -1933,6 +1993,71 @@ real_new_secrets (NMVpnServicePlugin *plugin,
        return TRUE;
 }
 
+#if NM_CHECK_VERSION(1,3,0)
+static gboolean
+real_need_p11_fd (NMVpnServicePlugin *plugin,
+                      NMConnection *connection,
+                      const char **uri,
+                      GError **error)
+{
+       NMSettingVpn *s_vpn;
+       const char *pkcs11_id;
+
+       g_return_val_if_fail (NM_IS_VPN_SERVICE_PLUGIN (plugin), FALSE);
+       g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
+
+       s_vpn = nm_connection_get_setting_vpn (connection);
+       if (!s_vpn) {
+               g_set_error_literal (error,
+                                    NM_VPN_PLUGIN_ERROR,
+                                    NM_VPN_PLUGIN_ERROR_INVALID_CONNECTION,
+                                    _("Could not process the request because the VPN connection settings 
were invalid."));
+               return FALSE;
+       }
+
+       pkcs11_id = nm_setting_vpn_get_data_item (s_vpn, NM_OPENVPN_KEY_PKCS11_ID);
+       if (pkcs11_id) {
+               *uri = pkcs11_id;
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+static gboolean
+real_p11_fd (NMVpnServicePlugin *plugin,
+                 int fd,
+                 GError **error)
+{
+       int flags;
+       NMOpenvpnPluginPrivate *priv = NM_OPENVPN_PLUGIN_GET_PRIVATE (plugin);
+
+       _LOGD ("VPN received p11-kit remoting fd: %d", fd);
+
+       if (priv->p11_fd) {
+               g_set_error_literal (error,
+                                    NM_VPN_PLUGIN_ERROR,
+                                    NM_VPN_PLUGIN_ERROR_FAILED,
+                                    _("Got an extra p11-kit fd"));
+               return FALSE;
+       }
+
+       flags = fcntl (fd, F_GETFD, 0);
+       flags &= ~FD_CLOEXEC;
+       if (fcntl (fd, F_SETFD, flags) == -1) {
+               g_set_error_literal (error,
+                                    NM_VPN_PLUGIN_ERROR,
+                                    NM_VPN_PLUGIN_ERROR_FAILED,
+                                    _("Could not clear close-on exec on p11-kit remoting fd"));
+               return FALSE;
+       }
+
+       priv->p11_fd = fd;
+
+       return TRUE;
+}
+#endif
+
 static void
 nm_openvpn_plugin_init (NMOpenvpnPlugin *plugin)
 {
@@ -1946,6 +2071,11 @@ dispose (GObject *object)
        nm_clear_g_source (&priv->connect_timer);
        real_disconnect (NM_VPN_SERVICE_PLUGIN (object), NULL);
 
+       if (priv->p11_fd) {
+               close (priv->p11_fd);
+               priv->p11_fd = 0;
+       }
+
        G_OBJECT_CLASS (nm_openvpn_plugin_parent_class)->dispose (object);
 }
 
@@ -1965,6 +2095,10 @@ nm_openvpn_plugin_class_init (NMOpenvpnPluginClass *plugin_class)
        parent_class->need_secrets = real_need_secrets;
        parent_class->disconnect   = real_disconnect;
        parent_class->new_secrets  = real_new_secrets;
+#if NM_CHECK_VERSION(1,3,0)
+       parent_class->need_p11_fd = real_need_p11_fd;
+       parent_class->p11_fd  = real_p11_fd;
+#endif
 }
 
 static void


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