Blame src/connection-editor/page-wireguard.c

Packit Service 639700
// SPDX-License-Identifier: GPL-2.0+
Packit Service 639700
/* NetworkManager Connection editor -- Connection editor for NetworkManager
Packit Service 639700
 *
Packit Service 639700
 * Copyright 2020 Red Hat, Inc.
Packit Service 639700
 */
Packit Service 639700
Packit Service 639700
#include "nm-default.h"
Packit Service 639700
Packit Service 639700
#include <string.h>
Packit Service 639700
Packit Service 639700
#include "page-wireguard.h"
Packit Service 639700
#include "nm-connection-editor.h"
Packit Service 639700
#include "nma-ui-utils.h"
Packit Service 639700
Packit Service 639700
G_DEFINE_TYPE (CEPageWireGuard, ce_page_wireguard, CE_TYPE_PAGE)
Packit Service 639700
Packit Service 639700
#define CE_PAGE_WIREGUARD_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CE_TYPE_PAGE_WIREGUARD, CEPageWireGuardPrivate))
Packit Service 639700
Packit Service 639700
typedef struct {
Packit Service 639700
	NMWireGuardPeer *peer;
Packit Service 639700
	GtkInfoBar *info_bar;
Packit Service 639700
	GtkLabel *label_info;
Packit Service 639700
	GtkButton *button_apply;
Packit Service 639700
	GtkBuilder *builder;
Packit Service 639700
	GtkEntry *entry_public_key;
Packit Service 639700
	GtkEntry *entry_allowed_ips;
Packit Service 639700
	GtkEntry *entry_endpoint;
Packit Service 639700
	GtkEntry *entry_psk;
Packit Service 639700
	GtkSpinButton *spin_persistent_keepalive;
Packit Service 639700
	GtkToggleButton *toggle_show_psk;
Packit Service 639700
} PeerDialogData;
Packit Service 639700
Packit Service 639700
typedef struct {
Packit Service 639700
	NMSettingWireGuard *setting;
Packit Service 639700
Packit Service 639700
	NMWireGuardPeer *dialog_peer;
Packit Service 639700
	int dialog_peer_index;
Packit Service 639700
Packit Service 639700
	GtkEntry *entry_ifname;
Packit Service 639700
	GtkEntry *entry_pk;
Packit Service 639700
	GtkSpinButton *spin_mtu;
Packit Service 639700
	GtkSpinButton *spin_fwmark;
Packit Service 639700
	GtkSpinButton *spin_listen_port;
Packit Service 639700
	GtkToggleButton *toggle_peer_routes;
Packit Service 639700
	GtkToggleButton *toggle_show_pk;
Packit Service 639700
	GtkButton *button_add;
Packit Service 639700
	GtkButton *button_delete;
Packit Service 639700
Packit Service 639700
	GtkTreeView *tree;
Packit Service 639700
	GtkTreeStore *store;
Packit Service 639700
} CEPageWireGuardPrivate;
Packit Service 639700
Packit Service 639700
enum {
Packit Service 639700
	COL_PUBLIC_KEY,
Packit Service 639700
	COL_ALLOWED_IPS,
Packit Service 639700
	N_COLUMNS,
Packit Service 639700
};
Packit Service 639700
Packit Service 639700
static void
Packit Service 639700
peer_dialog_data_destroy (PeerDialogData *data)
Packit Service 639700
{
Packit Service 639700
	g_object_unref (data->builder);
Packit Service 639700
	nm_wireguard_peer_unref (data->peer);
Packit Service 639700
	g_free (data);
Packit Service 639700
}
Packit Service 639700
Packit Service 639700
static char *
Packit Service 639700
format_allowed_ips (NMWireGuardPeer *peer)
Packit Service 639700
{
Packit Service 639700
	guint i, len;
Packit Service 639700
	GString *string = NULL;
Packit Service 639700
Packit Service 639700
	len = nm_wireguard_peer_get_allowed_ips_len (peer);
Packit Service 639700
	for (i = 0; i < len; i++) {
Packit Service 639700
		if (!string)
Packit Service 639700
			string = g_string_new ("");
Packit Service 639700
		else
Packit Service 639700
			g_string_append_c (string, ',');
Packit Service 639700
		g_string_append (string, nm_wireguard_peer_get_allowed_ip (peer, i, NULL));
Packit Service 639700
	}
Packit Service 639700
Packit Service 639700
	return string ? g_string_free (string, FALSE) : NULL;
Packit Service 639700
}
Packit Service 639700
Packit Service 639700
static void
Packit Service 639700
peer_dialog_update_ui (GtkWidget *dialog)
Packit Service 639700
{
Packit Service 639700
	PeerDialogData *data;
Packit Service 639700
	gs_free char *allowed_ips = NULL;
Packit Service 639700
Packit Service 639700
	data = g_object_get_data (G_OBJECT (dialog), "data");
Packit Service 639700
	g_return_if_fail (data && data->peer);
Packit Service 639700
Packit Service 639700
	allowed_ips = format_allowed_ips (data->peer);
Packit Service 639700
Packit Service 639700
	gtk_entry_set_text (data->entry_public_key, nm_wireguard_peer_get_public_key (data->peer) ?: "");
Packit Service 639700
	gtk_entry_set_text (data->entry_allowed_ips, allowed_ips ?: "");
Packit Service 639700
	gtk_entry_set_text (data->entry_endpoint, nm_wireguard_peer_get_endpoint (data->peer) ?: "");
Packit Service 639700
	gtk_spin_button_set_value (data->spin_persistent_keepalive, nm_wireguard_peer_get_persistent_keepalive (data->peer));
Packit Service 639700
	gtk_entry_set_text (data->entry_psk, nm_wireguard_peer_get_preshared_key (data->peer) ?: "");
Packit Service 639700
Packit Service 639700
	nma_utils_update_password_storage (GTK_WIDGET (data->entry_psk),
Packit Service 639700
	                                   nm_wireguard_peer_get_preshared_key_flags (data->peer),
Packit Service 639700
	                                   NULL,
Packit Service 639700
	                                   NULL);
Packit Service 639700
}
Packit Service 639700
Packit Service 639700
static void
Packit Service 639700
peer_dialog_update_peer (GtkWidget *dialog)
Packit Service 639700
{
Packit Service 639700
	PeerDialogData *data;
Packit Service 639700
	const char *pk;
Packit Service 639700
	const char *allowed_ips;
Packit Service 639700
	const char *endpoint;
Packit Service 639700
	const char *psk;
Packit Service 639700
	char **strv;
Packit Service 639700
	guint i;
Packit Service 639700
	int keepalive;
Packit Service 639700
	NMSettingSecretFlags secret_flags;
Packit Service 639700
Packit Service 639700
	data = g_object_get_data (G_OBJECT (dialog), "data");
Packit Service 639700
	g_return_if_fail (data && data->peer);
Packit Service 639700
Packit Service 639700
	pk = gtk_entry_get_text (data->entry_public_key);
Packit Service 639700
	nm_wireguard_peer_set_public_key (data->peer, pk && pk[0] ? pk : NULL, TRUE);
Packit Service 639700
Packit Service 639700
	nm_wireguard_peer_clear_allowed_ips (data->peer);
Packit Service 639700
	allowed_ips = gtk_entry_get_text (data->entry_allowed_ips);
Packit Service 639700
	strv = g_strsplit (allowed_ips, ",", -1);
Packit Service 639700
	for (i = 0; strv && strv[i]; i++)
Packit Service 639700
		nm_wireguard_peer_append_allowed_ip (data->peer, g_strstrip (strv[i]), TRUE);
Packit Service 639700
	g_strfreev (strv);
Packit Service 639700
Packit Service 639700
	endpoint = gtk_entry_get_text (data->entry_endpoint);
Packit Service 639700
	nm_wireguard_peer_set_endpoint (data->peer, endpoint && endpoint[0] ? endpoint : NULL, TRUE);
Packit Service 639700
Packit Service 639700
	keepalive = gtk_spin_button_get_value_as_int (data->spin_persistent_keepalive);
Packit Service 639700
	nm_wireguard_peer_set_persistent_keepalive (data->peer, keepalive);
Packit Service 639700
Packit Service 639700
	psk = gtk_entry_get_text (data->entry_psk);
Packit Service 639700
	nm_wireguard_peer_set_preshared_key (data->peer, psk && psk[0] ? psk : NULL, TRUE);
Packit Service 639700
Packit Service 639700
	secret_flags = nma_utils_menu_to_secret_flags ((GtkWidget *) data->entry_psk);
Packit Service 639700
	nm_wireguard_peer_set_preshared_key_flags (data->peer, secret_flags);
Packit Service 639700
}
Packit Service 639700
Packit Service 639700
static void
Packit Service 639700
peer_dialog_apply_clicked (GtkWidget *dialog)
Packit Service 639700
{
Packit Service 639700
	PeerDialogData *data;
Packit Service 639700
	gs_free_error GError *error = NULL;
Packit Service 639700
	gs_free char *reason = NULL;
Packit Service 639700
Packit Service 639700
	data = g_object_get_data (G_OBJECT (dialog), "data");
Packit Service 639700
Packit Service 639700
	if (!nm_wireguard_peer_is_valid (data->peer, TRUE, TRUE, &error)) {
Packit Service 639700
		reason = g_strdup_printf ("Error: %s", error->message);
Packit Service 639700
		gtk_label_set_text (data->label_info, reason);
Packit Service 639700
		gtk_widget_set_visible (GTK_WIDGET (data->info_bar), TRUE);
Packit Service 639700
	} else {
Packit Service 639700
		gtk_label_set_text (data->label_info, "");
Packit Service 639700
		gtk_widget_set_visible (GTK_WIDGET (data->info_bar), FALSE);
Packit Service 639700
		gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_APPLY);
Packit Service 639700
	}
Packit Service 639700
}
Packit Service 639700
Packit Service 639700
static void
Packit Service 639700
peer_dialog_show_psk (GtkDialog *dialog)
Packit Service 639700
{
Packit Service 639700
	PeerDialogData *data;
Packit Service 639700
Packit Service 639700
	data = g_object_get_data (G_OBJECT (dialog), "data");
Packit Service 639700
	gtk_entry_set_visibility (data->entry_psk,
Packit Service 639700
	                          gtk_toggle_button_get_active (data->toggle_show_psk));
Packit Service 639700
}
Packit Service 639700
Packit Service 639700
static GtkWidget *
Packit Service 639700
peer_dialog_create (GtkWidget *toplevel, NMWireGuardPeer *peer)
Packit Service 639700
{
Packit Service 639700
	GtkWidget *dialog;
Packit Service 639700
	gs_free_error GError *error = NULL;
Packit Service 639700
	PeerDialogData *data;
Packit Service 639700
	GtkBuilder *builder;
Packit Service 639700
Packit Service 639700
	builder = gtk_builder_new ();
Packit Service 639700
Packit Service 639700
	if (!gtk_builder_add_from_resource (builder,
Packit Service 639700
	                                    "/org/gnome/nm_connection_editor/ce-page-wireguard.ui",
Packit Service 639700
	                                    &error)) {
Packit Service 639700
		g_warning ("Couldn't load builder resource: %s", error->message);
Packit Service 639700
		g_error_free (error);
Packit Service 639700
		return NULL;
Packit Service 639700
	}
Packit Service 639700
Packit Service 639700
	dialog = GTK_WIDGET (gtk_builder_get_object (builder, "PeerDialog"));
Packit Service 639700
Packit Service 639700
	data = g_new0 (PeerDialogData, 1);
Packit Service 639700
	data->peer = nm_wireguard_peer_ref (peer);
Packit Service 639700
	data->builder = builder;
Packit Service 639700
	data->button_apply = GTK_BUTTON (gtk_builder_get_object (builder, "button_apply"));
Packit Service 639700
	data->entry_public_key = GTK_ENTRY (gtk_builder_get_object (builder, "entry_public_key"));
Packit Service 639700
	data->entry_allowed_ips = GTK_ENTRY (gtk_builder_get_object (builder, "entry_allowed_ips"));
Packit Service 639700
	data->entry_endpoint = GTK_ENTRY (gtk_builder_get_object (builder, "entry_endpoint"));
Packit Service 639700
	data->entry_psk = GTK_ENTRY (gtk_builder_get_object (builder, "entry_psk"));
Packit Service 639700
	data->spin_persistent_keepalive = GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "spin_persistent_keepalive"));
Packit Service 639700
	data->info_bar = GTK_INFO_BAR (gtk_builder_get_object (builder, "info_bar"));
Packit Service 639700
	data->label_info = GTK_LABEL (gtk_builder_get_object (builder, "label_info"));
Packit Service 639700
	data->toggle_show_psk = GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "toggle_show_psk"));
Packit Service 639700
Packit Service 639700
	g_object_set_data_full (G_OBJECT (dialog), "data",
Packit Service 639700
	                        data,
Packit Service 639700
	                        (GDestroyNotify) peer_dialog_data_destroy);
Packit Service 639700
Packit Service 639700
	nma_utils_setup_password_storage ((GtkWidget *) data->entry_psk, 0,
Packit Service 639700
	                                  NULL, NULL, TRUE, FALSE);
Packit Service 639700
	ce_spin_off_val (data->spin_persistent_keepalive, 0);
Packit Service 639700
Packit Service 639700
	gtk_entry_set_visibility (data->entry_psk, FALSE);
Packit Service 639700
Packit Service 639700
	peer_dialog_update_ui (dialog);
Packit Service 639700
Packit Service 639700
	g_signal_connect_swapped (data->button_apply, "clicked", G_CALLBACK (peer_dialog_apply_clicked), dialog);
Packit Service 639700
	g_signal_connect_swapped (data->entry_public_key, "changed", G_CALLBACK (peer_dialog_update_peer), dialog);
Packit Service 639700
	g_signal_connect_swapped (data->entry_allowed_ips, "changed", G_CALLBACK (peer_dialog_update_peer), dialog);
Packit Service 639700
	g_signal_connect_swapped (data->entry_endpoint, "changed", G_CALLBACK (peer_dialog_update_peer), dialog);
Packit Service 639700
	g_signal_connect_swapped (data->entry_psk, "changed", G_CALLBACK (peer_dialog_update_peer), dialog);
Packit Service 639700
	g_signal_connect_swapped (data->toggle_show_psk, "toggled", G_CALLBACK (peer_dialog_show_psk), dialog);
Packit Service 639700
Packit Service 639700
	gtk_label_set_text (data->label_info, "");
Packit Service 639700
	gtk_widget_set_visible (GTK_WIDGET (data->info_bar), FALSE);
Packit Service 639700
Packit Service 639700
	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
Packit Service 639700
	gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (toplevel));
Packit Service 639700
Packit Service 639700
	return dialog;
Packit Service 639700
}
Packit Service 639700
Packit Service 639700
static void
Packit Service 639700
wireguard_private_init (CEPageWireGuard *self)
Packit Service 639700
{
Packit Service 639700
	CEPageWireGuardPrivate *priv = CE_PAGE_WIREGUARD_GET_PRIVATE (self);
Packit Service 639700
	GtkBuilder *builder;
Packit Service 639700
	GtkTreeViewColumn *column;
Packit Service 639700
Packit Service 639700
	builder = CE_PAGE (self)->builder;
Packit Service 639700
Packit Service 639700
	priv->entry_ifname = GTK_ENTRY (gtk_builder_get_object (builder, "entry_ifname"));
Packit Service 639700
	priv->entry_pk = GTK_ENTRY (gtk_builder_get_object (builder, "entry_private_key"));
Packit Service 639700
	priv->spin_mtu = GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "spin_mtu"));
Packit Service 639700
	priv->spin_fwmark = GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "spin_fwmark"));
Packit Service 639700
	priv->spin_listen_port = GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "spin_listen_port"));
Packit Service 639700
	priv->toggle_peer_routes = GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "toggle_peer_routes"));
Packit Service 639700
	priv->toggle_show_pk = GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "toggle_show_private_key"));
Packit Service 639700
	priv->tree = GTK_TREE_VIEW (gtk_builder_get_object (builder, "tree_peers"));
Packit Service 639700
	priv->button_add = GTK_BUTTON (gtk_builder_get_object (builder, "button_add"));
Packit Service 639700
	priv->button_delete = GTK_BUTTON (gtk_builder_get_object (builder, "button_delete"));
Packit Service 639700
Packit Service 639700
	gtk_entry_set_visibility (priv->entry_pk, FALSE);
Packit Service 639700
Packit Service 639700
	priv->store = gtk_tree_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
Packit Service 639700
	column = gtk_tree_view_column_new_with_attributes (_("Public key"),
Packit Service 639700
	                                                   gtk_cell_renderer_text_new (),
Packit Service 639700
	                                                   "text", COL_PUBLIC_KEY,
Packit Service 639700
	                                                   NULL);
Packit Service 639700
	gtk_tree_view_column_set_resizable (column, TRUE);
Packit Service 639700
	gtk_tree_view_append_column (priv->tree, column);
Packit Service 639700
Packit Service 639700
	column = gtk_tree_view_column_new_with_attributes (_("Allowed IPs"),
Packit Service 639700
	                                                   gtk_cell_renderer_text_new (),
Packit Service 639700
	                                                   "text", COL_ALLOWED_IPS,
Packit Service 639700
	                                                   NULL);
Packit Service 639700
	gtk_tree_view_column_set_resizable (column, TRUE);
Packit Service 639700
	gtk_tree_view_append_column (priv->tree, column);
Packit Service 639700
Packit Service 639700
	gtk_tree_view_set_model (priv->tree, GTK_TREE_MODEL (priv->store));
Packit Service 639700
}
Packit Service 639700
Packit Service 639700
static void
Packit Service 639700
update_peers_table (CEPageWireGuard *self)
Packit Service 639700
{
Packit Service 639700
	CEPageWireGuardPrivate *priv = CE_PAGE_WIREGUARD_GET_PRIVATE (self);
Packit Service 639700
	NMSettingWireGuard *setting = priv->setting;
Packit Service 639700
	guint i, num;
Packit Service 639700
Packit Service 639700
	gtk_tree_store_clear (priv->store);
Packit Service 639700
Packit Service 639700
	num = nm_setting_wireguard_get_peers_len (setting);
Packit Service 639700
	for (i = 0; i < num; i++) {
Packit Service 639700
		NMWireGuardPeer *peer;
Packit Service 639700
		GtkTreeIter iter;
Packit Service 639700
		gs_free char *ips = NULL;
Packit Service 639700
Packit Service 639700
		peer = nm_setting_wireguard_get_peer (setting, i);
Packit Service 639700
		ips = format_allowed_ips (peer);
Packit Service 639700
		gtk_tree_store_append (priv->store, &iter, NULL);
Packit Service 639700
Packit Service 639700
		gtk_tree_store_set (priv->store, &iter,
Packit Service 639700
		                    COL_PUBLIC_KEY, nm_wireguard_peer_get_public_key (peer),
Packit Service 639700
		                    COL_ALLOWED_IPS, ips,
Packit Service 639700
		                    -1);
Packit Service 639700
	}
Packit Service 639700
}
Packit Service 639700
Packit Service 639700
static int
Packit Service 639700
get_selected_index (CEPageWireGuard *self)
Packit Service 639700
{
Packit Service 639700
	CEPageWireGuardPrivate *priv = CE_PAGE_WIREGUARD_GET_PRIVATE (self);
Packit Service 639700
	GtkTreeSelection *selection;
Packit Service 639700
	GtkTreeModel *model;
Packit Service 639700
	GList *list;
Packit Service 639700
	int *indices;
Packit Service 639700
	int ret = -1;
Packit Service 639700
Packit Service 639700
	selection = gtk_tree_view_get_selection (priv->tree);
Packit Service 639700
	nm_assert (selection);
Packit Service 639700
Packit Service 639700
	list = gtk_tree_selection_get_selected_rows (selection, &model);
Packit Service 639700
	if (!list)
Packit Service 639700
		goto done;
Packit Service 639700
Packit Service 639700
	indices = gtk_tree_path_get_indices ((GtkTreePath *) list->data);
Packit Service 639700
	if (!indices)
Packit Service 639700
		goto done;
Packit Service 639700
Packit Service 639700
	ret = indices[0];
Packit Service 639700
done:
Packit Service 639700
	g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free);
Packit Service 639700
	return ret;
Packit Service 639700
}
Packit Service 639700
Packit Service 639700
static void
Packit Service 639700
tree_selection_changed (CEPageWireGuard *self)
Packit Service 639700
{
Packit Service 639700
	CEPageWireGuardPrivate *priv = CE_PAGE_WIREGUARD_GET_PRIVATE (self);
Packit Service 639700
	int index;
Packit Service 639700
Packit Service 639700
	index = get_selected_index (self);
Packit Service 639700
	gtk_widget_set_sensitive (GTK_WIDGET (priv->button_delete), index >= 0);
Packit Service 639700
}
Packit Service 639700
Packit Service 639700
static void
Packit Service 639700
populate_ui (CEPageWireGuard *self)
Packit Service 639700
{
Packit Service 639700
	CEPageWireGuardPrivate *priv = CE_PAGE_WIREGUARD_GET_PRIVATE (self);
Packit Service 639700
	NMSettingWireGuard *setting = priv->setting;
Packit Service 639700
	NMConnection *connection;
Packit Service 639700
	const char *str;
Packit Service 639700
Packit Service 639700
	connection = CE_PAGE (self)->connection;
Packit Service 639700
	str = nm_connection_get_interface_name (connection);
Packit Service 639700
	if (str)
Packit Service 639700
		gtk_entry_set_text (priv->entry_ifname, str);
Packit Service 639700
Packit Service 639700
	gtk_entry_set_text (priv->entry_pk, nm_setting_wireguard_get_private_key (setting) ?: "");
Packit Service 639700
	nma_utils_setup_password_storage ((GtkWidget *) priv->entry_pk, 0,
Packit Service 639700
	                                  (NMSetting *) priv->setting,
Packit Service 639700
	                                  NM_SETTING_WIREGUARD_PRIVATE_KEY,
Packit Service 639700
	                                  FALSE, FALSE);
Packit Service 639700
Packit Service 639700
	ce_spin_automatic_val (priv->spin_mtu, 0);
Packit Service 639700
	ce_spin_automatic_val (priv->spin_listen_port, 0);
Packit Service 639700
	ce_spin_off_val (priv->spin_fwmark, 0);
Packit Service 639700
Packit Service 639700
	gtk_spin_button_set_value (priv->spin_mtu, nm_setting_wireguard_get_mtu (setting));
Packit Service 639700
	gtk_spin_button_set_value (priv->spin_fwmark, nm_setting_wireguard_get_fwmark (setting));
Packit Service 639700
	gtk_spin_button_set_value (priv->spin_listen_port, nm_setting_wireguard_get_listen_port (setting));
Packit Service 639700
Packit Service 639700
	gtk_toggle_button_set_active (priv->toggle_peer_routes,
Packit Service 639700
	                              nm_setting_wireguard_get_peer_routes (setting));
Packit Service 639700
Packit Service 639700
	update_peers_table (self);
Packit Service 639700
	tree_selection_changed (self);
Packit Service 639700
}
Packit Service 639700
Packit Service 639700
static void
Packit Service 639700
stuff_changed (GtkEditable *editable, gpointer user_data)
Packit Service 639700
{
Packit Service 639700
	ce_page_changed (CE_PAGE (user_data));
Packit Service 639700
}
Packit Service 639700
Packit Service 639700
static void
Packit Service 639700
peer_dialog_response_cb (GtkWidget *dialog, gint response, gpointer user_data)
Packit Service 639700
{
Packit Service 639700
	CEPageWireGuard *self = CE_PAGE_WIREGUARD (user_data);
Packit Service 639700
	CEPageWireGuardPrivate *priv = CE_PAGE_WIREGUARD_GET_PRIVATE (self);
Packit Service 639700
Packit Service 639700
	if (response == GTK_RESPONSE_APPLY) {
Packit Service 639700
		peer_dialog_update_peer (dialog);
Packit Service 639700
		if (priv->dialog_peer_index >= 0) {
Packit Service 639700
			nm_setting_wireguard_set_peer (priv->setting,
Packit Service 639700
			                               priv->dialog_peer,
Packit Service 639700
			                               priv->dialog_peer_index);
Packit Service 639700
		} else {
Packit Service 639700
			nm_setting_wireguard_append_peer (priv->setting,
Packit Service 639700
			                                  priv->dialog_peer);
Packit Service 639700
		}
Packit Service 639700
		update_peers_table (self);
Packit Service 639700
	}
Packit Service 639700
Packit Service 639700
	nm_wireguard_peer_unref (priv->dialog_peer);
Packit Service 639700
	priv->dialog_peer = NULL;
Packit Service 639700
	priv->dialog_peer_index = -1;
Packit Service 639700
Packit Service 639700
	gtk_widget_hide (dialog);
Packit Service 639700
	gtk_widget_destroy (dialog);
Packit Service 639700
}
Packit Service 639700
Packit Service 639700
static void
Packit Service 639700
add_delete_clicked (GtkButton *button, CEPageWireGuard *self)
Packit Service 639700
{
Packit Service 639700
	CEPageWireGuardPrivate *priv = CE_PAGE_WIREGUARD_GET_PRIVATE (self);
Packit Service 639700
	GtkWidget *dialog;
Packit Service 639700
	int index;
Packit Service 639700
Packit Service 639700
	g_return_if_fail (NM_IN_SET (button, priv->button_add, priv->button_delete));
Packit Service 639700
Packit Service 639700
	if (button == priv->button_add) {
Packit Service 639700
		priv->dialog_peer = nm_wireguard_peer_new ();
Packit Service 639700
		priv->dialog_peer_index = -1;
Packit Service 639700
		dialog = peer_dialog_create (gtk_widget_get_toplevel (CE_PAGE (self)->page),
Packit Service 639700
		                             priv->dialog_peer);
Packit Service 639700
		if (!dialog)
Packit Service 639700
			return;
Packit Service 639700
		g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (peer_dialog_response_cb), self);
Packit Service 639700
		gtk_widget_show (dialog);
Packit Service 639700
	} else {
Packit Service 639700
		index = get_selected_index (self);
Packit Service 639700
		if (index >= 0) {
Packit Service 639700
			nm_setting_wireguard_remove_peer (priv->setting, (guint) index);
Packit Service 639700
			update_peers_table (self);
Packit Service 639700
		}
Packit Service 639700
	}
Packit Service 639700
}
Packit Service 639700
Packit Service 639700
static void
Packit Service 639700
row_activated (GtkTreeView       *tree_view,
Packit Service 639700
               GtkTreePath       *path,
Packit Service 639700
               GtkTreeViewColumn *column,
Packit Service 639700
               CEPageWireGuard   *self)
Packit Service 639700
{
Packit Service 639700
	CEPageWireGuardPrivate *priv = CE_PAGE_WIREGUARD_GET_PRIVATE (self);
Packit Service 639700
	NMWireGuardPeer *peer;
Packit Service 639700
	GtkWidget *dialog;
Packit Service 639700
	int index;
Packit Service 639700
Packit Service 639700
	index = get_selected_index (self);
Packit Service 639700
	if (index < 0)
Packit Service 639700
		return;
Packit Service 639700
Packit Service 639700
	peer = nm_setting_wireguard_get_peer (priv->setting, index);
Packit Service 639700
	priv->dialog_peer = nm_wireguard_peer_new_clone (peer, TRUE);
Packit Service 639700
	priv->dialog_peer_index = index;
Packit Service 639700
Packit Service 639700
	dialog = peer_dialog_create (gtk_widget_get_toplevel (CE_PAGE (self)->page),
Packit Service 639700
	                             priv->dialog_peer);
Packit Service 639700
	if (!dialog)
Packit Service 639700
		return;
Packit Service 639700
Packit Service 639700
	g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (peer_dialog_response_cb), self);
Packit Service 639700
	gtk_widget_show (dialog);
Packit Service 639700
}
Packit Service 639700
Packit Service 639700
static void
Packit Service 639700
show_private_key (GtkToggleButton *button, gpointer user_data)
Packit Service 639700
{
Packit Service 639700
	CEPageWireGuardPrivate *priv = CE_PAGE_WIREGUARD_GET_PRIVATE (user_data);
Packit Service 639700
Packit Service 639700
	gtk_entry_set_visibility (priv->entry_pk, gtk_toggle_button_get_active (button));
Packit Service 639700
}
Packit Service 639700
Packit Service 639700
static void
Packit Service 639700
finish_setup (CEPageWireGuard *self, gpointer user_data)
Packit Service 639700
{
Packit Service 639700
	CEPageWireGuardPrivate *priv = CE_PAGE_WIREGUARD_GET_PRIVATE (self);
Packit Service 639700
	GtkTreeSelection *selection;
Packit Service 639700
Packit Service 639700
	selection = gtk_tree_view_get_selection (priv->tree);
Packit Service 639700
	populate_ui (self);
Packit Service 639700
Packit Service 639700
	g_signal_connect (priv->entry_ifname,      "changed",       G_CALLBACK (stuff_changed), self);
Packit Service 639700
	g_signal_connect (priv->entry_pk,          "changed",       G_CALLBACK (stuff_changed), self);
Packit Service 639700
	g_signal_connect (priv->spin_mtu,          "value-changed", G_CALLBACK (stuff_changed), self);
Packit Service 639700
	g_signal_connect (priv->spin_listen_port,  "value-changed", G_CALLBACK (stuff_changed), self);
Packit Service 639700
	g_signal_connect (priv->button_add,        "clicked",       G_CALLBACK (add_delete_clicked), self);
Packit Service 639700
	g_signal_connect (priv->button_delete,     "clicked",       G_CALLBACK (add_delete_clicked), self);
Packit Service 639700
	g_signal_connect (priv->tree,              "row-activated", G_CALLBACK (row_activated), self);
Packit Service 639700
	g_signal_connect (priv->toggle_show_pk,    "toggled",       G_CALLBACK (show_private_key), self);
Packit Service 639700
Packit Service 639700
	g_signal_connect_swapped (selection,       "changed",       G_CALLBACK (tree_selection_changed), self);
Packit Service 639700
}
Packit Service 639700
Packit Service 639700
CEPage *
Packit Service 639700
ce_page_wireguard_new (NMConnectionEditor *editor,
Packit Service 639700
                       NMConnection *connection,
Packit Service 639700
                       GtkWindow *parent_window,
Packit Service 639700
                       NMClient *client,
Packit Service 639700
                       const char **out_secrets_setting_name,
Packit Service 639700
                       GError **error)
Packit Service 639700
{
Packit Service 639700
	CEPageWireGuard *self;
Packit Service 639700
	CEPageWireGuardPrivate *priv;
Packit Service 639700
Packit Service 639700
	self = CE_PAGE_WIREGUARD (ce_page_new (CE_TYPE_PAGE_WIREGUARD,
Packit Service 639700
	                                       editor,
Packit Service 639700
	                                       connection,
Packit Service 639700
	                                       parent_window,
Packit Service 639700
	                                       client,
Packit Service 639700
	                                       "/org/gnome/nm_connection_editor/ce-page-wireguard.ui",
Packit Service 639700
	                                       "WireGuardPage",
Packit Service 639700
	                                      _("WireGuard")));
Packit Service 639700
	if (!self) {
Packit Service 639700
		g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("Could not load WireGuard user interface."));
Packit Service 639700
		return NULL;
Packit Service 639700
	}
Packit Service 639700
Packit Service 639700
	wireguard_private_init (self);
Packit Service 639700
	priv = CE_PAGE_WIREGUARD_GET_PRIVATE (self);
Packit Service 639700
Packit Service 639700
	priv->setting = (NMSettingWireGuard *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIREGUARD);
Packit Service 639700
	if (!priv->setting) {
Packit Service 639700
		priv->setting = NM_SETTING_WIREGUARD (nm_setting_wireguard_new ());
Packit Service 639700
		nm_connection_add_setting (connection, NM_SETTING (priv->setting));
Packit Service 639700
	}
Packit Service 639700
Packit Service 639700
	g_signal_connect (self, CE_PAGE_INITIALIZED, G_CALLBACK (finish_setup), NULL);
Packit Service 639700
Packit Service 639700
	*out_secrets_setting_name = NM_SETTING_WIREGUARD_SETTING_NAME;
Packit Service 639700
Packit Service 639700
	return CE_PAGE (self);
Packit Service 639700
}
Packit Service 639700
Packit Service 639700
static void
Packit Service 639700
ui_to_setting (CEPageWireGuard *self)
Packit Service 639700
{
Packit Service 639700
	CEPageWireGuardPrivate *priv = CE_PAGE_WIREGUARD_GET_PRIVATE (self);
Packit Service 639700
	NMSettingConnection *s_con;
Packit Service 639700
	guint32 mtu;
Packit Service 639700
	guint32 fwmark;
Packit Service 639700
	guint16 listen_port;
Packit Service 639700
	const char *private_key;
Packit Service 639700
	const char *ifname;
Packit Service 639700
	NMSettingSecretFlags secret_flags;
Packit Service 639700
	gboolean peer_routes;
Packit Service 639700
Packit Service 639700
	s_con = nm_connection_get_setting_connection (CE_PAGE (self)->connection);
Packit Service 639700
	g_return_if_fail (s_con != NULL);
Packit Service 639700
Packit Service 639700
	ifname = gtk_entry_get_text (priv->entry_ifname);
Packit Service 639700
	if (ifname && ifname[0] == '\0')
Packit Service 639700
		ifname = NULL;
Packit Service 639700
	g_object_set (s_con,
Packit Service 639700
	              NM_SETTING_CONNECTION_INTERFACE_NAME,
Packit Service 639700
	              ifname,
Packit Service 639700
	              NULL);
Packit Service 639700
Packit Service 639700
	private_key = gtk_entry_get_text (priv->entry_pk);
Packit Service 639700
	if (private_key && private_key[0] == '\0')
Packit Service 639700
		private_key = NULL;
Packit Service 639700
	mtu = gtk_spin_button_get_value_as_int (priv->spin_mtu);
Packit Service 639700
	fwmark = gtk_spin_button_get_value_as_int (priv->spin_fwmark);
Packit Service 639700
	listen_port = gtk_spin_button_get_value_as_int (priv->spin_listen_port);
Packit Service 639700
	peer_routes = gtk_toggle_button_get_active (priv->toggle_peer_routes);
Packit Service 639700
Packit Service 639700
	g_object_set (priv->setting,
Packit Service 639700
	              NM_SETTING_WIREGUARD_PRIVATE_KEY, private_key,
Packit Service 639700
	              NM_SETTING_WIREGUARD_LISTEN_PORT, listen_port,
Packit Service 639700
	              NM_SETTING_WIREGUARD_FWMARK, fwmark,
Packit Service 639700
	              NM_SETTING_WIREGUARD_MTU, mtu,
Packit Service 639700
	              NM_SETTING_WIREGUARD_PEER_ROUTES, peer_routes,
Packit Service 639700
	              NULL);
Packit Service 639700
Packit Service 639700
	/* Save private key flags to the connection */
Packit Service 639700
	secret_flags = nma_utils_menu_to_secret_flags ((GtkWidget *) priv->entry_pk);
Packit Service 639700
	nm_setting_set_secret_flags (NM_SETTING (priv->setting),
Packit Service 639700
	                             NM_SETTING_WIREGUARD_PRIVATE_KEY,
Packit Service 639700
	                             secret_flags, NULL);
Packit Service 639700
Packit Service 639700
	/* Update secret flags and popup when editing the connection */
Packit Service 639700
	nma_utils_update_password_storage ((GtkWidget *) priv->entry_pk,
Packit Service 639700
	                                   secret_flags,
Packit Service 639700
	                                   NM_SETTING (priv->setting),
Packit Service 639700
	                                   NM_SETTING_WIREGUARD_PRIVATE_KEY);
Packit Service 639700
}
Packit Service 639700
Packit Service 639700
static gboolean
Packit Service 639700
ce_page_validate_v (CEPage *page, NMConnection *connection, GError **error)
Packit Service 639700
{
Packit Service 639700
	CEPageWireGuard *self = CE_PAGE_WIREGUARD (page);
Packit Service 639700
	CEPageWireGuardPrivate *priv = CE_PAGE_WIREGUARD_GET_PRIVATE (self);
Packit Service 639700
Packit Service 639700
	ui_to_setting (self);
Packit Service 639700
Packit Service 639700
	return    nm_setting_verify (NM_SETTING (priv->setting), connection, error)
Packit Service 639700
	       && nm_setting_verify_secrets (NM_SETTING (priv->setting), connection, error);
Packit Service 639700
}
Packit Service 639700
Packit Service 639700
static void
Packit Service 639700
ce_page_wireguard_init (CEPageWireGuard *self)
Packit Service 639700
{
Packit Service 639700
}
Packit Service 639700
Packit Service 639700
static void
Packit Service 639700
ce_page_wireguard_class_init (CEPageWireGuardClass *wireguard_class)
Packit Service 639700
{
Packit Service 639700
	GObjectClass *object_class = G_OBJECT_CLASS (wireguard_class);
Packit Service 639700
	CEPageClass *parent_class = CE_PAGE_CLASS (wireguard_class);
Packit Service 639700
Packit Service 639700
	g_type_class_add_private (object_class, sizeof (CEPageWireGuardPrivate));
Packit Service 639700
Packit Service 639700
	parent_class->ce_page_validate_v = ce_page_validate_v;
Packit Service 639700
}
Packit Service 639700
Packit Service 639700
void
Packit Service 639700
wireguard_connection_new (FUNC_TAG_PAGE_NEW_CONNECTION_IMPL,
Packit Service 639700
                          GtkWindow *parent,
Packit Service 639700
                          const char *detail,
Packit Service 639700
                          gpointer detail_data,
Packit Service 639700
                          NMConnection *connection,
Packit Service 639700
                          NMClient *client,
Packit Service 639700
                          PageNewConnectionResultFunc result_func,
Packit Service 639700
                          gpointer user_data)
Packit Service 639700
{
Packit Service 639700
	gs_unref_object NMConnection *connection_tmp = NULL;
Packit Service 639700
	NMSettingIPConfig *s_ip;
Packit Service 639700
Packit Service 639700
	connection = _ensure_connection_other (connection, &connection_tmp);
Packit Service 639700
	ce_page_complete_connection (connection,
Packit Service 639700
	                             _("WireGuard connection %d"),
Packit Service 639700
	                             NM_SETTING_WIREGUARD_SETTING_NAME,
Packit Service 639700
	                             FALSE,
Packit Service 639700
	                             client);
Packit Service 639700
	nm_connection_add_setting (connection, nm_setting_wireguard_new ());
Packit Service 639700
Packit Service 639700
	s_ip = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
Packit Service 639700
	g_object_set (s_ip, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_DISABLED, NULL);
Packit Service 639700
	nm_connection_add_setting (connection, (NMSetting *) s_ip);
Packit Service 639700
Packit Service 639700
	s_ip = (NMSettingIPConfig *) nm_setting_ip6_config_new ();
Packit Service 639700
	g_object_set (s_ip, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
Packit Service 639700
	nm_connection_add_setting (connection, (NMSetting *) s_ip);
Packit Service 639700
Packit Service 639700
	(*result_func) (FUNC_TAG_PAGE_NEW_CONNECTION_RESULT_CALL, connection, FALSE, NULL, user_data);
Packit Service 639700
}