From 78ad9d72bac47ae80a346ec5681d0de81256d8ac Mon Sep 17 00:00:00 2001 From: Jonathan Kang Date: Wed, 9 Sep 2020 14:58:06 +0800 Subject: [PATCH] network: complete SAE support Added WirelessSecuritySAE class to fully implement SAE support. --- .../connection-editor/ce-page-security.c | 9 +- panels/network/wireless-security/meson.build | 3 + .../wireless-security.gresource.xml | 1 + panels/network/wireless-security/ws-sae.c | 213 ++++++++++++++++++ panels/network/wireless-security/ws-sae.h | 40 ++++ panels/network/wireless-security/ws-sae.ui | 78 +++++++ 6 files changed, 340 insertions(+), 4 deletions(-) create mode 100644 panels/network/wireless-security/ws-sae.c create mode 100644 panels/network/wireless-security/ws-sae.h create mode 100644 panels/network/wireless-security/ws-sae.ui diff --git a/panels/network/connection-editor/ce-page-security.c b/panels/network/connection-editor/ce-page-security.c index b33e16470..e3729459f 100644 --- a/panels/network/connection-editor/ce-page-security.c +++ b/panels/network/connection-editor/ce-page-security.c @@ -30,6 +30,7 @@ #include "wireless-security.h" #include "ws-dynamic-wep.h" #include "ws-leap.h" +#include "ws-sae.h" #include "ws-wep-key.h" #include "ws-wpa-eap.h" #include "ws-wpa-psk.h" @@ -353,11 +354,11 @@ finish_setup (CEPageSecurity *self) #if NM_CHECK_VERSION(1,20,6) if (nm_utils_security_valid (NMU_SEC_SAE, dev_caps, FALSE, is_adhoc, 0, 0, 0)) { - WirelessSecurityWPAPSK *ws_wpa_psk; + WirelessSecuritySAE *ws_sae; - ws_wpa_psk = ws_wpa_psk_new (self->connection); - if (ws_wpa_psk) { - add_security_item (self, WIRELESS_SECURITY (ws_wpa_psk), sec_model, + ws_sae = ws_sae_new (self->connection); + if (ws_sae) { + add_security_item (self, WIRELESS_SECURITY (ws_sae), sec_model, &iter, _("WPA3 Personal"), FALSE); if ((active < 0) && ((default_type == NMU_SEC_SAE))) active = item; diff --git a/panels/network/wireless-security/meson.build b/panels/network/wireless-security/meson.build index 277be5a85..f30f4eb5d 100644 --- a/panels/network/wireless-security/meson.build +++ b/panels/network/wireless-security/meson.build @@ -14,6 +14,7 @@ nm_applet_headers = [ 'wireless-security.h', 'ws-leap.h', 'ws-dynamic-wep.h', + 'ws-sae.h', 'ws-wep-key.h', 'ws-wpa-eap.h', 'ws-wpa-psk.h' @@ -31,6 +32,7 @@ nm_applet_sources = [ 'wireless-security.c', 'ws-leap.c', 'ws-dynamic-wep.c', + 'ws-sae.c', 'ws-wep-key.c', 'ws-wpa-eap.c', 'ws-wpa-psk.c' @@ -47,6 +49,7 @@ nm_resource_data = [ 'eap-method-ttls.ui', 'ws-dynamic-wep.ui', 'ws-leap.ui', + 'ws-sae.ui', 'ws-wep-key.ui', 'ws-wpa-eap.ui', 'ws-wpa-psk.ui' diff --git a/panels/network/wireless-security/wireless-security.gresource.xml b/panels/network/wireless-security/wireless-security.gresource.xml index a483d06a0..fa1a965ad 100644 --- a/panels/network/wireless-security/wireless-security.gresource.xml +++ b/panels/network/wireless-security/wireless-security.gresource.xml @@ -9,6 +9,7 @@ eap-method-ttls.ui ws-dynamic-wep.ui ws-leap.ui + ws-sae.ui ws-wep-key.ui ws-wpa-eap.ui ws-wpa-psk.ui diff --git a/panels/network/wireless-security/ws-sae.c b/panels/network/wireless-security/ws-sae.c new file mode 100644 index 000000000..67aa484f2 --- /dev/null +++ b/panels/network/wireless-security/ws-sae.c @@ -0,0 +1,213 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager Applet -- allow user control over networking + * + * Jonathan Kang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (c) 2020 SUSE LINUX GmbH, Nuernberg, Germany. + */ + +#include +#include + +#include "helpers.h" +#include "nma-ui-utils.h" +#include "ui-helpers.h" +#include "ws-sae.h" +#include "wireless-security.h" + +#define WPA_PMK_LEN 32 + +struct _WirelessSecuritySAE { + GtkGrid parent; + + GtkEntry *password_entry; + GtkLabel *password_label; + GtkCheckButton *show_password_check; + GtkComboBox *type_combo; + GtkLabel *type_label; +}; + +static void wireless_security_iface_init (WirelessSecurityInterface *); + +G_DEFINE_TYPE_WITH_CODE (WirelessSecuritySAE, ws_sae, GTK_TYPE_GRID, + G_IMPLEMENT_INTERFACE (wireless_security_get_type (), wireless_security_iface_init)); + +static void +show_toggled_cb (WirelessSecuritySAE *self) +{ + gboolean visible; + + visible = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->show_password_check)); + gtk_entry_set_visibility (self->show_password_check, visible); +} + +static gboolean +validate (WirelessSecurity *security, GError **error) +{ + WirelessSecuritySAE *self = WS_SAE (security); + const char *key; + + key = gtk_entry_get_text (self->password_entry); + + if (key == NULL || key[0] == '\0') { + widget_set_error (GTK_WIDGET (self->password_entry)); + g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("missing password")); + return FALSE; + } + widget_unset_error (GTK_WIDGET (self->password_entry)); + + return TRUE; +} + +static void +add_to_size_group (WirelessSecurity *security, GtkSizeGroup *group) +{ + WirelessSecuritySAE *self = WS_SAE (security); + + gtk_size_group_add_widget (group, GTK_WIDGET (self->type_label)); + gtk_size_group_add_widget (group, GTK_WIDGET (self->password_label)); +} + +static void +fill_connection (WirelessSecurity *security, NMConnection *connection) +{ + WirelessSecuritySAE *self = WS_SAE (security); + const char *key; + NMSettingWireless *s_wireless; + NMSettingWirelessSecurity *s_wireless_sec; + NMSettingSecretFlags secret_flags; + const char *mode; + gboolean is_adhoc = FALSE; + + s_wireless = nm_connection_get_setting_wireless (connection); + g_assert (s_wireless); + + mode = nm_setting_wireless_get_mode (s_wireless); + if (mode && !strcmp (mode, "adhoc")) + is_adhoc = TRUE; + + /* Blow away the old security setting by adding a clear one */ + s_wireless_sec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new (); + nm_connection_add_setting (connection, (NMSetting *) s_wireless_sec); + + key = gtk_entry_get_text (self->password_entry); + g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_PSK, key, NULL); + + /* Save PSK_FLAGS to the connection */ + secret_flags = nma_utils_menu_to_secret_flags (GTK_WIDGET (self->password_entry)); + nm_setting_set_secret_flags (NM_SETTING (s_wireless_sec), NM_SETTING_WIRELESS_SECURITY_PSK, + secret_flags, NULL); + + /* Update secret flags and popup when editing the connection */ + nma_utils_update_password_storage (GTK_WIDGET (self->password_entry), secret_flags, + NM_SETTING (s_wireless_sec), NM_SETTING_WIRELESS_SECURITY_PSK); + + wireless_security_clear_ciphers (connection); + if (is_adhoc) { + /* Ad-Hoc settings as specified by the supplicant */ + g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "sae", NULL); + nm_setting_wireless_security_add_proto (s_wireless_sec, "rsn"); + nm_setting_wireless_security_add_pairwise (s_wireless_sec, "ccmp"); + nm_setting_wireless_security_add_group (s_wireless_sec, "ccmp"); + } else { + g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "sae", NULL); + + /* Just leave ciphers and protocol empty, the supplicant will + * figure that out magically based on the AP IEs and card capabilities. + */ + } +} + +static gboolean +adhoc_compatible (WirelessSecurity *security) +{ + return FALSE; +} + +static void +changed_cb (WirelessSecuritySAE *self) +{ + wireless_security_notify_changed ((WirelessSecurity *) self); +} + +void +ws_sae_init (WirelessSecuritySAE *self) +{ + gtk_widget_init_template (GTK_WIDGET (self)); +} + +void +ws_sae_class_init (WirelessSecuritySAEClass *klass) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/ControlCenter/network/ws-sae.ui"); + + gtk_widget_class_bind_template_child (widget_class, WirelessSecuritySAE, password_entry); + gtk_widget_class_bind_template_child (widget_class, WirelessSecuritySAE, password_label); + gtk_widget_class_bind_template_child (widget_class, WirelessSecuritySAE, show_password_check); + gtk_widget_class_bind_template_child (widget_class, WirelessSecuritySAE, type_combo); + gtk_widget_class_bind_template_child (widget_class, WirelessSecuritySAE, type_label); +} + +static void +wireless_security_iface_init (WirelessSecurityInterface *iface) +{ + iface->validate = validate; + iface->add_to_size_group = add_to_size_group; + iface->fill_connection = fill_connection; + iface->adhoc_compatible = adhoc_compatible; +} + +WirelessSecuritySAE * +ws_sae_new (NMConnection *connection) +{ + WirelessSecuritySAE *self; + NMSetting *setting = NULL; + + self = g_object_new (ws_sae_get_type (), NULL); + + g_signal_connect_swapped (self->password_entry, "changed", G_CALLBACK (changed_cb), self); + gtk_entry_set_width_chars (self->password_entry, 28); + + /* Create password-storage popup menu for password entry under entry's secondary icon */ + if (connection) + setting = (NMSetting *) nm_connection_get_setting_wireless_security (connection); + nma_utils_setup_password_storage (GTK_WIDGET (self->password_entry), + 0, setting, NM_SETTING_WIRELESS_SECURITY_PSK, + FALSE, FALSE); + + /* Fill secrets, if any */ + if (connection) { + helper_fill_secret_entry (connection, + self->password_entry, + NM_TYPE_SETTING_WIRELESS_SECURITY, + (HelperSecretFunc) nm_setting_wireless_security_get_psk); + } + + g_signal_connect (self->show_password_check, "toggled", + (GCallback) show_toggled_cb, self); + + /* Hide WPA/RSN for now since this can be autodetected by NM and the + * supplicant when connecting to the AP. + */ + gtk_widget_hide (GTK_WIDGET (self->type_combo)); + gtk_widget_hide (GTK_WIDGET (self->type_label)); + + return self; +} + diff --git a/panels/network/wireless-security/ws-sae.h b/panels/network/wireless-security/ws-sae.h new file mode 100644 index 000000000..312528110 --- /dev/null +++ b/panels/network/wireless-security/ws-sae.h @@ -0,0 +1,40 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager Applet -- allow user control over networking + * + * Jonathan Kang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (c) 2020 SUSE LINUX GmbH, Nuernberg, Germany. + */ + +#ifndef WS_SAE_H +#define WS_SAE_H + +#include +#include + +G_BEGIN_DECLS + +/* For compatibility with NetworkManager-1.20 and earlier. */ +#define NMU_SEC_SAE 9 + +G_DECLARE_FINAL_TYPE (WirelessSecuritySAE, ws_sae, WS, SAE, GtkGrid) + +WirelessSecuritySAE * ws_sae_new (NMConnection *connection); + +G_END_DECLS + +#endif /* WS_SAE_H */ diff --git a/panels/network/wireless-security/ws-sae.ui b/panels/network/wireless-security/ws-sae.ui new file mode 100644 index 000000000..d96bdc32c --- /dev/null +++ b/panels/network/wireless-security/ws-sae.ui @@ -0,0 +1,78 @@ + + + + + + -- 2.26.2