|
Packit Service |
d328f3 |
// SPDX-License-Identifier: GPL-2.0+
|
|
Packit Service |
d328f3 |
/* NetworkManager Connection editor -- Connection editor for NetworkManager
|
|
Packit Service |
d328f3 |
*
|
|
Packit Service |
d328f3 |
* Dan Williams <dcbw@redhat.com>
|
|
Packit Service |
d328f3 |
*
|
|
Packit Service |
d328f3 |
* Copyright 2008 - 2014 Red Hat, Inc.
|
|
Packit Service |
d328f3 |
*/
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
#include "nm-default.h"
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
#include "page-vpn.h"
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
#include <string.h>
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
#include "connection-helpers.h"
|
|
Packit Service |
d328f3 |
#include "nm-connection-editor.h"
|
|
Packit Service |
d328f3 |
#include "vpn-helpers.h"
|
|
Packit Service |
d328f3 |
#include "nm-utils/nm-vpn-editor-plugin-call.h"
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
G_DEFINE_TYPE (CEPageVpn, ce_page_vpn, CE_TYPE_PAGE)
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
#define CE_PAGE_VPN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CE_TYPE_PAGE_VPN, CEPageVpnPrivate))
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
typedef struct {
|
|
Packit Service |
d328f3 |
NMSettingVpn *setting;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
char *service_type;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
NMVpnEditorPlugin *plugin;
|
|
Packit Service |
d328f3 |
NMVpnEditor *editor;
|
|
Packit Service |
d328f3 |
} CEPageVpnPrivate;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
vpn_plugin_changed_cb (NMVpnEditorPlugin *plugin, CEPageVpn *self)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
ce_page_changed (CE_PAGE (self));
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
finish_setup (CEPageVpn *self, gpointer user_data)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
CEPage *parent = CE_PAGE (self);
|
|
Packit Service |
d328f3 |
CEPageVpnPrivate *priv = CE_PAGE_VPN_GET_PRIVATE (self);
|
|
Packit Service |
d328f3 |
GError *local = NULL;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_return_if_fail (NM_IS_VPN_EDITOR_PLUGIN (priv->plugin));
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
priv->editor = nm_vpn_editor_plugin_get_editor (priv->plugin, CE_PAGE (self)->connection, &local);
|
|
Packit Service |
d328f3 |
if (!priv->editor) {
|
|
Packit Service |
d328f3 |
g_warning (_("Could not load editor VPN plugin for ā%sā (%s)."),
|
|
Packit Service |
d328f3 |
priv->service_type, local ? local->message : _("unknown failure"));
|
|
Packit Service |
d328f3 |
g_clear_error (&local);
|
|
Packit Service |
d328f3 |
return;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_signal_connect (priv->editor, "changed", G_CALLBACK (vpn_plugin_changed_cb), self);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
parent->page = GTK_WIDGET (nm_vpn_editor_get_widget (priv->editor));
|
|
Packit Service |
d328f3 |
if (!parent->page) {
|
|
Packit Service |
d328f3 |
g_warning ("Could not load VPN user interface for service '%s'.", priv->service_type);
|
|
Packit Service |
d328f3 |
return;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
g_object_ref_sink (parent->page);
|
|
Packit Service |
d328f3 |
gtk_widget_show_all (parent->page);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
CEPage *
|
|
Packit Service |
d328f3 |
ce_page_vpn_new (NMConnectionEditor *editor,
|
|
Packit Service |
d328f3 |
NMConnection *connection,
|
|
Packit Service |
d328f3 |
GtkWindow *parent_window,
|
|
Packit Service |
d328f3 |
NMClient *client,
|
|
Packit Service |
d328f3 |
const char **out_secrets_setting_name,
|
|
Packit Service |
d328f3 |
GError **error)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
CEPageVpn *self;
|
|
Packit Service |
d328f3 |
CEPageVpnPrivate *priv;
|
|
Packit Service |
d328f3 |
const char *service_type;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
self = CE_PAGE_VPN (ce_page_new (CE_TYPE_PAGE_VPN,
|
|
Packit Service |
d328f3 |
editor,
|
|
Packit Service |
d328f3 |
connection,
|
|
Packit Service |
d328f3 |
parent_window,
|
|
Packit Service |
d328f3 |
client,
|
|
Packit Service |
d328f3 |
NULL,
|
|
Packit Service |
d328f3 |
NULL,
|
|
Packit Service |
d328f3 |
_("VPN")));
|
|
Packit Service |
d328f3 |
if (!self) {
|
|
Packit Service |
d328f3 |
g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("Could not load VPN user interface."));
|
|
Packit Service |
d328f3 |
return NULL;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
priv = CE_PAGE_VPN_GET_PRIVATE (self);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
priv->setting = nm_connection_get_setting_vpn (connection);
|
|
Packit Service |
d328f3 |
g_assert (priv->setting);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
service_type = nm_setting_vpn_get_service_type (priv->setting);
|
|
Packit Service |
d328f3 |
g_assert (service_type);
|
|
Packit Service |
d328f3 |
priv->service_type = g_strdup (service_type);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
priv->plugin = vpn_get_plugin_by_service (service_type);
|
|
Packit Service |
d328f3 |
if (!priv->plugin) {
|
|
Packit Service |
d328f3 |
g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC, _("Could not find VPN plugin for ā%sā."), service_type);
|
|
Packit Service |
d328f3 |
g_object_unref (self);
|
|
Packit Service |
d328f3 |
return NULL;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
priv->plugin = g_object_ref (priv->plugin);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_signal_connect (self, CE_PAGE_INITIALIZED, G_CALLBACK (finish_setup), NULL);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
*out_secrets_setting_name = NM_SETTING_VPN_SETTING_NAME;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
return CE_PAGE (self);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
gboolean
|
|
Packit Service |
d328f3 |
ce_page_vpn_can_export (CEPageVpn *page)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
CEPageVpnPrivate *priv = CE_PAGE_VPN_GET_PRIVATE (page);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
return (nm_vpn_editor_plugin_get_capabilities (priv->plugin) & NM_VPN_EDITOR_PLUGIN_CAPABILITY_EXPORT) != 0;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static gboolean
|
|
Packit Service |
d328f3 |
ce_page_validate_v (CEPage *page, NMConnection *connection, GError **error)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
CEPageVpn *self = CE_PAGE_VPN (page);
|
|
Packit Service |
d328f3 |
CEPageVpnPrivate *priv = CE_PAGE_VPN_GET_PRIVATE (self);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
return nm_vpn_editor_update_connection (priv->editor, connection, error);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
ce_page_vpn_init (CEPageVpn *self)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
dispose (GObject *object)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
CEPageVpnPrivate *priv = CE_PAGE_VPN_GET_PRIVATE (object);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
if (priv->editor) {
|
|
Packit Service |
d328f3 |
g_signal_handlers_disconnect_by_func (priv->editor, G_CALLBACK (vpn_plugin_changed_cb), object);
|
|
Packit Service |
d328f3 |
g_clear_object (&priv->editor);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
g_clear_pointer (&priv->service_type, g_free);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_clear_object (&priv->plugin);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
G_OBJECT_CLASS (ce_page_vpn_parent_class)->dispose (object);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
ce_page_vpn_class_init (CEPageVpnClass *vpn_class)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
GObjectClass *object_class = G_OBJECT_CLASS (vpn_class);
|
|
Packit Service |
d328f3 |
CEPageClass *parent_class = CE_PAGE_CLASS (vpn_class);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_type_class_add_private (object_class, sizeof (CEPageVpnPrivate));
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/* virtual methods */
|
|
Packit Service |
d328f3 |
object_class->dispose = dispose;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
parent_class->ce_page_validate_v = ce_page_validate_v;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
typedef struct {
|
|
Packit Service |
d328f3 |
NMClient *client;
|
|
Packit Service |
d328f3 |
PageNewConnectionResultFunc result_func;
|
|
Packit Service |
d328f3 |
gpointer user_data;
|
|
Packit Service |
d328f3 |
} NewVpnInfo;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
typedef void (*VpnImportSuccessCallback) (NMConnection *connection, gpointer user_data);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
typedef struct {
|
|
Packit Service |
d328f3 |
VpnImportSuccessCallback callback;
|
|
Packit Service |
d328f3 |
gpointer user_data;
|
|
Packit Service |
d328f3 |
} ActionInfo;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
complete_vpn_connection (NMConnection *connection, NMClient *client)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
ce_page_complete_connection (connection,
|
|
Packit Service |
d328f3 |
_("VPN connection %d"),
|
|
Packit Service |
d328f3 |
NM_SETTING_VPN_SETTING_NAME,
|
|
Packit Service |
d328f3 |
FALSE,
|
|
Packit Service |
d328f3 |
client);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
#define NEW_VPN_CONNECTION_PRIMARY_LABEL _("Choose a VPN Connection Type")
|
|
Packit Service |
d328f3 |
#define NEW_VPN_CONNECTION_SECONDARY_LABEL _("Select the type of VPN you wish to use for the new connection. If the type of VPN connection you wish to create does not appear in the list, you may not have the correct VPN plugin installed.")
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static gboolean
|
|
Packit Service |
d328f3 |
vpn_type_filter_func (FUNC_TAG_NEW_CONNECTION_TYPE_FILTER_IMPL,
|
|
Packit Service |
d328f3 |
GType type,
|
|
Packit Service |
d328f3 |
gpointer user_data)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
return type == NM_TYPE_SETTING_VPN;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
vpn_type_result_func (FUNC_TAG_NEW_CONNECTION_RESULT_IMPL,
|
|
Packit Service |
d328f3 |
NMConnection *connection,
|
|
Packit Service |
d328f3 |
gpointer user_data)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
NewVpnInfo *info = user_data;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
info->result_func (FUNC_TAG_PAGE_NEW_CONNECTION_RESULT_CALL, connection, connection == NULL, NULL, info->user_data);
|
|
Packit Service |
d328f3 |
g_slice_free (NewVpnInfo, info);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
void
|
|
Packit Service |
d328f3 |
vpn_connection_new (FUNC_TAG_PAGE_NEW_CONNECTION_IMPL,
|
|
Packit Service |
d328f3 |
GtkWindow *parent,
|
|
Packit Service |
d328f3 |
const char *detail,
|
|
Packit Service |
d328f3 |
gpointer detail_data,
|
|
Packit Service |
d328f3 |
NMConnection *connection,
|
|
Packit Service |
d328f3 |
NMClient *client,
|
|
Packit Service |
d328f3 |
PageNewConnectionResultFunc result_func,
|
|
Packit Service |
d328f3 |
gpointer user_data)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
NMSetting *s_vpn;
|
|
Packit Service |
d328f3 |
const char *service_type;
|
|
Packit Service |
d328f3 |
gs_free char *service_type_free = NULL;
|
|
Packit Service |
d328f3 |
gs_free char *add_detail_key_free = NULL;
|
|
Packit Service |
d328f3 |
gs_free char *add_detail_val_free = NULL;
|
|
Packit Service |
d328f3 |
const CEPageVpnDetailData *vpn_data = detail_data;
|
|
Packit Service |
d328f3 |
gssize split_idx, l;
|
|
Packit Service |
d328f3 |
const char *add_detail_key = NULL;
|
|
Packit Service |
d328f3 |
const char *add_detail_val = NULL;
|
|
Packit Service |
d328f3 |
gs_unref_object NMConnection *connection_tmp = NULL;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
if (!detail && !connection) {
|
|
Packit Service |
d328f3 |
NewVpnInfo *info;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/* This will happen if nm-c-e is launched from the command line
|
|
Packit Service |
d328f3 |
* with "--create --type vpn". Dump the user back into the
|
|
Packit Service |
d328f3 |
* new connection dialog to let them pick a subtype now.
|
|
Packit Service |
d328f3 |
*/
|
|
Packit Service |
d328f3 |
info = g_slice_new (NewVpnInfo);
|
|
Packit Service |
d328f3 |
info->result_func = result_func;
|
|
Packit Service |
d328f3 |
info->user_data = user_data;
|
|
Packit Service |
d328f3 |
new_connection_dialog_full (parent, client,
|
|
Packit Service |
d328f3 |
NEW_VPN_CONNECTION_PRIMARY_LABEL,
|
|
Packit Service |
d328f3 |
NEW_VPN_CONNECTION_SECONDARY_LABEL,
|
|
Packit Service |
d328f3 |
vpn_type_filter_func,
|
|
Packit Service |
d328f3 |
vpn_type_result_func, info);
|
|
Packit Service |
d328f3 |
return;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
connection = _ensure_connection_other (connection, &connection_tmp);
|
|
Packit Service |
d328f3 |
if (detail) {
|
|
Packit Service |
d328f3 |
service_type = detail;
|
|
Packit Service |
d328f3 |
add_detail_key = vpn_data ? vpn_data->add_detail_key : NULL;
|
|
Packit Service |
d328f3 |
add_detail_val = vpn_data ? vpn_data->add_detail_val : NULL;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
service_type_free = nm_vpn_plugin_info_list_find_service_type (vpn_get_plugin_infos (), detail);
|
|
Packit Service |
d328f3 |
if (service_type_free)
|
|
Packit Service |
d328f3 |
service_type = service_type_free;
|
|
Packit Service |
d328f3 |
else if (!vpn_data) {
|
|
Packit Service |
d328f3 |
/* when called without @vpn_data, it means that @detail may contain "<SERVICE_TYPE>:<ADD_DETAIL>".
|
|
Packit Service |
d328f3 |
* Try to parse them by spliting @detail at the colons and try to interpret the first part as
|
|
Packit Service |
d328f3 |
* @service_type and the remainder as add-detail. */
|
|
Packit Service |
d328f3 |
l = strlen (detail);
|
|
Packit Service |
d328f3 |
for (split_idx = 1; split_idx < l - 1; split_idx++) {
|
|
Packit Service |
d328f3 |
if (detail[split_idx] == ':') {
|
|
Packit Service |
d328f3 |
gs_free char *detail_main = g_strndup (detail, split_idx);
|
|
Packit Service |
d328f3 |
NMVpnEditorPlugin *plugin;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
service_type_free = nm_vpn_plugin_info_list_find_service_type (vpn_get_plugin_infos (), detail_main);
|
|
Packit Service |
d328f3 |
if (!service_type_free)
|
|
Packit Service |
d328f3 |
continue;
|
|
Packit Service |
d328f3 |
plugin = vpn_get_plugin_by_service (service_type_free);
|
|
Packit Service |
d328f3 |
if (!plugin) {
|
|
Packit Service |
d328f3 |
g_clear_pointer (&service_type_free, g_free);
|
|
Packit Service |
d328f3 |
continue;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/* we found a @service_type. Try to use the remainder as add-detail. */
|
|
Packit Service |
d328f3 |
service_type = service_type_free;
|
|
Packit Service |
d328f3 |
if (nm_vpn_editor_plugin_get_service_add_detail (plugin, service_type, &detail[split_idx + 1],
|
|
Packit Service |
d328f3 |
NULL, NULL,
|
|
Packit Service |
d328f3 |
&add_detail_key_free, &add_detail_val_free, NULL)
|
|
Packit Service |
d328f3 |
&& add_detail_key_free && add_detail_key_free[0]
|
|
Packit Service |
d328f3 |
&& add_detail_val_free && add_detail_val_free[0]) {
|
|
Packit Service |
d328f3 |
add_detail_key = add_detail_key_free;
|
|
Packit Service |
d328f3 |
add_detail_val = add_detail_val_free;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
break;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
if (!service_type)
|
|
Packit Service |
d328f3 |
service_type = detail;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
s_vpn = nm_setting_vpn_new ();
|
|
Packit Service |
d328f3 |
g_object_set (s_vpn, NM_SETTING_VPN_SERVICE_TYPE, service_type, NULL);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
if (add_detail_key)
|
|
Packit Service |
d328f3 |
nm_setting_vpn_add_data_item ((NMSettingVpn *) s_vpn, add_detail_key, add_detail_val);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
nm_connection_add_setting (connection, s_vpn);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
complete_vpn_connection (connection, client);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
(*result_func) (FUNC_TAG_PAGE_NEW_CONNECTION_RESULT_CALL, connection, FALSE, NULL, user_data);
|
|
Packit Service |
d328f3 |
}
|