Blame src/connection-editor/vpn-helpers.c

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 - 2017 Red Hat, Inc.
Packit Service d328f3
 */
Packit Service d328f3
Packit Service d328f3
#include "nm-default.h"
Packit Service d328f3
Packit Service d328f3
#include <string.h>
Packit Service d328f3
#include <gmodule.h>
Packit Service d328f3
Packit Service d328f3
#include "vpn-helpers.h"
Packit Service d328f3
#include "utils.h"
Packit Service d328f3
Packit Service d328f3
NMVpnEditorPlugin *
Packit Service d328f3
vpn_get_plugin_by_service (const char *service)
Packit Service d328f3
{
Packit Service d328f3
	NMVpnPluginInfo *plugin_info;
Packit Service d328f3
Packit Service d328f3
	plugin_info = nm_vpn_plugin_info_list_find_by_service (vpn_get_plugin_infos (), service);
Packit Service d328f3
	if (plugin_info)
Packit Service d328f3
		return nm_vpn_plugin_info_get_editor_plugin (plugin_info);
Packit Service d328f3
	return NULL;
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
static gint
Packit Service d328f3
_sort_vpn_plugins (NMVpnPluginInfo *aa, NMVpnPluginInfo *bb)
Packit Service d328f3
{
Packit Service d328f3
	return strcmp (nm_vpn_plugin_info_get_name (aa), nm_vpn_plugin_info_get_name (bb));
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
GSList *
Packit Service d328f3
vpn_get_plugin_infos (void)
Packit Service d328f3
{
Packit Service d328f3
	static gboolean plugins_loaded = FALSE;
Packit Service d328f3
	static GSList *plugins = NULL;
Packit Service d328f3
	GSList *p;
Packit Service d328f3
Packit Service d328f3
	if (G_LIKELY (plugins_loaded))
Packit Service d328f3
		return plugins;
Packit Service d328f3
	plugins_loaded = TRUE;
Packit Service d328f3
Packit Service d328f3
	p = nm_vpn_plugin_info_list_load ();
Packit Service d328f3
	plugins = NULL;
Packit Service d328f3
	while (p) {
Packit Service d328f3
		NMVpnPluginInfo *plugin_info = NM_VPN_PLUGIN_INFO (p->data);
Packit Service d328f3
		GError *error = NULL;
Packit Service d328f3
Packit Service d328f3
		/* load the editor plugin, and preserve only those NMVpnPluginInfo that can
Packit Service d328f3
		 * successfully load the plugin. */
Packit Service d328f3
		if (nm_vpn_plugin_info_load_editor_plugin (plugin_info, &error)) {
Packit Service d328f3
			plugins = g_slist_prepend (plugins, plugin_info);
Packit Service d328f3
			g_info ("vpn: (%s,%s) loaded",
Packit Service d328f3
			        nm_vpn_plugin_info_get_name (plugin_info),
Packit Service d328f3
			        nm_vpn_plugin_info_get_filename (plugin_info));
Packit Service d328f3
		} else {
Packit Service d328f3
			if (   !nm_vpn_plugin_info_get_plugin (plugin_info)
Packit Service d328f3
			    && nm_vpn_plugin_info_lookup_property (plugin_info, NM_VPN_PLUGIN_INFO_KF_GROUP_GNOME, "properties")) {
Packit Service d328f3
				g_message ("vpn: (%s,%s) cannot load legacy-only plugin",
Packit Service d328f3
				           nm_vpn_plugin_info_get_name (plugin_info),
Packit Service d328f3
				           nm_vpn_plugin_info_get_filename (plugin_info));
Packit Service d328f3
			} else if (g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) {
Packit Service d328f3
				g_message ("vpn: (%s,%s) file \"%s\" not found. Did you install the client package?",
Packit Service d328f3
				           nm_vpn_plugin_info_get_name (plugin_info),
Packit Service d328f3
				           nm_vpn_plugin_info_get_filename (plugin_info),
Packit Service d328f3
				           nm_vpn_plugin_info_get_plugin (plugin_info));
Packit Service d328f3
			} else {
Packit Service d328f3
				g_warning ("vpn: (%s,%s) could not load plugin: %s",
Packit Service d328f3
				           nm_vpn_plugin_info_get_name (plugin_info),
Packit Service d328f3
				           nm_vpn_plugin_info_get_filename (plugin_info),
Packit Service d328f3
				           error->message);
Packit Service d328f3
			}
Packit Service d328f3
			g_clear_error (&error);
Packit Service d328f3
			g_object_unref (plugin_info);
Packit Service d328f3
		}
Packit Service d328f3
		p = g_slist_delete_link (p, p);
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
	/* sort the list of plugins alphabetically. */
Packit Service d328f3
	plugins = g_slist_sort (plugins, (GCompareFunc) _sort_vpn_plugins);
Packit Service d328f3
	return plugins;
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
static void
Packit Service d328f3
export_vpn_to_file_cb (GtkWidget *dialog, gint response, gpointer user_data)
Packit Service d328f3
{
Packit Service d328f3
	NMConnection *connection = NM_CONNECTION (user_data);
Packit Service d328f3
	char *filename = NULL;
Packit Service d328f3
	GError *error = NULL;
Packit Service d328f3
	NMVpnEditorPlugin *plugin;
Packit Service d328f3
	NMSettingConnection *s_con = NULL;
Packit Service d328f3
	NMSettingVpn *s_vpn = NULL;
Packit Service d328f3
	const char *service_type;
Packit Service d328f3
	const char *id = NULL;
Packit Service d328f3
	gboolean success = FALSE;
Packit Service d328f3
Packit Service d328f3
	if (response != GTK_RESPONSE_ACCEPT)
Packit Service d328f3
		goto out;
Packit Service d328f3
Packit Service d328f3
	filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
Packit Service d328f3
	if (!filename) {
Packit Service d328f3
		g_set_error (&error, NMA_ERROR, NMA_ERROR_GENERIC, "no filename");
Packit Service d328f3
		goto done;
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
	if (g_file_test (filename, G_FILE_TEST_EXISTS)) {
Packit Service d328f3
		int replace_response;
Packit Service d328f3
		GtkWidget *replace_dialog;
Packit Service d328f3
		char *bname;
Packit Service d328f3
Packit Service d328f3
		bname = g_path_get_basename (filename);
Packit Service d328f3
		replace_dialog = gtk_message_dialog_new (NULL,
Packit Service d328f3
		                                         GTK_DIALOG_DESTROY_WITH_PARENT,
Packit Service d328f3
		                                         GTK_MESSAGE_QUESTION,
Packit Service d328f3
		                                         GTK_BUTTONS_CANCEL,
Packit Service d328f3
		                                         _("A file named “%s” already exists."),
Packit Service d328f3
		                                         bname);
Packit Service d328f3
		gtk_dialog_add_buttons (GTK_DIALOG (replace_dialog), _("_Replace"), GTK_RESPONSE_OK, NULL);
Packit Service d328f3
		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (replace_dialog),
Packit Service d328f3
							  _("Do you want to replace %s with the VPN connection you are saving?"), bname);
Packit Service d328f3
		g_free (bname);
Packit Service d328f3
		replace_response = gtk_dialog_run (GTK_DIALOG (replace_dialog));
Packit Service d328f3
		gtk_widget_destroy (replace_dialog);
Packit Service d328f3
		if (replace_response != GTK_RESPONSE_OK)
Packit Service d328f3
			goto out;
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
	s_con = nm_connection_get_setting_connection (connection);
Packit Service d328f3
	id = s_con ? nm_setting_connection_get_id (s_con) : NULL;
Packit Service d328f3
	if (!id) {
Packit Service d328f3
		g_set_error (&error, NMA_ERROR, NMA_ERROR_GENERIC, "connection setting invalid");
Packit Service d328f3
		goto done;
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
	s_vpn = nm_connection_get_setting_vpn (connection);
Packit Service d328f3
	service_type = s_vpn ? nm_setting_vpn_get_service_type (s_vpn) : NULL;
Packit Service d328f3
Packit Service d328f3
	if (!service_type) {
Packit Service d328f3
		g_set_error (&error, NMA_ERROR, NMA_ERROR_GENERIC, "VPN setting invalid");
Packit Service d328f3
		goto done;
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
	plugin = vpn_get_plugin_by_service (service_type);
Packit Service d328f3
	if (plugin)
Packit Service d328f3
		success = nm_vpn_editor_plugin_export (plugin, filename, connection, &error);
Packit Service d328f3
Packit Service d328f3
done:
Packit Service d328f3
	if (!success) {
Packit Service d328f3
		GtkWidget *err_dialog;
Packit Service d328f3
		char *bname = filename ? g_path_get_basename (filename) : g_strdup ("(none)");
Packit Service d328f3
Packit Service d328f3
		err_dialog = gtk_message_dialog_new (NULL,
Packit Service d328f3
		                                     GTK_DIALOG_DESTROY_WITH_PARENT,
Packit Service d328f3
		                                     GTK_MESSAGE_ERROR,
Packit Service d328f3
		                                     GTK_BUTTONS_OK,
Packit Service d328f3
		                                     _("Cannot export VPN connection"));
Packit Service d328f3
		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (err_dialog),
Packit Service d328f3
		                                 _("The VPN connection “%s” could not be exported to %s.\n\nError: %s."),
Packit Service d328f3
		                                 id ? id : "(unknown)", bname, error ? error->message : "unknown error");
Packit Service d328f3
		g_free (bname);
Packit Service d328f3
		g_signal_connect (err_dialog, "delete-event", G_CALLBACK (gtk_widget_destroy), NULL);
Packit Service d328f3
		g_signal_connect (err_dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
Packit Service d328f3
		gtk_widget_show_all (err_dialog);
Packit Service d328f3
		gtk_window_present (GTK_WINDOW (err_dialog));
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
out:
Packit Service d328f3
	if (error)
Packit Service d328f3
		g_error_free (error);
Packit Service d328f3
	g_object_unref (connection);
Packit Service d328f3
Packit Service d328f3
	gtk_widget_hide (dialog);
Packit Service d328f3
	gtk_widget_destroy (dialog);
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
void
Packit Service d328f3
vpn_export (NMConnection *connection)
Packit Service d328f3
{
Packit Service d328f3
	GtkWidget *dialog;
Packit Service d328f3
	NMVpnEditorPlugin *plugin;
Packit Service d328f3
	NMSettingVpn *s_vpn = NULL;
Packit Service d328f3
	const char *service_type;
Packit Service d328f3
	const char *home_folder;
Packit Service d328f3
Packit Service d328f3
	s_vpn = nm_connection_get_setting_vpn (connection);
Packit Service d328f3
	service_type = s_vpn ? nm_setting_vpn_get_service_type (s_vpn) : NULL;
Packit Service d328f3
Packit Service d328f3
	if (!service_type) {
Packit Service d328f3
		g_warning ("%s: invalid VPN connection!", __func__);
Packit Service d328f3
		return;
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
	dialog = gtk_file_chooser_dialog_new (_("Export VPN connection…"),
Packit Service d328f3
	                                      NULL,
Packit Service d328f3
	                                      GTK_FILE_CHOOSER_ACTION_SAVE,
Packit Service d328f3
	                                      _("_Cancel"), GTK_RESPONSE_CANCEL,
Packit Service d328f3
	                                      _("_Save"), GTK_RESPONSE_ACCEPT,
Packit Service d328f3
	                                      NULL);
Packit Service d328f3
	home_folder = g_get_home_dir ();
Packit Service d328f3
	gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), home_folder);
Packit Service d328f3
Packit Service d328f3
	plugin = vpn_get_plugin_by_service (service_type);
Packit Service d328f3
	if (plugin) {
Packit Service d328f3
		char *suggested = NULL;
Packit Service d328f3
Packit Service d328f3
		suggested = nm_vpn_editor_plugin_get_suggested_filename (plugin, connection);
Packit Service d328f3
		if (suggested) {
Packit Service d328f3
			gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), suggested);
Packit Service d328f3
			g_free (suggested);
Packit Service d328f3
		}
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
	g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (export_vpn_to_file_cb), g_object_ref (connection));
Packit Service d328f3
	gtk_widget_show_all (dialog);
Packit Service d328f3
	gtk_window_present (GTK_WINDOW (dialog));
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
gboolean
Packit Service d328f3
vpn_supports_ipv6 (NMConnection *connection)
Packit Service d328f3
{
Packit Service d328f3
	NMSettingVpn *s_vpn;
Packit Service d328f3
	const char *service_type;
Packit Service d328f3
	NMVpnEditorPlugin *plugin;
Packit Service d328f3
	guint32 capabilities;
Packit Service d328f3
Packit Service d328f3
	s_vpn = nm_connection_get_setting_vpn (connection);
Packit Service d328f3
	g_return_val_if_fail (s_vpn != NULL, FALSE);
Packit Service d328f3
Packit Service d328f3
	service_type = nm_setting_vpn_get_service_type (s_vpn);
Packit Service d328f3
	g_return_val_if_fail (service_type != NULL, FALSE);
Packit Service d328f3
Packit Service d328f3
	plugin = vpn_get_plugin_by_service (service_type);
Packit Service d328f3
	if (!plugin)
Packit Service d328f3
		return FALSE;
Packit Service d328f3
Packit Service d328f3
	capabilities = nm_vpn_editor_plugin_get_capabilities (plugin);
Packit Service d328f3
	return (capabilities & NM_VPN_EDITOR_PLUGIN_CAPABILITY_IPV6) != 0;
Packit Service d328f3
}
Packit Service d328f3