Blame src/connection-editor/page-macsec.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
 * Copyright 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
Packit Service d328f3
#include "page-macsec.h"
Packit Service d328f3
#include "nm-connection-editor.h"
Packit Service d328f3
#include "nma-ui-utils.h"
Packit Service d328f3
Packit Service d328f3
G_DEFINE_TYPE (CEPageMacsec, ce_page_macsec, CE_TYPE_PAGE)
Packit Service d328f3
Packit Service d328f3
#define CE_PAGE_MACSEC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CE_TYPE_PAGE_MACSEC, CEPageMacsecPrivate))
Packit Service d328f3
Packit Service d328f3
typedef struct {
Packit Service d328f3
	NMSettingMacsec *setting;
Packit Service d328f3
Packit Service d328f3
	GtkEntry *name;
Packit Service d328f3
	GtkComboBoxText *parent;
Packit Service d328f3
	GtkComboBox *mode;
Packit Service d328f3
	GtkEntry *cak;
Packit Service d328f3
	GtkEntry *ckn;
Packit Service d328f3
	GtkToggleButton *encryption;
Packit Service d328f3
	GtkComboBox *validation;
Packit Service d328f3
	GtkSpinButton *sci_port;
Packit Service d328f3
} CEPageMacsecPrivate;
Packit Service d328f3
Packit Service d328f3
static void
Packit Service d328f3
macsec_private_init (CEPageMacsec *self)
Packit Service d328f3
{
Packit Service d328f3
	CEPageMacsecPrivate *priv = CE_PAGE_MACSEC_GET_PRIVATE (self);
Packit Service d328f3
	GtkBuilder *builder;
Packit Service d328f3
Packit Service d328f3
	builder = CE_PAGE (self)->builder;
Packit Service d328f3
Packit Service d328f3
	priv->name = GTK_ENTRY (gtk_builder_get_object (builder, "macsec_name"));
Packit Service d328f3
	priv->parent = GTK_COMBO_BOX_TEXT (gtk_builder_get_object (builder, "macsec_parent"));
Packit Service d328f3
	priv->mode = GTK_COMBO_BOX (gtk_builder_get_object (builder, "macsec_mode"));
Packit Service d328f3
	priv->cak = GTK_ENTRY (gtk_builder_get_object (builder, "macsec_cak"));
Packit Service d328f3
	priv->ckn = GTK_ENTRY (gtk_builder_get_object (builder, "macsec_ckn"));
Packit Service d328f3
	priv->encryption = GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "macsec_encryption"));
Packit Service d328f3
	priv->validation = GTK_COMBO_BOX (gtk_builder_get_object (builder, "macsec_validation"));
Packit Service d328f3
	priv->sci_port = GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "macsec_sci_port"));
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
static void
Packit Service d328f3
mode_changed (GtkComboBox *combo, gpointer user_data)
Packit Service d328f3
{
Packit Service d328f3
	CEPageMacsec *self = user_data;
Packit Service d328f3
	CEPageMacsecPrivate *priv = CE_PAGE_MACSEC_GET_PRIVATE (self);
Packit Service d328f3
	NMSettingMacsecMode mode;
Packit Service d328f3
	NMConnection *connection;
Packit Service d328f3
	gboolean mode_psk;
Packit Service d328f3
Packit Service d328f3
	mode = gtk_combo_box_get_active (combo);
Packit Service d328f3
Packit Service d328f3
	mode_psk = mode == NM_SETTING_MACSEC_MODE_PSK;
Packit Service d328f3
Packit Service d328f3
	gtk_widget_set_sensitive (GTK_WIDGET (priv->cak), mode_psk);
Packit Service d328f3
	gtk_widget_set_sensitive (GTK_WIDGET (priv->ckn), mode_psk);
Packit Service d328f3
Packit Service d328f3
	if (!mode_psk) {
Packit Service d328f3
		gtk_entry_set_text (priv->cak, "");
Packit Service d328f3
		gtk_entry_set_text (priv->ckn, "");
Packit Service d328f3
Packit Service d328f3
		connection = CE_PAGE (self)->connection;
Packit Service d328f3
		if (!nm_connection_get_setting_802_1x (connection))
Packit Service d328f3
			nm_connection_add_setting (connection, nm_setting_802_1x_new ());
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
	nm_connection_editor_inter_page_set_value (CE_PAGE (self)->editor,
Packit Service d328f3
	                                           INTER_PAGE_CHANGE_MACSEC_MODE,
Packit Service d328f3
	                                           GUINT_TO_POINTER (mode));
Packit Service d328f3
	ce_page_changed (CE_PAGE (user_data));
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
static void
Packit Service d328f3
populate_ui (CEPageMacsec *self, NMConnection *connection)
Packit Service d328f3
{
Packit Service d328f3
	CEPageMacsecPrivate *priv = CE_PAGE_MACSEC_GET_PRIVATE (self);
Packit Service d328f3
	NMSettingMacsec *setting = priv->setting;
Packit Service d328f3
	NMSettingMacsecMode mode;
Packit Service d328f3
	NMSettingMacsecValidation validation;
Packit Service d328f3
	const char *cak = "", *ckn = "", *str;
Packit Service d328f3
Packit Service d328f3
	str = nm_connection_get_interface_name (CE_PAGE (self)->connection);
Packit Service d328f3
	if (str)
Packit Service d328f3
		gtk_entry_set_text (priv->name, str);
Packit Service d328f3
Packit Service d328f3
	str = nm_setting_macsec_get_parent (setting);
Packit Service d328f3
	ce_page_setup_device_combo (CE_PAGE (self), GTK_COMBO_BOX (priv->parent),
Packit Service d328f3
	                            G_TYPE_NONE, str,
Packit Service d328f3
	                            NULL, NULL);
Packit Service d328f3
Packit Service d328f3
	mode = nm_setting_macsec_get_mode (setting);
Packit Service d328f3
	if (mode >= NM_SETTING_MACSEC_MODE_PSK && mode <= NM_SETTING_MACSEC_MODE_EAP)
Packit Service d328f3
		gtk_combo_box_set_active (priv->mode, mode);
Packit Service d328f3
Packit Service d328f3
	if (mode == NM_SETTING_MACSEC_MODE_PSK) {
Packit Service d328f3
		cak = nm_setting_macsec_get_mka_cak (setting);
Packit Service d328f3
		ckn = nm_setting_macsec_get_mka_ckn (setting);
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
	gtk_entry_set_text (priv->cak, cak ?: "");
Packit Service d328f3
	gtk_entry_set_text (priv->ckn, ckn ?: "");
Packit Service d328f3
Packit Service d328f3
	nma_utils_setup_password_storage ((GtkWidget *) priv->cak, 0,
Packit Service d328f3
	                                  (NMSetting *) priv->setting,
Packit Service d328f3
	                                  NM_SETTING_MACSEC_MKA_CAK,
Packit Service d328f3
	                                  FALSE, FALSE);
Packit Service d328f3
Packit Service d328f3
	gtk_toggle_button_set_active (priv->encryption,
Packit Service d328f3
	                              nm_setting_macsec_get_encrypt (setting));
Packit Service d328f3
Packit Service d328f3
	validation = nm_setting_macsec_get_validation (setting);
Packit Service d328f3
	if (   validation >= NM_SETTING_MACSEC_VALIDATION_DISABLE
Packit Service d328f3
	    && validation <= NM_SETTING_MACSEC_VALIDATION_STRICT)
Packit Service d328f3
		gtk_combo_box_set_active (priv->validation, validation);
Packit Service d328f3
Packit Service d328f3
	gtk_spin_button_set_value (priv->sci_port, nm_setting_macsec_get_port (setting));
Packit Service d328f3
Packit Service d328f3
	mode_changed (priv->mode, self);
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
static void
Packit Service d328f3
stuff_changed (GtkEditable *editable, gpointer user_data)
Packit Service d328f3
{
Packit Service d328f3
	ce_page_changed (CE_PAGE (user_data));
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
static void
Packit Service d328f3
finish_setup (CEPageMacsec *self, gpointer user_data)
Packit Service d328f3
{
Packit Service d328f3
	CEPage *parent = CE_PAGE (self);
Packit Service d328f3
	CEPageMacsecPrivate *priv = CE_PAGE_MACSEC_GET_PRIVATE (self);
Packit Service d328f3
Packit Service d328f3
	populate_ui (self, parent->connection);
Packit Service d328f3
Packit Service d328f3
	g_signal_connect (priv->name, "changed", G_CALLBACK (stuff_changed), self);
Packit Service d328f3
	g_signal_connect (priv->parent, "changed", G_CALLBACK (stuff_changed), self);
Packit Service d328f3
	g_signal_connect (priv->mode, "changed", G_CALLBACK (stuff_changed), self);
Packit Service d328f3
	g_signal_connect (priv->cak, "changed", G_CALLBACK (stuff_changed), self);
Packit Service d328f3
	g_signal_connect (priv->ckn, "changed", G_CALLBACK (stuff_changed), self);
Packit Service d328f3
	g_signal_connect (priv->sci_port, "value-changed", G_CALLBACK (stuff_changed), self);
Packit Service d328f3
	g_signal_connect (priv->validation, "changed", G_CALLBACK (stuff_changed), self);
Packit Service d328f3
	g_signal_connect (priv->encryption, "toggled", G_CALLBACK (stuff_changed), self);
Packit Service d328f3
Packit Service d328f3
	g_signal_connect (priv->mode, "changed", G_CALLBACK (mode_changed), self);
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
CEPage *
Packit Service d328f3
ce_page_macsec_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
	CEPageMacsec *self;
Packit Service d328f3
	CEPageMacsecPrivate *priv;
Packit Service d328f3
Packit Service d328f3
	self = CE_PAGE_MACSEC (ce_page_new (CE_TYPE_PAGE_MACSEC,
Packit Service d328f3
	                                    editor,
Packit Service d328f3
	                                    connection,
Packit Service d328f3
	                                    parent_window,
Packit Service d328f3
	                                    client,
Packit Service d328f3
	                                    "/org/gnome/nm_connection_editor/ce-page-macsec.ui",
Packit Service d328f3
	                                    "MacsecPage",
Packit Service d328f3
	                                   _("MACsec")));
Packit Service d328f3
	if (!self) {
Packit Service d328f3
		g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("Could not load MACsec user interface."));
Packit Service d328f3
		return NULL;
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
	macsec_private_init (self);
Packit Service d328f3
	priv = CE_PAGE_MACSEC_GET_PRIVATE (self);
Packit Service d328f3
Packit Service d328f3
	priv->setting = nm_connection_get_setting_macsec (connection);
Packit Service d328f3
	if (!priv->setting) {
Packit Service d328f3
		priv->setting = NM_SETTING_MACSEC (nm_setting_macsec_new ());
Packit Service d328f3
		nm_connection_add_setting (connection, NM_SETTING (priv->setting));
Packit Service d328f3
	}
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_MACSEC_SETTING_NAME;
Packit Service d328f3
Packit Service d328f3
	return CE_PAGE (self);
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
static void
Packit Service d328f3
ui_to_setting (CEPageMacsec *self)
Packit Service d328f3
{
Packit Service d328f3
	CEPageMacsecPrivate *priv = CE_PAGE_MACSEC_GET_PRIVATE (self);
Packit Service d328f3
	NMSettingConnection *s_con;
Packit Service d328f3
	const char *parent = NULL;
Packit Service d328f3
	const char *cak = NULL;
Packit Service d328f3
	const char *ckn = NULL;
Packit Service d328f3
	NMSettingMacsecMode mode;
Packit Service d328f3
	gboolean encryption;
Packit Service d328f3
	NMSettingMacsecValidation validation;
Packit Service d328f3
	gint sci_port;
Packit Service d328f3
	GtkWidget *entry;
Packit Service d328f3
	NMSettingSecretFlags secret_flags;
Packit Service d328f3
Packit Service d328f3
	s_con = nm_connection_get_setting_connection (CE_PAGE (self)->connection);
Packit Service d328f3
	g_return_if_fail (s_con != NULL);
Packit Service d328f3
	g_object_set (s_con,
Packit Service d328f3
	              NM_SETTING_CONNECTION_INTERFACE_NAME, gtk_entry_get_text (priv->name),
Packit Service d328f3
	              NULL);
Packit Service d328f3
Packit Service d328f3
	entry = gtk_bin_get_child (GTK_BIN (priv->parent));
Packit Service d328f3
	if (entry) {
Packit Service d328f3
		ce_page_device_entry_get (GTK_ENTRY (entry), ARPHRD_ETHER, TRUE,
Packit Service d328f3
		                          (char **) &parent, NULL, NULL, NULL);
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
	mode = gtk_combo_box_get_active (priv->mode);
Packit Service d328f3
Packit Service d328f3
	if (mode == NM_SETTING_MACSEC_MODE_PSK) {
Packit Service d328f3
		cak = gtk_entry_get_text (priv->cak);
Packit Service d328f3
		ckn = gtk_entry_get_text (priv->ckn);
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
	encryption = gtk_toggle_button_get_active (priv->encryption);
Packit Service d328f3
	validation = gtk_combo_box_get_active (priv->validation);
Packit Service d328f3
	sci_port = gtk_spin_button_get_value_as_int (priv->sci_port);
Packit Service d328f3
Packit Service d328f3
	g_object_set (priv->setting,
Packit Service d328f3
	              NM_SETTING_MACSEC_PARENT, parent,
Packit Service d328f3
	              NM_SETTING_MACSEC_MODE, mode,
Packit Service d328f3
	              NM_SETTING_MACSEC_MKA_CAK, cak,
Packit Service d328f3
	              NM_SETTING_MACSEC_MKA_CKN, ckn,
Packit Service d328f3
	              NM_SETTING_MACSEC_ENCRYPT, encryption,
Packit Service d328f3
	              NM_SETTING_MACSEC_VALIDATION, validation,
Packit Service d328f3
	              NM_SETTING_MACSEC_PORT, sci_port,
Packit Service d328f3
	              NULL);
Packit Service d328f3
Packit Service d328f3
	/* Save CAK flags to the connection */
Packit Service d328f3
	secret_flags = nma_utils_menu_to_secret_flags ((GtkWidget *) priv->cak);
Packit Service d328f3
	nm_setting_set_secret_flags (NM_SETTING (priv->setting), NM_SETTING_MACSEC_MKA_CAK,
Packit Service d328f3
	                             secret_flags, NULL);
Packit Service d328f3
Packit Service d328f3
	/* Update secret flags and popup when editing the connection */
Packit Service d328f3
	nma_utils_update_password_storage ((GtkWidget *) priv->cak, secret_flags,
Packit Service d328f3
	                                   NM_SETTING (priv->setting), NM_SETTING_MACSEC_MKA_CAK);
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
	CEPageMacsec *self = CE_PAGE_MACSEC (page);
Packit Service d328f3
	CEPageMacsecPrivate *priv = CE_PAGE_MACSEC_GET_PRIVATE (self);
Packit Service d328f3
Packit Service d328f3
	ui_to_setting (self);
Packit Service d328f3
	return nm_setting_verify (NM_SETTING (priv->setting), connection, error);
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
static gboolean
Packit Service d328f3
inter_page_change (CEPage *page)
Packit Service d328f3
{
Packit Service d328f3
	CEPageMacsecPrivate *priv = CE_PAGE_MACSEC_GET_PRIVATE (page);
Packit Service d328f3
	gpointer enable;
Packit Service d328f3
Packit Service d328f3
	if (nm_connection_editor_inter_page_get_value (page->editor,
Packit Service d328f3
	                                               INTER_PAGE_CHANGE_802_1X_ENABLE,
Packit Service d328f3
	                                               &enable)) {
Packit Service d328f3
		gtk_combo_box_set_active (priv->mode,
Packit Service d328f3
		                          GPOINTER_TO_INT (enable) ?
Packit Service d328f3
		                              NM_SETTING_MACSEC_MODE_EAP :
Packit Service d328f3
		                              NM_SETTING_MACSEC_MODE_PSK);
Packit Service d328f3
		ce_page_changed (page);
Packit Service d328f3
	}
Packit Service d328f3
Packit Service d328f3
	return TRUE;
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
static void
Packit Service d328f3
ce_page_macsec_init (CEPageMacsec *self)
Packit Service d328f3
{
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
static void
Packit Service d328f3
ce_page_macsec_class_init (CEPageMacsecClass *macsec_class)
Packit Service d328f3
{
Packit Service d328f3
	GObjectClass *object_class = G_OBJECT_CLASS (macsec_class);
Packit Service d328f3
	CEPageClass *parent_class = CE_PAGE_CLASS (macsec_class);
Packit Service d328f3
Packit Service d328f3
	g_type_class_add_private (object_class, sizeof (CEPageMacsecPrivate));
Packit Service d328f3
Packit Service d328f3
	/* virtual methods */
Packit Service d328f3
	parent_class->ce_page_validate_v = ce_page_validate_v;
Packit Service d328f3
	parent_class->inter_page_change = inter_page_change;
Packit Service d328f3
}
Packit Service d328f3
Packit Service d328f3
void
Packit Service d328f3
macsec_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
	gs_unref_object NMConnection *connection_tmp = NULL;
Packit Service d328f3
Packit Service d328f3
	connection = _ensure_connection_other (connection, &connection_tmp);
Packit Service d328f3
	ce_page_complete_connection (connection,
Packit Service d328f3
	                             _("MACSEC connection %d"),
Packit Service d328f3
	                             NM_SETTING_MACSEC_SETTING_NAME,
Packit Service d328f3
	                             FALSE,
Packit Service d328f3
	                             client);
Packit Service d328f3
	nm_connection_add_setting (connection, nm_setting_macsec_new ());
Packit Service d328f3
	nm_connection_add_setting (connection, nm_setting_wired_new ());
Packit Service d328f3
Packit Service d328f3
	(*result_func) (FUNC_TAG_PAGE_NEW_CONNECTION_RESULT_CALL, connection, FALSE, NULL, user_data);
Packit Service d328f3
}