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