[libnma/lr/nma-ws: 4/7] nma-ws: add
- From: Lubomir Rintel <lkundrak src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libnma/lr/nma-ws: 4/7] nma-ws: add
- Date: Thu, 31 Oct 2019 08:24:25 +0000 (UTC)
commit 3782111cbf6a1b8f617e94097e2c06f56201c212
Author: Lubomir Rintel <lkundrak v3 sk>
Date: Tue Oct 22 06:52:27 2019 +0200
nma-ws: add
This is a library based on src/wireless-security that aims to replace
it, providing a public API in libnma.
The wireless-security code is used by the wifi-dialog provided by libnma,
nm-applet, nm-connection-editor and gnome-control-center, that should all be
ported to this common library.
Makefile.am | 61 ++++-
NEWS | 7 +
po/POTFILES.in | 27 ++
src/libnma.ver | 21 ++
src/meson.build | 10 +-
src/nma-version.h.in | 9 +-
src/nma-ws/meson.build | 44 ++++
src/nma-ws/nma-eap-fast.c | 438 +++++++++++++++++++++++++++++++
src/nma-ws/nma-eap-fast.h | 20 ++
src/nma-ws/nma-eap-fast.ui | 166 ++++++++++++
src/nma-ws/nma-eap-leap.c | 257 ++++++++++++++++++
src/nma-ws/nma-eap-leap.h | 19 ++
src/nma-ws/nma-eap-leap.ui | 82 ++++++
src/nma-ws/nma-eap-peap.c | 486 ++++++++++++++++++++++++++++++++++
src/nma-ws/nma-eap-peap.h | 20 ++
src/nma-ws/nma-eap-peap.ui | 195 ++++++++++++++
src/nma-ws/nma-eap-simple.c | 485 ++++++++++++++++++++++++++++++++++
src/nma-ws/nma-eap-simple.h | 49 ++++
src/nma-ws/nma-eap-simple.ui | 141 ++++++++++
src/nma-ws/nma-eap-tls.c | 497 +++++++++++++++++++++++++++++++++++
src/nma-ws/nma-eap-tls.h | 20 ++
src/nma-ws/nma-eap-tls.ui | 89 +++++++
src/nma-ws/nma-eap-ttls.c | 521 ++++++++++++++++++++++++++++++++++++
src/nma-ws/nma-eap-ttls.h | 20 ++
src/nma-ws/nma-eap-ttls.ui | 148 +++++++++++
src/nma-ws/nma-eap.c | 424 ++++++++++++++++++++++++++++++
src/nma-ws/nma-eap.h | 106 ++++++++
src/nma-ws/nma-ws-802-1x-private.h | 37 +++
src/nma-ws/nma-ws-802-1x.c | 525 +++++++++++++++++++++++++++++++++++++
src/nma-ws/nma-ws-802-1x.h | 31 +++
src/nma-ws/nma-ws-802-1x.ui | 72 +++++
src/nma-ws/nma-ws-dynamic-wep.c | 68 +++++
src/nma-ws/nma-ws-dynamic-wep.h | 34 +++
src/nma-ws/nma-ws-helpers.c | 31 +++
src/nma-ws/nma-ws-helpers.h | 18 ++
src/nma-ws/nma-ws-leap.c | 293 +++++++++++++++++++++
src/nma-ws/nma-ws-leap.h | 32 +++
src/nma-ws/nma-ws-leap.ui | 86 ++++++
src/nma-ws/nma-ws-private.h | 27 ++
src/nma-ws/nma-ws-sae.c | 285 ++++++++++++++++++++
src/nma-ws/nma-ws-sae.h | 30 +++
src/nma-ws/nma-ws-sae.ui | 84 ++++++
src/nma-ws/nma-ws-wep-key.c | 457 ++++++++++++++++++++++++++++++++
src/nma-ws/nma-ws-wep-key.h | 35 +++
src/nma-ws/nma-ws-wep-key.ui | 161 ++++++++++++
src/nma-ws/nma-ws-wpa-eap.c | 70 +++++
src/nma-ws/nma-ws-wpa-eap.h | 35 +++
src/nma-ws/nma-ws-wpa-psk.c | 303 +++++++++++++++++++++
src/nma-ws/nma-ws-wpa-psk.h | 32 +++
src/nma-ws/nma-ws-wpa-psk.ui | 83 ++++++
src/nma-ws/nma-ws.c | 141 ++++++++++
src/nma-ws/nma-ws.h | 56 ++++
src/nma.gresource.xml | 11 +
src/wireless-security/ws-leap.ui | 2 +-
54 files changed, 7389 insertions(+), 12 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 2ff7dbc7..9b5658e4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -246,12 +246,12 @@ src/nma-resources.c: src/nma.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --s
$(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) $< --target=$@ --sourcedir=$(srcdir)/src --generate-source
--internal
src/libnma-gtk4/nma-resources.c: src/nma.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES)
--generate-dependencies $(srcdir)/src/nma.gresource.xml |sed "s,^,$(builddir)/src/libnma-gtk4/,")
- @mkdir -p $(builddir)/src/libnma-gtk4
+ @mkdir -p $(builddir)/src/libnma-gtk4 $(builddir)/src/libnma-gtk4/nma-ws
$(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) $< --target=$@ --sourcedir=$(builddir)/src/libnma-gtk4
--generate-source --internal
src/libnma-gtk4/%.ui: src/%.ui
- @mkdir -p $(builddir)/src/libnma-gtk4
+ @mkdir -p $(builddir)/src/libnma-gtk4 $(builddir)/src/libnma-gtk4/nma-ws
gtk4-builder-tool simplify --3to4 $< |awk '/^</ {xml=1} {if (xml) print; else print >"/dev/stderr"}'
$@
CLEANFILES += \
@@ -277,7 +277,15 @@ libnma_h_pub = \
src/nma-ui-utils.h \
src/nma-cert-chooser.h \
src/nma-bar-code-widget.h \
- src/nma-bar-code.h
+ src/nma-bar-code.h \
+ \
+ src/nma-ws/nma-ws-dynamic-wep.h \
+ src/nma-ws/nma-ws-leap.h \
+ src/nma-ws/nma-ws-sae.h \
+ src/nma-ws/nma-ws-wep-key.h \
+ src/nma-ws/nma-ws-wpa-eap.h \
+ src/nma-ws/nma-ws-wpa-psk.h \
+ src/nma-ws/nma-ws.h
libnma_c_real = \
src/nma-wifi-dialog.c \
@@ -289,7 +297,24 @@ libnma_c_real = \
src/nma-cert-chooser.c \
src/nma-file-cert-chooser.c \
src/nma-bar-code-widget.c \
- src/nma-bar-code.c
+ src/nma-bar-code.c \
+ \
+ src/nma-ws/nma-ws.c \
+ src/nma-ws/nma-ws-802-1x.c \
+ src/nma-ws/nma-ws-sae.c \
+ src/nma-ws/nma-ws-wep-key.c \
+ src/nma-ws/nma-ws-wpa-psk.c \
+ src/nma-ws/nma-ws-leap.c \
+ src/nma-ws/nma-ws-wpa-eap.c \
+ src/nma-ws/nma-ws-dynamic-wep.c \
+ src/nma-ws/nma-eap.c \
+ src/nma-ws/nma-eap-tls.c \
+ src/nma-ws/nma-eap-leap.c \
+ src/nma-ws/nma-eap-fast.c \
+ src/nma-ws/nma-eap-ttls.c \
+ src/nma-ws/nma-eap-peap.c \
+ src/nma-ws/nma-eap-simple.c \
+ src/nma-ws/nma-ws-helpers.c
EXTRA_DIST += \
src/qrcodegen.c \
@@ -297,7 +322,17 @@ EXTRA_DIST += \
libnma_h_priv_real = \
src/nma-cert-chooser-private.h \
- src/nma-private.h
+ src/nma-private.h \
+ src/nma-ws/nma-ws-private.h \
+ src/nma-ws/nma-ws-802-1x-private.h \
+ src/nma-ws/nma-eap.h \
+ src/nma-ws/nma-eap-tls.h \
+ src/nma-ws/nma-eap-leap.h \
+ src/nma-ws/nma-eap-fast.h \
+ src/nma-ws/nma-eap-ttls.h \
+ src/nma-ws/nma-eap-peap.h \
+ src/nma-ws/nma-eap-simple.h \
+ src/nma-ws/nma-ws-helpers.h
libnma_h_priv_gcr = \
src/nma-pkcs11-token-login-dialog.h \
@@ -531,6 +566,7 @@ src_libnma_gtk4_la_CFLAGS = \
"-I$(srcdir)/shared" \
"-I$(srcdir)/src/utils" \
"-I$(srcdir)/src/wireless-security" \
+ "-I$(srcdir)/src/nma-ws" \
"-I$(srcdir)/src" \
-Isrc \
$(GTK4_CFLAGS) \
@@ -724,7 +760,20 @@ EXTRA_DIST += \
src/nma-vpn-password-dialog.ui \
src/nma.gresource.xml \
src/meson.build \
- src/tests/meson.build
+ src/tests/meson.build \
+ \
+ src/nma-ws/nma-eap-fast.ui \
+ src/nma-ws/nma-eap-leap.ui \
+ src/nma-ws/nma-eap-peap.ui \
+ src/nma-ws/nma-eap-simple.ui \
+ src/nma-ws/nma-eap-tls.ui \
+ src/nma-ws/nma-eap-ttls.ui \
+ src/nma-ws/nma-ws-802-1x.ui \
+ src/nma-ws/nma-ws-leap.ui \
+ src/nma-ws/nma-ws-sae.ui \
+ src/nma-ws/nma-ws-wep-key.ui \
+ src/nma-ws/nma-ws-wpa-psk.ui \
+ src/nma-ws/meson.build
###############################################################################
diff --git a/NEWS b/NEWS
index 969f0e20..6bfc9876 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,10 @@
+=======================================================
+libnma-1.8.28
+Overview of changes since network-manager-applet-1.8.26
+=======================================================
+
+* Turned the wireless-security library to a public API
+
=======================================================
libnma-1.8.26
Overview of changes since network-manager-applet-1.8.24
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 67777098..87c2a3de 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -17,6 +17,33 @@ src/nma-ui-utils.c
src/nma-vpn-password-dialog.c
src/nma-vpn-password-dialog.ui
src/nma-wifi-dialog.c
+src/nma-ws/nma-eap.c
+src/nma-ws/nma-eap-fast.c
+src/nma-ws/nma-eap-fast.ui
+src/nma-ws/nma-eap-leap.c
+src/nma-ws/nma-eap-leap.ui
+src/nma-ws/nma-eap-peap.c
+src/nma-ws/nma-eap-peap.ui
+src/nma-ws/nma-eap-simple.c
+src/nma-ws/nma-eap-simple.ui
+src/nma-ws/nma-eap-tls.c
+src/nma-ws/nma-eap-tls.ui
+src/nma-ws/nma-eap-ttls.c
+src/nma-ws/nma-eap-ttls.ui
+src/nma-ws/nma-ws-802-1x.c
+src/nma-ws/nma-ws-802-1x.ui
+src/nma-ws/nma-ws.c
+src/nma-ws/nma-ws-dynamic-wep.c
+src/nma-ws/nma-ws-helpers.c
+src/nma-ws/nma-ws-leap.c
+src/nma-ws/nma-ws-leap.ui
+src/nma-ws/nma-ws-sae.c
+src/nma-ws/nma-ws-sae.ui
+src/nma-ws/nma-ws-wep-key.c
+src/nma-ws/nma-ws-wep-key.ui
+src/nma-ws/nma-ws-wpa-eap.c
+src/nma-ws/nma-ws-wpa-psk.c
+src/nma-ws/nma-ws-wpa-psk.ui
src/wifi.ui
src/utils/utils.c
src/wireless-security/eap-method.c
diff --git a/src/libnma.ver b/src/libnma.ver
index 9b263d9c..1f293ce3 100644
--- a/src/libnma.ver
+++ b/src/libnma.ver
@@ -112,3 +112,24 @@ libnma_1_8_22 {
nma_bar_code_widget_get_type;
nma_bar_code_widget_new;
} libnma_1_8_12;
+
+libnma_1_8_28 {
+ nma_ws_802_1x_get_type;
+ nma_ws_802_1x_new;
+ nma_ws_add_to_size_group;
+ nma_ws_dynamic_wep_get_type;
+ nma_ws_dynamic_wep_new;
+ nma_ws_fill_connection;
+ nma_ws_get_type;
+ nma_ws_leap_get_type;
+ nma_ws_leap_new;
+ nma_ws_sae_get_type;
+ nma_ws_sae_new;
+ nma_ws_validate;
+ nma_ws_wep_key_get_type;
+ nma_ws_wep_key_new;
+ nma_ws_wpa_eap_get_type;
+ nma_ws_wpa_eap_new;
+ nma_ws_wpa_psk_get_type;
+ nma_ws_wpa_psk_new;
+} libnma_1_8_22;
diff --git a/src/meson.build b/src/meson.build
index 280a3415..879bb66c 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -16,6 +16,7 @@ version_header = configure_file(
subdir('utils')
subdir('wireless-security')
+subdir('nma-ws')
cert_chooser_headers = files('nma-cert-chooser.h')
@@ -24,7 +25,7 @@ cert_chooser_sources = files(
'nma-file-cert-chooser.c'
)
-resource_data = files(
+resource_data = nma_ws_resource_data + files(
'nma-bar-code-widget.ui',
'nma-mobile-wizard.ui',
'nma-pkcs11-cert-chooser-dialog.ui',
@@ -39,7 +40,7 @@ built_sources = gnome.compile_resources(
dependencies: resource_data
)
-gir_headers = cert_chooser_headers + files(
+gir_headers = cert_chooser_headers + nma_ws_headers + files(
'nma-bar-code-widget.h',
'nma-bar-code.h',
'nma-mobile-providers.h',
@@ -54,7 +55,7 @@ install_headers(
subdir: 'libnma'
)
-gir_sources = [version_header] + cert_chooser_sources + files(
+gir_sources = [version_header] + cert_chooser_sources + nma_ws_sources + files(
'init.c',
'nma-bar-code-widget.c',
'nma-bar-code.c',
@@ -69,7 +70,8 @@ incs = [
top_inc,
shared_inc,
src_inc,
- wireless_security_inc
+ wireless_security_inc,
+ nma_ws_inc,
]
deps = [
diff --git a/src/nma-version.h.in b/src/nma-version.h.in
index 78e0f206..770791b3 100644
--- a/src/nma-version.h.in
+++ b/src/nma-version.h.in
@@ -59,9 +59,10 @@
#define NMA_VERSION_1_8_10 (NMA_ENCODE_VERSION (1, 8, 10))
#define NMA_VERSION_1_8_12 (NMA_ENCODE_VERSION (1, 8, 12))
#define NMA_VERSION_1_8_22 (NMA_ENCODE_VERSION (1, 8, 22))
+#define NMA_VERSION_1_8_28 (NMA_ENCODE_VERSION (1, 8, 28))
#define NMA_VERSION_CUR_STABLE NMA_VERSION_1_8_10
-#define NMA_VERSION_NEXT_STABLE NMA_VERSION_1_8_22
+#define NMA_VERSION_NEXT_STABLE NMA_VERSION_1_8_28
#define NMA_VERSION NMA_ENCODE_VERSION (NMA_MAJOR_VERSION, NMA_MINOR_VERSION, NMA_MICRO_VERSION)
@@ -116,4 +117,10 @@
# define NMA_AVAILABLE_IN_1_8_22
#endif
+#if NMA_VERSION_MAX_ALLOWED < NMA_VERSION_1_8_28
+# define NMA_AVAILABLE_IN_1_8_28 G_UNAVAILABLE(1.8,28)
+#else
+# define NMA_AVAILABLE_IN_1_8_28
+#endif
+
#endif /* NMA_VERSION_H */
diff --git a/src/nma-ws/meson.build b/src/nma-ws/meson.build
new file mode 100644
index 00000000..8088edab
--- /dev/null
+++ b/src/nma-ws/meson.build
@@ -0,0 +1,44 @@
+nma_ws_inc = include_directories('.')
+
+nma_ws_resource_data = files(
+ 'nma-ws-802-1x.ui',
+ 'nma-ws-leap.ui',
+ 'nma-ws-sae.ui',
+ 'nma-ws-wep-key.ui',
+ 'nma-ws-wpa-psk.ui',
+ 'nma-eap-fast.ui',
+ 'nma-eap-leap.ui',
+ 'nma-eap-peap.ui',
+ 'nma-eap-simple.ui',
+ 'nma-eap-tls.ui',
+ 'nma-eap-ttls.ui',
+)
+
+nma_ws_headers = files(
+ 'nma-ws-dynamic-wep.h',
+ 'nma-ws-leap.h',
+ 'nma-ws-sae.h',
+ 'nma-ws-wep-key.h',
+ 'nma-ws-wpa-eap.h',
+ 'nma-ws-wpa-psk.h',
+ 'nma-ws.h',
+)
+
+nma_ws_sources = files(
+ 'nma-eap.c',
+ 'nma-eap-fast.c',
+ 'nma-eap-leap.c',
+ 'nma-eap-peap.c',
+ 'nma-eap-simple.c',
+ 'nma-eap-tls.c',
+ 'nma-eap-ttls.c',
+ 'nma-ws-802-1x.c',
+ 'nma-ws.c',
+ 'nma-ws-dynamic-wep.c',
+ 'nma-ws-helpers.c',
+ 'nma-ws-leap.c',
+ 'nma-ws-sae.c',
+ 'nma-ws-wep-key.c',
+ 'nma-ws-wpa-eap.c',
+ 'nma-ws-wpa-psk.c',
+)
diff --git a/src/nma-ws/nma-eap-fast.c b/src/nma-ws/nma-eap-fast.c
new file mode 100644
index 00000000..c3b3e42a
--- /dev/null
+++ b/src/nma-ws/nma-eap-fast.c
@@ -0,0 +1,438 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EAP-FAST authentication method (RFC4851)
+ *
+ * Copyright 2012 - 2019 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+#include "nma-private.h"
+
+#include <ctype.h>
+#include <string.h>
+
+#include "nma-eap.h"
+#include "nma-ws.h"
+#include "nma-ws-private.h"
+#include "utils.h"
+
+#define I_NAME_COLUMN 0
+#define I_METHOD_COLUMN 1
+
+struct _NMAEapFast {
+ NMAEap parent;
+
+ const char *password_flags_name;
+ GtkSizeGroup *size_group;
+ NMAWs8021x *ws_8021x;
+ gboolean is_editor;
+};
+
+static void
+destroy (NMAEap *parent)
+{
+ NMAEapFast *method = (NMAEapFast *) parent;
+
+ if (method->size_group)
+ g_object_unref (method->size_group);
+}
+
+static gboolean
+validate (NMAEap *parent, GError **error)
+{
+ GtkWidget *widget;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ NMAEap *eap = NULL;
+ const char *file;
+ gboolean provisioning;
+ gboolean valid = TRUE;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_provision_checkbutton"));
+ g_assert (widget);
+ provisioning = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_file_button"));
+ g_assert (widget);
+ file = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+ if (!provisioning && !file) {
+ widget_set_error (widget);
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("missing EAP-FAST PAC file"));
+ valid = FALSE;
+ } else
+ widget_unset_error (widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_inner_auth_combo"));
+ g_assert (widget);
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+ gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+ g_assert (eap);
+ valid = nma_eap_validate (eap, valid ? error : NULL) && valid;
+ nma_eap_unref (eap);
+ return valid;
+}
+
+static void
+add_to_size_group (NMAEap *parent, GtkSizeGroup *group)
+{
+ NMAEapFast *method = (NMAEapFast *) parent;
+ GtkWidget *widget;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ NMAEap *eap;
+
+ if (method->size_group)
+ g_object_unref (method->size_group);
+ method->size_group = g_object_ref (group);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_anon_identity_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_file_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_provision_checkbutton"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_inner_auth_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_inner_auth_combo"));
+ g_assert (widget);
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+ gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+ g_assert (eap);
+ nma_eap_add_to_size_group (eap, group);
+ nma_eap_unref (eap);
+}
+
+static void
+fill_connection (NMAEap *parent, NMConnection *connection)
+{
+ NMSetting8021x *s_8021x;
+ GtkWidget *widget;
+ const char *text;
+ char *filename;
+ NMAEap *eap = NULL;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gboolean enabled;
+ int pac_provisioning = 0;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ g_assert (s_8021x);
+
+ nm_setting_802_1x_add_eap_method (s_8021x, "fast");
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_anon_identity_entry"));
+ g_assert (widget);
+ text = gtk_editable_get_text (GTK_EDITABLE (widget));
+ if (text && strlen (text))
+ g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, text, NULL);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_file_button"));
+ g_assert (widget);
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+ g_object_set (s_8021x, NM_SETTING_802_1X_PAC_FILE, filename, NULL);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_provision_checkbutton"));
+ enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+
+ if (!enabled)
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "0", NULL);
+ else {
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder,
"eap_fast_pac_provision_combo"));
+ pac_provisioning = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
+
+ switch (pac_provisioning) {
+ case 0: /* Anonymous */
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "1",
NULL);
+ break;
+ case 1: /* Authenticated */
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "2",
NULL);
+ break;
+ case 2: /* Both - anonymous and authenticated */
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "3",
NULL);
+ break;
+ default: /* Should not happen */
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "1",
NULL);
+ break;
+ }
+ }
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_inner_auth_combo"));
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+ gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+ g_assert (eap);
+
+ nma_eap_fill_connection (eap, connection);
+ nma_eap_unref (eap);
+}
+
+static void
+inner_auth_combo_changed_cb (GtkWidget *combo, gpointer user_data)
+{
+ NMAEap *parent = (NMAEap *) user_data;
+ NMAEapFast *method = (NMAEapFast *) parent;
+ GtkWidget *vbox;
+ NMAEap *eap = NULL;
+ GList *elt, *children;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkWidget *eap_widget;
+
+ vbox = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_inner_auth_vbox"));
+ g_assert (vbox);
+
+ /* Remove any previous wireless security widgets */
+ children = gtk_container_get_children (GTK_CONTAINER (vbox));
+ for (elt = children; elt; elt = g_list_next (elt))
+ gtk_container_remove (GTK_CONTAINER (vbox), GTK_WIDGET (elt->data));
+ g_list_free (children);
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter);
+ gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+ g_assert (eap);
+
+ eap_widget = nma_eap_get_widget (eap);
+ g_assert (eap_widget);
+ gtk_widget_unparent (eap_widget);
+
+ if (method->size_group)
+ nma_eap_add_to_size_group (eap, method->size_group);
+ gtk_container_add (GTK_CONTAINER (vbox), eap_widget);
+
+ nma_eap_unref (eap);
+
+ nma_ws_changed_cb (combo, method->ws_8021x);
+}
+
+static GtkWidget *
+inner_auth_combo_init (NMAEapFast *method,
+ NMConnection *connection,
+ NMSetting8021x *s_8021x,
+ gboolean secrets_only)
+{
+ NMAEap *parent = (NMAEap *) method;
+ GtkWidget *combo;
+ GtkListStore *auth_model;
+ GtkTreeIter iter;
+ NMAEapSimple *em_gtc;
+ NMAEapSimple *em_mschap_v2;
+ guint32 active = 0;
+ const char *phase2_auth = NULL;
+ NMAEapSimpleFlags simple_flags;
+
+ auth_model = gtk_list_store_new (2, G_TYPE_STRING, nma_eap_get_type ());
+
+ if (s_8021x) {
+ if (nm_setting_802_1x_get_phase2_auth (s_8021x))
+ phase2_auth = nm_setting_802_1x_get_phase2_auth (s_8021x);
+ else if (nm_setting_802_1x_get_phase2_autheap (s_8021x))
+ phase2_auth = nm_setting_802_1x_get_phase2_autheap (s_8021x);
+ }
+
+ simple_flags = NMA_EAP_SIMPLE_FLAG_PHASE2;
+ if (method->is_editor)
+ simple_flags |= NMA_EAP_SIMPLE_FLAG_IS_EDITOR;
+ if (secrets_only)
+ simple_flags |= NMA_EAP_SIMPLE_FLAG_SECRETS_ONLY;
+
+ em_gtc = nma_eap_simple_new (method->ws_8021x,
+ connection,
+ NMA_EAP_SIMPLE_TYPE_GTC,
+ simple_flags,
+ NULL);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ I_NAME_COLUMN, _("GTC"),
+ I_METHOD_COLUMN, em_gtc,
+ -1);
+ nma_eap_unref (NMA_EAP (em_gtc));
+
+ /* Check for defaulting to GTC */
+ if (phase2_auth && !strcasecmp (phase2_auth, "gtc"))
+ active = 0;
+
+ em_mschap_v2 = nma_eap_simple_new (method->ws_8021x,
+ connection,
+ NMA_EAP_SIMPLE_TYPE_MSCHAP_V2,
+ simple_flags,
+ NULL);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ I_NAME_COLUMN, _("MSCHAPv2"),
+ I_METHOD_COLUMN, em_mschap_v2,
+ -1);
+ nma_eap_unref (NMA_EAP (em_mschap_v2));
+
+ /* Check for defaulting to MSCHAPv2 */
+ if (phase2_auth && !strcasecmp (phase2_auth, "mschapv2"))
+ active = 1;
+
+ combo = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_inner_auth_combo"));
+ g_assert (combo);
+
+ gtk_combo_box_set_model (GTK_COMBO_BOX (combo), GTK_TREE_MODEL (auth_model));
+ g_object_unref (G_OBJECT (auth_model));
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combo), active);
+
+ g_signal_connect (G_OBJECT (combo), "changed",
+ (GCallback) inner_auth_combo_changed_cb,
+ method);
+ return combo;
+}
+
+static void
+update_secrets (NMAEap *parent, NMConnection *connection)
+{
+ nma_eap_phase2_update_secrets_helper (parent,
+ connection,
+ "eap_fast_inner_auth_combo",
+ I_METHOD_COLUMN);
+}
+
+static void
+pac_toggled_cb (GtkWidget *widget, gpointer user_data)
+{
+ NMAEap *parent = (NMAEap *) user_data;
+ NMAEapFast *method = (NMAEapFast *) parent;
+ gboolean enabled = FALSE;
+ GtkWidget *provision_combo;
+
+ provision_combo = GTK_WIDGET (gtk_builder_get_object (parent->builder,
"eap_fast_pac_provision_combo"));
+ g_return_if_fail (provision_combo);
+
+ enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+
+ gtk_widget_set_sensitive (provision_combo, enabled);
+
+ nma_ws_changed_cb (widget, method->ws_8021x);
+}
+
+NMAEapFast *
+nma_eap_fast_new (NMAWs8021x *ws_8021x,
+ NMConnection *connection,
+ gboolean is_editor,
+ gboolean secrets_only)
+{
+ NMAEap *parent;
+ NMAEapFast *method;
+ GtkWidget *widget;
+ GtkFileFilter *filter;
+ NMSetting8021x *s_8021x = NULL;
+ const char *filename;
+ gboolean provisioning_enabled = TRUE;
+
+ parent = nma_eap_init (sizeof (NMAEapFast),
+ validate,
+ add_to_size_group,
+ fill_connection,
+ update_secrets,
+ destroy,
+ "/org/gnome/libnma/nma-eap-fast.ui",
+ "eap_fast_grid",
+ "eap_fast_anon_identity_entry",
+ FALSE);
+ if (!parent)
+ return NULL;
+
+ method = (NMAEapFast *) parent;
+ method->password_flags_name = NM_SETTING_802_1X_PASSWORD;
+ method->ws_8021x = ws_8021x;
+ method->is_editor = is_editor;
+
+ if (connection)
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_provision_combo"));
+ g_assert (widget);
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
+ if (s_8021x) {
+ const char *fast_prov;
+
+ fast_prov = nm_setting_802_1x_get_phase1_fast_provisioning (s_8021x);
+ if (fast_prov) {
+ if (!strcmp (fast_prov, "0"))
+ provisioning_enabled = FALSE;
+ else if (!strcmp (fast_prov, "1"))
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
+ else if (!strcmp (fast_prov, "2"))
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 1);
+ else if (!strcmp (fast_prov, "3"))
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 2);
+ }
+ }
+ gtk_widget_set_sensitive (widget, provisioning_enabled);
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) nma_ws_changed_cb,
+ ws_8021x);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_provision_checkbutton"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), provisioning_enabled);
+ g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (pac_toggled_cb), parent);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_anon_identity_entry"));
+ if (s_8021x && nm_setting_802_1x_get_anonymous_identity (s_8021x))
+ gtk_editable_set_text (GTK_EDITABLE (widget), nm_setting_802_1x_get_anonymous_identity
(s_8021x));
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) nma_ws_changed_cb,
+ ws_8021x);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_file_button"));
+ g_assert (widget);
+ gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (widget), TRUE);
+ gtk_file_chooser_button_set_title (GTK_FILE_CHOOSER_BUTTON (widget),
+ _("Choose a PAC file"));
+ g_signal_connect (G_OBJECT (widget), "selection-changed",
+ (GCallback) nma_ws_changed_cb,
+ ws_8021x);
+
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_add_pattern (filter, "*.pac");
+ gtk_file_filter_set_name (filter, _("PAC files (*.pac)"));
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (widget), filter);
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_add_pattern (filter, "*");
+ gtk_file_filter_set_name (filter, _("All files"));
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (widget), filter);
+
+ if (connection && s_8021x) {
+ filename = nm_setting_802_1x_get_pac_file (s_8021x);
+ if (filename)
+ gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), filename);
+ }
+
+ widget = inner_auth_combo_init (method, connection, s_8021x, secrets_only);
+ inner_auth_combo_changed_cb (widget, (gpointer) method);
+
+ if (secrets_only) {
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder,
"eap_fast_anon_identity_label"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder,
"eap_fast_anon_identity_entry"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder,
"eap_fast_pac_provision_checkbutton"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder,
"eap_fast_pac_provision_combo"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_file_label"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_pac_file_button"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_inner_auth_label"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_fast_inner_auth_combo"));
+ gtk_widget_hide (widget);
+ }
+
+ return method;
+}
diff --git a/src/nma-ws/nma-eap-fast.h b/src/nma-ws/nma-eap-fast.h
new file mode 100644
index 00000000..a63d9707
--- /dev/null
+++ b/src/nma-ws/nma-eap-fast.h
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EAP-FAST authentication method (RFC4851)
+ *
+ * Copyright 2012 - 2019 Red Hat, Inc.
+ */
+
+#ifndef NMA_EAP_FAST_H
+#define NMA_EAP_FAST_H
+
+#include "nma-ws.h"
+
+typedef struct _NMAEapFast NMAEapFast;
+
+NMAEapFast *nma_eap_fast_new (NMAWs8021x *ws_8021x,
+ NMConnection *connection,
+ gboolean is_editor,
+ gboolean secrets_only);
+
+#endif /* NMA_EAP_FAST_H */
diff --git a/src/nma-ws/nma-eap-fast.ui b/src/nma-ws/nma-eap-fast.ui
new file mode 100644
index 00000000..ed33a819
--- /dev/null
+++ b/src/nma-ws/nma-eap-fast.ui
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="nm-applet">
+ <requires lib="gtk+" version="3.10"/>
+ <object class="GtkListStore" id="model8">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0"> </col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="model9">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">Anonymous</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Authenticated</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Both</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkGrid" id="eap_fast_grid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="eap_fast_anon_identity_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Anony_mous identity</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_fast_anon_identity_entry</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="eap_fast_anon_identity_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eap_fast_pac_file_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">PAC _file</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_fast_pac_file_button</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFileChooserButton" id="eap_fast_pac_file_button">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="eap_fast_inner_auth_vbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eap_fast_inner_auth_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Inner authentication</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_fast_inner_auth_combo</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="eap_fast_inner_auth_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">model8</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer8"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="eap_fast_pac_provision_checkbutton">
+ <property name="label" translatable="yes">Allow automatic PAC pro_visioning</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="eap_fast_pac_provision_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">model9</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer9"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/src/nma-ws/nma-eap-leap.c b/src/nma-ws/nma-eap-leap.c
new file mode 100644
index 00000000..d0929efc
--- /dev/null
+++ b/src/nma-ws/nma-eap-leap.c
@@ -0,0 +1,257 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Dan Williams <dcbw redhat com>
+ *
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+#include "nma-private.h"
+
+#include <ctype.h>
+#include <string.h>
+
+#include "nma-eap.h"
+#include "nma-ws.h"
+#include "nma-ws-private.h"
+#include "nma-ws-helpers.h"
+#include "nma-ws-802-1x.h"
+#include "nma-ws-802-1x-private.h"
+#include "nma-ui-utils.h"
+#include "utils.h"
+
+struct _NMAEapLeap {
+ NMAEap parent;
+
+ NMAWs8021x *ws_8021x;
+
+ gboolean editing_connection;
+
+ const char *password_flags_name;
+ GtkEntry *username_entry;
+ GtkEntry *password_entry;
+ GtkToggleButton *show_password;
+};
+
+static void
+show_toggled_cb (GtkToggleButton *button, NMAEapLeap *method)
+{
+ gboolean visible;
+
+ visible = gtk_toggle_button_get_active (button);
+ gtk_entry_set_visibility (method->password_entry, visible);
+}
+
+static gboolean
+validate (NMAEap *parent, GError **error)
+{
+ NMAEapLeap *method = (NMAEapLeap *)parent;
+ const char *text;
+ gboolean ret = TRUE;
+
+ text = gtk_editable_get_text (GTK_EDITABLE (method->username_entry));
+ if (!text || !strlen (text)) {
+ widget_set_error (GTK_WIDGET (method->username_entry));
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("missing EAP-LEAP username"));
+ ret = FALSE;
+ } else
+ widget_unset_error (GTK_WIDGET (method->username_entry));
+
+ text = gtk_editable_get_text (GTK_EDITABLE (method->password_entry));
+ if (!text || !strlen (text)) {
+ widget_set_error (GTK_WIDGET (method->password_entry));
+ if (ret) {
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("missing EAP-LEAP
password"));
+ ret = FALSE;
+ }
+ } else
+ widget_unset_error (GTK_WIDGET (method->password_entry));
+
+ return ret;
+}
+
+static void
+add_to_size_group (NMAEap *parent, GtkSizeGroup *group)
+{
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_leap_username_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_leap_password_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+}
+
+static void
+fill_connection (NMAEap *parent, NMConnection *connection)
+{
+ NMAEapLeap *method = (NMAEapLeap *) parent;
+ NMSetting8021x *s_8021x;
+ NMSettingSecretFlags secret_flags;
+ GtkWidget *passwd_entry;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ g_assert (s_8021x);
+
+ nm_setting_802_1x_add_eap_method (s_8021x, "leap");
+
+ g_object_set (s_8021x,
+ NM_SETTING_802_1X_IDENTITY, gtk_editable_get_text (GTK_EDITABLE
(method->username_entry)),
+ NM_SETTING_802_1X_PASSWORD, gtk_editable_get_text (GTK_EDITABLE
(method->password_entry)),
+ NULL);
+
+ passwd_entry = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_leap_password_entry"));
+ g_assert (passwd_entry);
+
+ /* Save 802.1X password flags to the connection */
+ secret_flags = nma_utils_menu_to_secret_flags (passwd_entry);
+ nm_setting_set_secret_flags (NM_SETTING (s_8021x), method->password_flags_name,
+ secret_flags, NULL);
+
+ /* Update secret flags and popup when editing the connection */
+ if (method->editing_connection)
+ nma_utils_update_password_storage (passwd_entry, secret_flags,
+ NM_SETTING (s_8021x), method->password_flags_name);
+}
+
+static void
+update_secrets (NMAEap *parent, NMConnection *connection)
+{
+ nma_ws_helper_fill_secret_entry (connection,
+ GTK_EDITABLE (gtk_builder_get_object (parent->builder,
"eap_leap_password_entry")),
+ NM_TYPE_SETTING_802_1X,
+ (HelperSecretFunc) nm_setting_802_1x_get_password);
+}
+
+/* Set the UI fields for user, password and show_password to the
+ * values as provided by method->ws_8021x. */
+static void
+set_userpass_ui (NMAEapLeap *method)
+{
+ if (method->ws_8021x->username) {
+ gtk_editable_set_text (GTK_EDITABLE (method->username_entry),
+ method->ws_8021x->username);
+ } else {
+ gtk_editable_set_text (GTK_EDITABLE (method->username_entry), "");
+ }
+
+ if (method->ws_8021x->password && !method->ws_8021x->always_ask) {
+ gtk_editable_set_text (GTK_EDITABLE (method->password_entry),
+ method->ws_8021x->password);
+ } else {
+ gtk_editable_set_text (GTK_EDITABLE (method->password_entry), "");
+ }
+
+ gtk_toggle_button_set_active (method->show_password, method->ws_8021x->show_password);
+}
+
+static void
+widgets_realized (GtkWidget *widget, NMAEapLeap *method)
+{
+ set_userpass_ui (method);
+}
+
+static void
+widgets_unrealized (GtkWidget *widget, NMAEapLeap *method)
+{
+ nma_ws_802_1x_set_userpass (method->ws_8021x,
+ gtk_editable_get_text (GTK_EDITABLE (method->username_entry)),
+ gtk_editable_get_text (GTK_EDITABLE (method->password_entry)),
+ (gboolean) -1,
+ gtk_toggle_button_get_active (method->show_password));
+}
+
+static void
+destroy (NMAEap *parent)
+{
+ NMAEapLeap *method = (NMAEapLeap *) parent;
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_leap_grid"));
+ g_assert (widget);
+ g_signal_handlers_disconnect_by_data (widget, method);
+
+ g_signal_handlers_disconnect_by_data (method->username_entry, method->ws_8021x);
+ g_signal_handlers_disconnect_by_data (method->password_entry, method->ws_8021x);
+ g_signal_handlers_disconnect_by_data (method->show_password, method);
+}
+
+NMAEapLeap *
+nma_eap_leap_new (NMAWs8021x *ws_8021x,
+ NMConnection *connection,
+ gboolean secrets_only)
+{
+ NMAEapLeap *method;
+ NMAEap *parent;
+ GtkWidget *widget;
+ NMSetting8021x *s_8021x = NULL;
+
+ parent = nma_eap_init (sizeof (NMAEapLeap),
+ validate,
+ add_to_size_group,
+ fill_connection,
+ update_secrets,
+ destroy,
+ "/org/gnome/libnma/nma-eap-leap.ui",
+ "eap_leap_grid",
+ "eap_leap_username_entry",
+ FALSE);
+ if (!parent)
+ return NULL;
+
+ method = (NMAEapLeap *) parent;
+ method->password_flags_name = NM_SETTING_802_1X_PASSWORD;
+ method->editing_connection = secrets_only ? FALSE : TRUE;
+ method->ws_8021x = ws_8021x;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_leap_grid"));
+ g_assert (widget);
+ g_signal_connect (G_OBJECT (widget), "realize",
+ (GCallback) widgets_realized,
+ method);
+ g_signal_connect (G_OBJECT (widget), "unrealize",
+ (GCallback) widgets_unrealized,
+ method);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_leap_username_entry"));
+ g_assert (widget);
+ method->username_entry = GTK_ENTRY (widget);
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) nma_ws_changed_cb,
+ ws_8021x);
+
+ if (secrets_only)
+ gtk_widget_set_sensitive (widget, FALSE);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_leap_password_entry"));
+ g_assert (widget);
+ method->password_entry = GTK_ENTRY (widget);
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) nma_ws_changed_cb,
+ ws_8021x);
+
+ /* Create password-storage popup menu for password entry under entry's secondary icon */
+ if (connection)
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ nma_utils_setup_password_storage (widget, 0, (NMSetting *) s_8021x, method->password_flags_name,
+ FALSE, secrets_only);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "show_checkbutton_eapleap"));
+ g_assert (widget);
+ method->show_password = GTK_TOGGLE_BUTTON (widget);
+ g_signal_connect (G_OBJECT (widget), "toggled",
+ (GCallback) show_toggled_cb,
+ parent);
+
+ /* Initialize the UI fields with the security settings from method->ws_8021x.
+ * This will be done again when the widget gets realized. It must be done here as well,
+ * because the outer dialog will ask to 'validate' the connection before the security tab
+ * is shown/realized (to enable the 'Apply' button).
+ * As 'validate' accesses the contents of the UI fields, they must be initialized now, even
+ * if the widgets are not yet visible. */
+ set_userpass_ui (method);
+
+ return method;
+}
diff --git a/src/nma-ws/nma-eap-leap.h b/src/nma-ws/nma-eap-leap.h
new file mode 100644
index 00000000..c75aa56a
--- /dev/null
+++ b/src/nma-ws/nma-eap-leap.h
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Dan Williams <dcbw redhat com>
+ *
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+
+#ifndef NMA_EAP_LEAP_H
+#define NMA_EAP_LEAP_H
+
+#include "nma-ws.h"
+
+typedef struct _NMAEapLeap NMAEapLeap;
+
+NMAEapLeap *nma_eap_leap_new (NMAWs8021x *ws_8021x,
+ NMConnection *connection,
+ gboolean secrets_only);
+
+#endif /* NMA_EAP_LEAP_H */
diff --git a/src/nma-ws/nma-eap-leap.ui b/src/nma-ws/nma-eap-leap.ui
new file mode 100644
index 00000000..a3cfae72
--- /dev/null
+++ b/src/nma-ws/nma-eap-leap.ui
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="nm-applet">
+ <requires lib="gtk+" version="3.10"/>
+ <object class="GtkGrid" id="eap_leap_grid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">start</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="eap_leap_username_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Username</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_leap_username_entry</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eap_leap_password_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Password</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_leap_password_entry</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="eap_leap_password_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="visibility">False</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="show_checkbutton_eapleap">
+ <property name="label" translatable="yes">Sho_w password</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="eap_leap_username_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+</interface>
diff --git a/src/nma-ws/nma-eap-peap.c b/src/nma-ws/nma-eap-peap.c
new file mode 100644
index 00000000..3f96c46d
--- /dev/null
+++ b/src/nma-ws/nma-eap-peap.c
@@ -0,0 +1,486 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Dan Williams <dcbw redhat com>
+ *
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+#include "nma-private.h"
+
+#include <ctype.h>
+#include <string.h>
+
+#include "nma-eap.h"
+#include "nma-ws.h"
+#include "nma-ws-private.h"
+#include "nma-cert-chooser.h"
+#include "utils.h"
+
+#define I_NAME_COLUMN 0
+#define I_METHOD_COLUMN 1
+
+struct _NMAEapPeap {
+ NMAEap parent;
+
+ const char *password_flags_name;
+ GtkSizeGroup *size_group;
+ NMAWs8021x *ws_8021x;
+ gboolean is_editor;
+ GtkWidget *ca_cert_chooser;
+};
+
+static void
+destroy (NMAEap *parent)
+{
+ NMAEapPeap *method = (NMAEapPeap *) parent;
+
+ if (method->size_group)
+ g_object_unref (method->size_group);
+}
+
+static gboolean
+validate (NMAEap *parent, GError **error)
+{
+ NMAEapPeap *method = (NMAEapPeap *) parent;
+ GtkWidget *widget;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ NMAEap *eap = NULL;
+ gboolean valid = FALSE;
+
+ if ( gtk_widget_get_sensitive (method->ca_cert_chooser)
+ && !nma_cert_chooser_validate (NMA_CERT_CHOOSER (method->ca_cert_chooser), error))
+ return FALSE;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_inner_auth_combo"));
+ g_assert (widget);
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+ gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+ g_assert (eap);
+ valid = nma_eap_validate (eap, error);
+ nma_eap_unref (eap);
+ return valid;
+}
+
+static void
+ca_cert_not_required_toggled (GtkWidget *button, gpointer user_data)
+{
+ NMAEapPeap *method = (NMAEapPeap *) user_data;
+
+ gtk_widget_set_sensitive (method->ca_cert_chooser,
+ !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)));
+}
+
+static void
+add_to_size_group (NMAEap *parent, GtkSizeGroup *group)
+{
+ NMAEapPeap *method = (NMAEapPeap *) parent;
+ GtkWidget *widget;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ NMAEap *eap;
+
+ if (method->size_group)
+ g_object_unref (method->size_group);
+ method->size_group = g_object_ref (group);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_anon_identity_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_domain_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ nma_cert_chooser_add_to_size_group (NMA_CERT_CHOOSER (method->ca_cert_chooser), group);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_version_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_inner_auth_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_inner_auth_combo"));
+ g_assert (widget);
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+ gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+ g_assert (eap);
+ nma_eap_add_to_size_group (eap, group);
+ nma_eap_unref (eap);
+}
+
+static void
+fill_connection (NMAEap *parent, NMConnection *connection)
+{
+ NMAEapPeap *method = (NMAEapPeap *) parent;
+ NMSetting8021x *s_8021x;
+ NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ GtkWidget *widget;
+ const char *text;
+ char *value = NULL;
+ NMAEap *eap = NULL;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ int peapver_active = 0;
+ GError *error = NULL;
+ gboolean ca_cert_error = FALSE;
+ NMSetting8021xCKScheme scheme = NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
+ NMSettingSecretFlags secret_flags;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ g_assert (s_8021x);
+
+ nm_setting_802_1x_add_eap_method (s_8021x, "peap");
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_anon_identity_entry"));
+ g_assert (widget);
+ text = gtk_editable_get_text (GTK_EDITABLE (widget));
+ if (text && strlen (text))
+ g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, text, NULL);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_domain_entry"));
+ g_assert (widget);
+ text = gtk_editable_get_text (GTK_EDITABLE (widget));
+ if (text && strlen (text))
+ g_object_set (s_8021x, NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH, text, NULL);
+
+ /* Save CA certificate PIN and its flags to the connection */
+ secret_flags = nma_cert_chooser_get_cert_password_flags (NMA_CERT_CHOOSER (method->ca_cert_chooser));
+ nm_setting_set_secret_flags (NM_SETTING (s_8021x), NM_SETTING_802_1X_CA_CERT_PASSWORD,
+ secret_flags, NULL);
+ if (method->is_editor) {
+ /* Update secret flags and popup when editing the connection */
+ nma_cert_chooser_update_cert_password_storage (NMA_CERT_CHOOSER (method->ca_cert_chooser),
+ secret_flags, NM_SETTING (s_8021x),
+ NM_SETTING_802_1X_CA_CERT_PASSWORD);
+ g_object_set (s_8021x, NM_SETTING_802_1X_CA_CERT_PASSWORD,
+ nma_cert_chooser_get_cert_password (NMA_CERT_CHOOSER (method->ca_cert_chooser)),
+ NULL);
+ }
+
+ /* TLS CA certificate */
+ if (gtk_widget_get_sensitive (method->ca_cert_chooser))
+ value = nma_cert_chooser_get_cert (NMA_CERT_CHOOSER (method->ca_cert_chooser), &scheme);
+ format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ if (!nm_setting_802_1x_set_ca_cert (s_8021x, value, scheme, &format, &error)) {
+ g_warning ("Couldn't read CA certificate '%s': %s", value, error ? error->message :
"(unknown)");
+ g_clear_error (&error);
+ ca_cert_error = TRUE;
+ }
+ nma_eap_ca_cert_ignore_set (parent, connection, value, ca_cert_error);
+ g_free (value);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_version_combo"));
+ peapver_active = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
+ switch (peapver_active) {
+ case 1: /* PEAP v0 */
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_PEAPVER, "0", NULL);
+ break;
+ case 2: /* PEAP v1 */
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_PEAPVER, "1", NULL);
+ break;
+ default: /* Automatic */
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_PEAPVER, NULL, NULL);
+ break;
+ }
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_inner_auth_combo"));
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+ gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+ g_assert (eap);
+
+ nma_eap_fill_connection (eap, connection);
+ nma_eap_unref (eap);
+}
+static void
+inner_auth_combo_changed_cb (GtkWidget *combo, gpointer user_data)
+{
+ NMAEap *parent = (NMAEap *) user_data;
+ NMAEapPeap *method = (NMAEapPeap *) parent;
+ GtkWidget *vbox;
+ NMAEap *eap = NULL;
+ GList *elt, *children;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkWidget *eap_widget;
+
+ vbox = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_inner_auth_vbox"));
+ g_assert (vbox);
+
+ /* Remove any previous wireless security widgets */
+ children = gtk_container_get_children (GTK_CONTAINER (vbox));
+ for (elt = children; elt; elt = g_list_next (elt))
+ gtk_container_remove (GTK_CONTAINER (vbox), GTK_WIDGET (elt->data));
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter);
+ gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+ g_assert (eap);
+
+ eap_widget = nma_eap_get_widget (eap);
+ g_assert (eap_widget);
+ gtk_widget_unparent (eap_widget);
+
+ if (method->size_group)
+ nma_eap_add_to_size_group (eap, method->size_group);
+ gtk_container_add (GTK_CONTAINER (vbox), eap_widget);
+
+ nma_eap_unref (eap);
+
+ nma_ws_changed_cb (combo, method->ws_8021x);
+}
+
+static GtkWidget *
+inner_auth_combo_init (NMAEapPeap *method,
+ NMConnection *connection,
+ NMSetting8021x *s_8021x,
+ gboolean secrets_only)
+{
+ NMAEap *parent = (NMAEap *) method;
+ GtkWidget *combo;
+ GtkListStore *auth_model;
+ GtkTreeIter iter;
+ NMAEapSimple *em_mschap_v2;
+ NMAEapSimple *em_md5;
+ NMAEapSimple *em_gtc;
+ guint32 active = 0;
+ const char *phase2_auth = NULL;
+ NMAEapSimpleFlags simple_flags;
+
+ auth_model = gtk_list_store_new (2, G_TYPE_STRING, nma_eap_get_type ());
+
+ if (s_8021x) {
+ if (nm_setting_802_1x_get_phase2_auth (s_8021x))
+ phase2_auth = nm_setting_802_1x_get_phase2_auth (s_8021x);
+ else if (nm_setting_802_1x_get_phase2_autheap (s_8021x))
+ phase2_auth = nm_setting_802_1x_get_phase2_autheap (s_8021x);
+ }
+
+ simple_flags = NMA_EAP_SIMPLE_FLAG_PHASE2;
+ if (method->is_editor)
+ simple_flags |= NMA_EAP_SIMPLE_FLAG_IS_EDITOR;
+ if (secrets_only)
+ simple_flags |= NMA_EAP_SIMPLE_FLAG_SECRETS_ONLY;
+
+ em_mschap_v2 = nma_eap_simple_new (method->ws_8021x,
+ connection,
+ NMA_EAP_SIMPLE_TYPE_MSCHAP_V2,
+ simple_flags,
+ NULL);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ I_NAME_COLUMN, _("MSCHAPv2"),
+ I_METHOD_COLUMN, em_mschap_v2,
+ -1);
+ nma_eap_unref (NMA_EAP (em_mschap_v2));
+
+ /* Check for defaulting to MSCHAPv2 */
+ if (phase2_auth && !strcasecmp (phase2_auth, "mschapv2"))
+ active = 0;
+
+ em_md5 = nma_eap_simple_new (method->ws_8021x,
+ connection,
+ NMA_EAP_SIMPLE_TYPE_MD5,
+ simple_flags,
+ NULL);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ I_NAME_COLUMN, _("MD5"),
+ I_METHOD_COLUMN, em_md5,
+ -1);
+ nma_eap_unref (NMA_EAP (em_md5));
+
+ /* Check for defaulting to MD5 */
+ if (phase2_auth && !strcasecmp (phase2_auth, "md5"))
+ active = 1;
+
+ em_gtc = nma_eap_simple_new (method->ws_8021x,
+ connection,
+ NMA_EAP_SIMPLE_TYPE_GTC,
+ simple_flags,
+ NULL);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ I_NAME_COLUMN, _("GTC"),
+ I_METHOD_COLUMN, em_gtc,
+ -1);
+ nma_eap_unref (NMA_EAP (em_gtc));
+
+ /* Check for defaulting to GTC */
+ if (phase2_auth && !strcasecmp (phase2_auth, "gtc"))
+ active = 2;
+
+ combo = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_inner_auth_combo"));
+ g_assert (combo);
+
+ gtk_combo_box_set_model (GTK_COMBO_BOX (combo), GTK_TREE_MODEL (auth_model));
+ g_object_unref (G_OBJECT (auth_model));
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combo), active);
+
+ g_signal_connect (G_OBJECT (combo), "changed",
+ (GCallback) inner_auth_combo_changed_cb,
+ method);
+ return combo;
+}
+
+static void
+update_secrets (NMAEap *parent, NMConnection *connection)
+{
+ nma_eap_phase2_update_secrets_helper (parent,
+ connection,
+ "eap_peap_inner_auth_combo",
+ I_METHOD_COLUMN);
+}
+
+NMAEapPeap *
+nma_eap_peap_new (NMAWs8021x *ws_8021x,
+ NMConnection *connection,
+ gboolean is_editor,
+ gboolean secrets_only)
+{
+ NMAEap *parent;
+ NMAEapPeap *method;
+ GtkWidget *widget;
+ NMSetting8021x *s_8021x = NULL;
+ gboolean ca_not_required = FALSE;
+
+ parent = nma_eap_init (sizeof (NMAEapPeap),
+ validate,
+ add_to_size_group,
+ fill_connection,
+ update_secrets,
+ destroy,
+ "/org/gnome/libnma/nma-eap-peap.ui",
+ "eap_peap_grid",
+ "eap_peap_anon_identity_entry",
+ FALSE);
+ if (!parent)
+ return NULL;
+
+ method = (NMAEapPeap *) parent;
+ method->password_flags_name = NM_SETTING_802_1X_PASSWORD;
+ method->ws_8021x = ws_8021x;
+ method->is_editor = is_editor;
+
+ if (connection)
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_grid"));
+ g_assert (widget);
+
+ method->ca_cert_chooser = nma_cert_chooser_new ("CA",
+ NMA_CERT_CHOOSER_FLAG_CERT
+ | (secrets_only ? NMA_CERT_CHOOSER_FLAG_PASSWORDS :
0));
+ gtk_grid_attach (GTK_GRID (widget), method->ca_cert_chooser, 0, 2, 2, 1);
+ gtk_widget_show (method->ca_cert_chooser);
+
+ g_signal_connect (method->ca_cert_chooser,
+ "cert-validate",
+ G_CALLBACK (nma_eap_ca_cert_validate_cb),
+ NULL);
+ g_signal_connect (method->ca_cert_chooser,
+ "changed",
+ G_CALLBACK (nma_ws_changed_cb),
+ ws_8021x);
+
+ nma_eap_setup_cert_chooser (NMA_CERT_CHOOSER (method->ca_cert_chooser), s_8021x,
+ nm_setting_802_1x_get_ca_cert_scheme,
+ nm_setting_802_1x_get_ca_cert_path,
+ nm_setting_802_1x_get_ca_cert_uri,
+ nm_setting_802_1x_get_ca_cert_password,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+
+ if (connection && nma_eap_ca_cert_ignore_get (parent, connection)) {
+ gchar *ca_cert;
+ NMSetting8021xCKScheme scheme;
+
+ ca_cert = nma_cert_chooser_get_cert (NMA_CERT_CHOOSER (method->ca_cert_chooser), &scheme);
+ if (ca_cert)
+ g_free (ca_cert);
+ else
+ ca_not_required = TRUE;
+ }
+
+ if (secrets_only)
+ ca_not_required = TRUE;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder,
"eap_peap_ca_cert_not_required_checkbox"));
+ g_assert (widget);
+ g_signal_connect (G_OBJECT (widget), "toggled",
+ (GCallback) ca_cert_not_required_toggled,
+ parent);
+ g_signal_connect (G_OBJECT (widget), "toggled",
+ (GCallback) nma_ws_changed_cb,
+ ws_8021x);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), ca_not_required);
+
+ widget = inner_auth_combo_init (method, connection, s_8021x, secrets_only);
+ inner_auth_combo_changed_cb (widget, (gpointer) method);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_version_combo"));
+ g_assert (widget);
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
+ if (s_8021x) {
+ const char *peapver;
+
+ peapver = nm_setting_802_1x_get_phase1_peapver (s_8021x);
+ if (peapver) {
+ /* Index 0 is "Automatic" */
+ if (!strcmp (peapver, "0"))
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 1);
+ else if (!strcmp (peapver, "1"))
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 2);
+ }
+ }
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) nma_ws_changed_cb,
+ ws_8021x);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_anon_identity_entry"));
+ if (s_8021x && nm_setting_802_1x_get_anonymous_identity (s_8021x))
+ gtk_editable_set_text (GTK_EDITABLE (widget), nm_setting_802_1x_get_anonymous_identity
(s_8021x));
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) nma_ws_changed_cb,
+ ws_8021x);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_domain_entry"));
+ if (s_8021x && nm_setting_802_1x_get_domain_suffix_match (s_8021x))
+ gtk_editable_set_text (GTK_EDITABLE (widget), nm_setting_802_1x_get_domain_suffix_match
(s_8021x));
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) nma_ws_changed_cb,
+ ws_8021x);
+
+ if (secrets_only) {
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder,
"eap_peap_anon_identity_label"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder,
"eap_peap_anon_identity_entry"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_domain_label"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_domain_entry"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder,
"eap_peap_ca_cert_not_required_checkbox"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_inner_auth_label"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_inner_auth_combo"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_version_label"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_peap_version_combo"));
+ gtk_widget_hide (widget);
+ }
+
+ return method;
+}
diff --git a/src/nma-ws/nma-eap-peap.h b/src/nma-ws/nma-eap-peap.h
new file mode 100644
index 00000000..9f6c4a1e
--- /dev/null
+++ b/src/nma-ws/nma-eap-peap.h
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Dan Williams <dcbw redhat com>
+ *
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+
+#ifndef NMA_EAP_PEAP_H
+#define NMA_EAP_PEAP_H
+
+#include "nma-ws.h"
+
+typedef struct _NMAEapPeap NMAEapPeap;
+
+NMAEapPeap *nma_eap_peap_new (NMAWs8021x *ws_8021x,
+ NMConnection *connection,
+ gboolean is_editor,
+ gboolean secrets_only);
+
+#endif /* NMA_EAP_PEAP_H */
diff --git a/src/nma-ws/nma-eap-peap.ui b/src/nma-ws/nma-eap-peap.ui
new file mode 100644
index 00000000..0bd417f7
--- /dev/null
+++ b/src/nma-ws/nma-eap-peap.ui
@@ -0,0 +1,195 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="nm-applet">
+ <requires lib="gtk+" version="3.10"/>
+ <object class="GtkListStore" id="model8">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0"> </col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="model9">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">Automatic</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Version 0</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Version 1</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkGrid" id="eap_peap_grid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="eap_peap_anon_identity_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Anony_mous identity</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_peap_anon_identity_entry</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="eap_peap_anon_identity_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="eap_peap_ca_cert_not_required_checkbox">
+ <property name="label" translatable="yes">No CA certificate is _required</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eap_peap_version_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">PEAP _version</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_peap_version_combo</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="eap_peap_version_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="model">model9</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer9"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eap_peap_inner_auth_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Inner authentication</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_peap_inner_auth_combo</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="eap_peap_inner_auth_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="model">model8</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer8"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="eap_peap_inner_auth_vbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">6</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eap_peap_domain_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Suffix of the server certificate name.</property>
+ <property name="label" translatable="yes">_Domain</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_peap_domain_entry</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="eap_peap_domain_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+</interface>
diff --git a/src/nma-ws/nma-eap-simple.c b/src/nma-ws/nma-eap-simple.c
new file mode 100644
index 00000000..a26f6bda
--- /dev/null
+++ b/src/nma-ws/nma-eap-simple.c
@@ -0,0 +1,485 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Dan Williams <dcbw redhat com>
+ *
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+#include "nma-private.h"
+
+#include <ctype.h>
+#include <string.h>
+
+#include "nma-eap.h"
+#include "nma-ws.h"
+#include "nma-ws-private.h"
+#include "nma-ws-helpers.h"
+#include "nma-ws-802-1x.h"
+#include "nma-ws-802-1x-private.h"
+#include "nma-ui-utils.h"
+#include "utils.h"
+
+struct _NMAEapSimple {
+ NMAEap parent;
+
+ NMAWs8021x *ws_8021x;
+
+ const char *password_flags_name;
+ NMAEapSimpleType type;
+ NMAEapSimpleFlags flags;
+
+ gboolean username_requested;
+ gboolean password_requested;
+ gboolean pkey_passphrase_requested;
+ GtkEntry *username_entry;
+ GtkEntry *password_entry;
+ GtkToggleButton *show_password;
+ GtkEntry *pkey_passphrase_entry;
+ GtkToggleButton *show_pkey_passphrase;
+ guint idle_func_id;
+};
+
+static void
+show_password_toggled_cb (GtkToggleButton *button, NMAEapSimple *method)
+{
+ gboolean visible;
+
+ visible = gtk_toggle_button_get_active (button);
+ gtk_entry_set_visibility (method->password_entry, visible);
+}
+
+static void
+show_pkey_passphrase_toggled_cb (GtkToggleButton *button, NMAEapSimple *method)
+{
+ gboolean visible;
+
+ visible = gtk_toggle_button_get_active (button);
+ gtk_entry_set_visibility (method->pkey_passphrase_entry, visible);
+}
+
+static gboolean
+always_ask_selected (GtkEntry *passwd_entry)
+{
+ return !!( nma_utils_menu_to_secret_flags (GTK_WIDGET (passwd_entry))
+ & NM_SETTING_SECRET_FLAG_NOT_SAVED);
+}
+
+static gboolean
+validate (NMAEap *parent, GError **error)
+{
+ NMAEapSimple *method = (NMAEapSimple *)parent;
+ const char *text;
+ gboolean ret = TRUE;
+
+ if (method->username_requested) {
+ text = gtk_editable_get_text (GTK_EDITABLE (method->username_entry));
+ if (!text || !strlen (text)) {
+ widget_set_error (GTK_WIDGET (method->username_entry));
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("missing EAP username"));
+ ret = FALSE;
+ } else
+ widget_unset_error (GTK_WIDGET (method->username_entry));
+ }
+
+ /* Check if the password should always be requested */
+ if (method->password_requested) {
+ if (always_ask_selected (method->password_entry))
+ widget_unset_error (GTK_WIDGET (method->password_entry));
+ else {
+ text = gtk_editable_get_text (GTK_EDITABLE (method->password_entry));
+ if (!text || !strlen (text)) {
+ widget_set_error (GTK_WIDGET (method->password_entry));
+ if (ret) {
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC,
+ _("missing EAP password"));
+ ret = FALSE;
+ }
+ } else
+ widget_unset_error (GTK_WIDGET (method->password_entry));
+ }
+ }
+
+ if (method->pkey_passphrase_requested) {
+ text = gtk_editable_get_text (GTK_EDITABLE (method->pkey_passphrase_entry));
+ if (!text || !strlen (text)) {
+ widget_set_error (GTK_WIDGET (method->pkey_passphrase_entry));
+ if (ret) {
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC,
+ _("missing EAP client Private Key passphrase"));
+ ret = FALSE;
+ }
+ } else
+ widget_unset_error (GTK_WIDGET (method->pkey_passphrase_entry));
+ }
+
+ return ret;
+}
+
+static void
+add_to_size_group (NMAEap *parent, GtkSizeGroup *group)
+{
+ NMAEapSimple *method = (NMAEapSimple *) parent;
+ GtkWidget *widget;
+
+ if (method->username_requested) {
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_simple_username_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+ }
+
+ if (method->password_requested) {
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_simple_password_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+ }
+
+ if (method->pkey_passphrase_requested) {
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder,
"eap_simple_pkey_passphrase_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+ }
+}
+
+typedef struct {
+ const char *name;
+ gboolean autheap_allowed;
+} EapType;
+
+/* Indexed by NMA_EAP_SIMPLE_TYPE_* */
+static const EapType eap_table[NMA_EAP_SIMPLE_TYPE_LAST] = {
+ [NMA_EAP_SIMPLE_TYPE_PAP] = { "pap", FALSE },
+ [NMA_EAP_SIMPLE_TYPE_MSCHAP] = { "mschap", FALSE },
+ [NMA_EAP_SIMPLE_TYPE_MSCHAP_V2] = { "mschapv2", TRUE },
+ [NMA_EAP_SIMPLE_TYPE_PLAIN_MSCHAP_V2] = { "mschapv2", FALSE },
+ [NMA_EAP_SIMPLE_TYPE_MD5] = { "md5", TRUE },
+ [NMA_EAP_SIMPLE_TYPE_PWD] = { "pwd", TRUE },
+ [NMA_EAP_SIMPLE_TYPE_CHAP] = { "chap", FALSE },
+ [NMA_EAP_SIMPLE_TYPE_GTC] = { "gtc", TRUE },
+ [NMA_EAP_SIMPLE_TYPE_UNKNOWN] = { "unknown", TRUE },
+};
+
+static void
+fill_connection (NMAEap *parent, NMConnection *connection)
+{
+ NMAEapSimple *method = (NMAEapSimple *) parent;
+ NMSetting8021x *s_8021x;
+ gboolean not_saved = FALSE;
+ NMSettingSecretFlags flags;
+ const EapType *eap_type;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ g_assert (s_8021x);
+
+ if (!(method->flags & NMA_EAP_SIMPLE_FLAG_SECRETS_ONLY)) {
+ /* If this is the main EAP method, clear any existing methods because the
+ * user-selected one will replace it.
+ */
+ if (parent->phase2 == FALSE)
+ nm_setting_802_1x_clear_eap_methods (s_8021x);
+
+ eap_type = &eap_table[method->type];
+ if (parent->phase2) {
+ /* If the outer EAP method (TLS, TTLS, PEAP, etc) allows inner/phase2
+ * EAP methods (which only TTLS allows) *and* the inner/phase2 method
+ * supports being an inner EAP method, then set PHASE2_AUTHEAP.
+ * Otherwise the inner/phase2 method goes into PHASE2_AUTH.
+ */
+ if ((method->flags & NMA_EAP_SIMPLE_FLAG_AUTHEAP_ALLOWED) &&
eap_type->autheap_allowed) {
+ g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTHEAP, eap_type->name,
NULL);
+ g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, NULL, NULL);
+ } else {
+ g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, eap_type->name, NULL);
+ g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTHEAP, NULL, NULL);
+ }
+ } else
+ nm_setting_802_1x_add_eap_method (s_8021x, eap_type->name);
+ }
+
+ if (method->username_requested) {
+ g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY,
+ gtk_editable_get_text (GTK_EDITABLE (method->username_entry)),
+ NULL);
+ }
+
+ if (method->password_requested) {
+ /* Save the password always ask setting */
+ not_saved = always_ask_selected (method->password_entry);
+ flags = nma_utils_menu_to_secret_flags (GTK_WIDGET (method->password_entry));
+ nm_setting_set_secret_flags (NM_SETTING (s_8021x), method->password_flags_name, flags, NULL);
+
+ /* Fill the connection's password if we're in the applet so that it'll get
+ * back to NM. From the editor though, since the connection isn't going
+ * back to NM in response to a GetSecrets() call, we don't save it if the
+ * user checked "Always Ask".
+ */
+ if (!(method->flags & NMA_EAP_SIMPLE_FLAG_IS_EDITOR) || not_saved == FALSE) {
+ g_object_set (s_8021x, NM_SETTING_802_1X_PASSWORD,
+ gtk_editable_get_text (GTK_EDITABLE (method->password_entry)),
+ NULL);
+ }
+
+ /* Update secret flags and popup when editing the connection */
+ if (!(method->flags & NMA_EAP_SIMPLE_FLAG_SECRETS_ONLY)) {
+ GtkWidget *passwd_entry = GTK_WIDGET (gtk_builder_get_object (parent->builder,
+
"eap_simple_password_entry"));
+ g_assert (passwd_entry);
+
+ nma_utils_update_password_storage (passwd_entry, flags,
+ NM_SETTING (s_8021x), method->password_flags_name);
+ }
+ }
+
+ if (method->pkey_passphrase_requested) {
+ g_object_set (s_8021x, NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD,
+ gtk_editable_get_text (GTK_EDITABLE (method->pkey_passphrase_entry)),
+ NULL);
+ }
+}
+
+static void
+update_secrets (NMAEap *parent, NMConnection *connection)
+{
+ nma_ws_helper_fill_secret_entry (connection,
+ GTK_EDITABLE (gtk_builder_get_object (parent->builder,
"eap_simple_password_entry")),
+ NM_TYPE_SETTING_802_1X,
+ (HelperSecretFunc) nm_setting_802_1x_get_password);
+ nma_ws_helper_fill_secret_entry (connection,
+ GTK_EDITABLE (gtk_builder_get_object (parent->builder,
"eap_simple_pkey_passphrase_entry")),
+ NM_TYPE_SETTING_802_1X,
+ (HelperSecretFunc) nm_setting_802_1x_get_private_key_password);
+}
+
+static gboolean
+stuff_changed (NMAEapSimple *method)
+{
+ nma_ws_changed_cb (NULL, method->ws_8021x);
+ method->idle_func_id = 0;
+ return FALSE;
+}
+
+static void
+password_storage_changed (GObject *entry,
+ GParamSpec *pspec,
+ NMAEapSimple *method)
+{
+ gboolean always_ask;
+ gboolean secrets_only = method->flags & NMA_EAP_SIMPLE_FLAG_SECRETS_ONLY;
+
+ always_ask = always_ask_selected (method->password_entry);
+
+ if (always_ask && !secrets_only) {
+ /* we always clear this button and do not restore it
+ * (because we want to hide the password). */
+ gtk_toggle_button_set_active (method->show_password, FALSE);
+ }
+
+ gtk_widget_set_sensitive (GTK_WIDGET (method->show_password),
+ !always_ask || secrets_only);
+
+ if (!method->idle_func_id)
+ method->idle_func_id = g_idle_add ((GSourceFunc) stuff_changed, method);
+}
+
+/* Set the UI fields for user, password, always_ask and show_password to the
+ * values as provided by method->ws_8021x. */
+static void
+set_userpass_ui (NMAEapSimple *method)
+{
+ if (method->ws_8021x->username) {
+ gtk_editable_set_text (GTK_EDITABLE (method->username_entry),
+ method->ws_8021x->username);
+ } else {
+ gtk_editable_set_text (GTK_EDITABLE (method->username_entry), "");
+ }
+
+ if (method->ws_8021x->password && !method->ws_8021x->always_ask) {
+ gtk_editable_set_text (GTK_EDITABLE (method->password_entry),
+ method->ws_8021x->password);
+ } else {
+ gtk_editable_set_text (GTK_EDITABLE (method->password_entry), "");
+ }
+
+ gtk_toggle_button_set_active (method->show_password, method->ws_8021x->show_password);
+
+ password_storage_changed (NULL, NULL, method);
+}
+
+static void
+widgets_realized (GtkWidget *widget, NMAEapSimple *method)
+{
+ set_userpass_ui (method);
+}
+
+static void
+widgets_unrealized (GtkWidget *widget, NMAEapSimple *method)
+{
+ nma_ws_802_1x_set_userpass (method->ws_8021x,
+ gtk_editable_get_text (GTK_EDITABLE (method->username_entry)),
+ gtk_editable_get_text (GTK_EDITABLE (method->password_entry)),
+ always_ask_selected (method->password_entry),
+ gtk_toggle_button_get_active (method->show_password));
+}
+
+static void
+destroy (NMAEap *parent)
+{
+ NMAEapSimple *method = (NMAEapSimple *) parent;
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_simple_grid"));
+ g_assert (widget);
+ g_signal_handlers_disconnect_by_data (widget, method);
+
+ g_signal_handlers_disconnect_by_data (method->username_entry, method->ws_8021x);
+ g_signal_handlers_disconnect_by_data (method->password_entry, method->ws_8021x);
+ g_signal_handlers_disconnect_by_data (method->password_entry, method);
+ g_signal_handlers_disconnect_by_data (method->show_password, method);
+ g_signal_handlers_disconnect_by_data (method->pkey_passphrase_entry, method->ws_8021x);
+ g_signal_handlers_disconnect_by_data (method->show_pkey_passphrase, method);
+
+ nm_clear_g_source (&method->idle_func_id);
+}
+
+static void
+hide_row (GtkWidget **widgets, size_t num)
+{
+ while (num--)
+ gtk_widget_hide (*widgets++);
+}
+
+NMAEapSimple *
+nma_eap_simple_new (NMAWs8021x *ws_8021x,
+ NMConnection *connection,
+ NMAEapSimpleType type,
+ NMAEapSimpleFlags flags,
+ const char *const*hints)
+{
+ NMAEap *parent;
+ NMAEapSimple *method;
+ GtkWidget *widget;
+ NMSetting8021x *s_8021x = NULL;
+ GtkWidget *widget_row[10];
+
+ parent = nma_eap_init (sizeof (NMAEapSimple),
+ validate,
+ add_to_size_group,
+ fill_connection,
+ update_secrets,
+ destroy,
+ "/org/gnome/libnma/nma-eap-simple.ui",
+ "eap_simple_grid",
+ "eap_simple_username_entry",
+ flags & NMA_EAP_SIMPLE_FLAG_PHASE2);
+ if (!parent)
+ return NULL;
+
+ method = (NMAEapSimple *) parent;
+ method->password_flags_name = NM_SETTING_802_1X_PASSWORD;
+ method->ws_8021x = ws_8021x;
+ method->flags = flags;
+ method->type = type;
+ g_assert (type < NMA_EAP_SIMPLE_TYPE_LAST);
+ g_assert ( type != NMA_EAP_SIMPLE_TYPE_UNKNOWN
+ || hints);
+
+ if (hints) {
+ for (; *hints; hints++) {
+ if (!strcmp (*hints, NM_SETTING_802_1X_IDENTITY))
+ method->username_requested = TRUE;
+ else if (!strcmp (*hints, NM_SETTING_802_1X_PASSWORD)) {
+ method->password_requested = TRUE;
+ method->password_flags_name = NM_SETTING_802_1X_PASSWORD;
+ } else if (!strcmp (*hints, NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD))
+ method->pkey_passphrase_requested = TRUE;
+ }
+ } else {
+ method->username_requested = TRUE;
+ method->password_requested = TRUE;
+ }
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_simple_grid"));
+ g_assert (widget);
+ g_signal_connect (G_OBJECT (widget), "realize",
+ (GCallback) widgets_realized,
+ method);
+ g_signal_connect (G_OBJECT (widget), "unrealize",
+ (GCallback) widgets_unrealized,
+ method);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_simple_username_entry"));
+ g_assert (widget);
+ method->username_entry = GTK_ENTRY (widget);
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) nma_ws_changed_cb,
+ ws_8021x);
+
+ if ( (method->flags & NMA_EAP_SIMPLE_FLAG_SECRETS_ONLY)
+ && !method->username_requested)
+ gtk_widget_set_sensitive (widget, FALSE);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_simple_password_entry"));
+ g_assert (widget);
+ method->password_entry = GTK_ENTRY (widget);
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) nma_ws_changed_cb,
+ ws_8021x);
+
+ /* Create password-storage popup menu for password entry under entry's secondary icon */
+ if (connection)
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ nma_utils_setup_password_storage (widget, 0, (NMSetting *) s_8021x, method->password_flags_name,
+ FALSE, flags & NMA_EAP_SIMPLE_FLAG_SECRETS_ONLY);
+
+ g_signal_connect (method->password_entry, "notify::secondary-icon-name",
+ G_CALLBACK (password_storage_changed),
+ method);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "show_checkbutton_eapsimple"));
+ g_assert (widget);
+ method->show_password = GTK_TOGGLE_BUTTON (widget);
+ g_signal_connect (G_OBJECT (widget), "toggled",
+ (GCallback) show_password_toggled_cb,
+ method);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_simple_pkey_passphrase_entry"));
+ g_assert (widget);
+ method->pkey_passphrase_entry = GTK_ENTRY (widget);
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) nma_ws_changed_cb,
+ ws_8021x);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder,
"eap_simple_show_pkey_passphrase_checkbutton"));
+ g_assert (widget);
+ method->show_pkey_passphrase = GTK_TOGGLE_BUTTON (widget);
+ g_signal_connect (G_OBJECT (widget), "toggled",
+ (GCallback) show_pkey_passphrase_toggled_cb,
+ method);
+
+ widget_row[0] = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_simple_username_label"));
+ widget_row[1] = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_simple_username_entry"));
+ if (!method->username_requested)
+ hide_row (widget_row, 2);
+
+ widget_row[0] = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_simple_password_label"));
+ widget_row[1] = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_simple_password_entry"));
+ widget_row[2] = GTK_WIDGET (gtk_builder_get_object (parent->builder, "show_checkbutton_eapsimple"));
+ if (!method->password_requested)
+ hide_row (widget_row, 3);
+
+ widget_row[0] = GTK_WIDGET (gtk_builder_get_object (parent->builder,
"eap_simple_pkey_passphrase_label"));
+ widget_row[1] = GTK_WIDGET (gtk_builder_get_object (parent->builder,
"eap_simple_pkey_passphrase_entry"));
+ widget_row[2] = GTK_WIDGET (gtk_builder_get_object (parent->builder,
"eap_simple_show_pkey_passphrase_checkbutton"));
+ if (!method->pkey_passphrase_requested)
+ hide_row (widget_row, 3);
+
+ /* Initialize the UI fields with the security settings from method->ws_8021x.
+ * This will be done again when the widget gets realized. It must be done here as well,
+ * because the outer dialog will ask to 'validate' the connection before the security tab
+ * is shown/realized (to enable the 'Apply' button).
+ * As 'validate' accesses the contents of the UI fields, they must be initialized now, even
+ * if the widgets are not yet visible. */
+ set_userpass_ui (method);
+
+ return method;
+}
diff --git a/src/nma-ws/nma-eap-simple.h b/src/nma-ws/nma-eap-simple.h
new file mode 100644
index 00000000..82024dca
--- /dev/null
+++ b/src/nma-ws/nma-eap-simple.h
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Dan Williams <dcbw redhat com>
+ *
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+
+#ifndef NMA_EAP_SIMPLE_H
+#define NMA_EAP_SIMPLE_H
+
+#include "nma-ws.h"
+
+typedef enum {
+ /* NOTE: when updating this table, also update nma_eap_methods[] */
+ NMA_EAP_SIMPLE_TYPE_PAP = 0,
+ NMA_EAP_SIMPLE_TYPE_MSCHAP,
+ NMA_EAP_SIMPLE_TYPE_MSCHAP_V2,
+ NMA_EAP_SIMPLE_TYPE_PLAIN_MSCHAP_V2,
+ NMA_EAP_SIMPLE_TYPE_MD5,
+ NMA_EAP_SIMPLE_TYPE_PWD,
+ NMA_EAP_SIMPLE_TYPE_CHAP,
+ NMA_EAP_SIMPLE_TYPE_GTC,
+ NMA_EAP_SIMPLE_TYPE_UNKNOWN,
+
+ /* Boundary value, do not use */
+ NMA_EAP_SIMPLE_TYPE_LAST
+} NMAEapSimpleType;
+
+typedef enum {
+ NMA_EAP_SIMPLE_FLAG_NONE = 0x00,
+ /* Indicates the EAP method is an inner/phase2 method */
+ NMA_EAP_SIMPLE_FLAG_PHASE2 = 0x01,
+ /* Set by TTLS to indicate that inner/phase2 EAP is allowed */
+ NMA_EAP_SIMPLE_FLAG_AUTHEAP_ALLOWED = 0x02,
+ /* Set from nm-connection-editor or the GNOME network panel */
+ NMA_EAP_SIMPLE_FLAG_IS_EDITOR = 0x04,
+ /* Set to indicate that this request is only for secrets */
+ NMA_EAP_SIMPLE_FLAG_SECRETS_ONLY = 0x08
+} NMAEapSimpleFlags;
+
+typedef struct _NMAEapSimple NMAEapSimple;
+
+NMAEapSimple *nma_eap_simple_new (NMAWs8021x *ws_8021x,
+ NMConnection *connection,
+ NMAEapSimpleType type,
+ NMAEapSimpleFlags flags,
+ const char *const*hints);
+
+#endif /* NMA_EAP_SIMPLE_H */
diff --git a/src/nma-ws/nma-eap-simple.ui b/src/nma-ws/nma-eap-simple.ui
new file mode 100644
index 00000000..cdbf65e9
--- /dev/null
+++ b/src/nma-ws/nma-eap-simple.ui
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="nm-applet">
+ <requires lib="gtk+" version="3.10"/>
+ <object class="GtkGrid" id="eap_simple_grid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">start</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="eap_simple_username_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Username</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_simple_username_entry</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eap_simple_password_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Password</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_simple_password_entry</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="eap_simple_password_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="visibility">False</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="eap_simple_username_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="vbox5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkCheckButton" id="show_checkbutton_eapsimple">
+ <property name="label" translatable="yes">Sho_w password</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eap_simple_pkey_passphrase_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">P_rivate Key Passphrase</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_simple_pkey_passphrase_entry</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="eap_simple_pkey_passphrase_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="visibility">False</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="eap_simple_show_pkey_passphrase_checkbutton">
+ <property name="label" translatable="yes">Sh_ow passphrase</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+</interface>
diff --git a/src/nma-ws/nma-eap-tls.c b/src/nma-ws/nma-eap-tls.c
new file mode 100644
index 00000000..5f671fab
--- /dev/null
+++ b/src/nma-ws/nma-eap-tls.c
@@ -0,0 +1,497 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Dan Williams <dcbw redhat com>
+ * Lubomir Rintel <lkundrak v3 sk>
+ *
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+#include "nma-private.h"
+
+#include <ctype.h>
+#include <string.h>
+
+#include "nma-eap.h"
+#include "nma-ws.h"
+#include "nma-ws-private.h"
+#include "nma-ui-utils.h"
+#include "nma-cert-chooser.h"
+#include "utils.h"
+
+struct _NMAEapTls {
+ NMAEap parent;
+
+ const char *ca_cert_password_flags_name;
+ const char *client_cert_password_flags_name;
+ const char *client_key_password_flags_name;
+
+ gboolean editing_connection;
+ GtkWidget *ca_cert_chooser;
+ GtkWidget *client_cert_chooser;
+};
+
+
+static gboolean
+validate (NMAEap *parent, GError **error)
+{
+ NMAEapTls *method = (NMAEapTls *) parent;
+ GtkWidget *widget;
+ const char *identity;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_identity_entry"));
+ g_assert (widget);
+ identity = gtk_editable_get_text (GTK_EDITABLE (widget));
+ if (!identity || !strlen (identity)) {
+ widget_set_error (widget);
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("missing EAP-TLS identity"));
+ return FALSE;
+ } else {
+ widget_unset_error (widget);
+ }
+
+ if ( gtk_widget_get_sensitive (method->ca_cert_chooser)
+ && !nma_cert_chooser_validate (NMA_CERT_CHOOSER (method->ca_cert_chooser), error))
+ return FALSE;
+
+ if (!nma_cert_chooser_validate (NMA_CERT_CHOOSER (method->client_cert_chooser), error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+ca_cert_not_required_toggled (GtkWidget *button, gpointer user_data)
+{
+ NMAEapTls *method = (NMAEapTls *) user_data;
+
+ gtk_widget_set_sensitive (method->ca_cert_chooser,
+ !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)));
+}
+
+static void
+add_to_size_group (NMAEap *parent, GtkSizeGroup *group)
+{
+ NMAEapTls *method = (NMAEapTls *) parent;
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_identity_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_domain_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ nma_cert_chooser_add_to_size_group (NMA_CERT_CHOOSER (method->client_cert_chooser), group);
+ nma_cert_chooser_add_to_size_group (NMA_CERT_CHOOSER (method->ca_cert_chooser), group);
+}
+
+static void
+fill_connection (NMAEap *parent, NMConnection *connection)
+{
+ NMAEapTls *method = (NMAEapTls *) parent;
+ NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ NMSetting8021x *s_8021x;
+ NMSettingSecretFlags secret_flags;
+ GtkWidget *widget;
+ char *value = NULL;
+ const char *password = NULL;
+ GError *error = NULL;
+ gboolean ca_cert_error = FALSE;
+ NMSetting8021xCKScheme scheme;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ g_assert (s_8021x);
+
+ if (parent->phase2)
+ g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, "tls", NULL);
+ else
+ nm_setting_802_1x_add_eap_method (s_8021x, "tls");
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_identity_entry"));
+ g_assert (widget);
+ g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, gtk_editable_get_text (GTK_EDITABLE (widget)),
NULL);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_domain_entry"));
+ g_assert (widget);
+ g_object_set (s_8021x,
+ parent->phase2 ? NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH :
NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH,
+ gtk_editable_get_text (GTK_EDITABLE (widget)), NULL);
+
+ /* TLS private key */
+ password = nma_cert_chooser_get_key_password (NMA_CERT_CHOOSER (method->client_cert_chooser));
+ value = nma_cert_chooser_get_key (NMA_CERT_CHOOSER (method->client_cert_chooser), &scheme);
+
+ if (parent->phase2) {
+ if (!nm_setting_802_1x_set_phase2_private_key (s_8021x, value, password, scheme, &format,
&error)) {
+ g_warning ("Couldn't read phase2 private key '%s': %s", value, error ? error->message
: "(unknown)");
+ g_clear_error (&error);
+ }
+ } else {
+ if (!nm_setting_802_1x_set_private_key (s_8021x, value, password, scheme, &format, &error)) {
+ g_warning ("Couldn't read private key '%s': %s", value, error ? error->message :
"(unknown)");
+ g_clear_error (&error);
+ }
+ }
+ g_free (value);
+
+ /* Save CA certificate PIN and its flags to the connection */
+ secret_flags = nma_cert_chooser_get_cert_password_flags (NMA_CERT_CHOOSER (method->ca_cert_chooser));
+ nm_setting_set_secret_flags (NM_SETTING (s_8021x), method->ca_cert_password_flags_name,
+ secret_flags, NULL);
+ if (method->editing_connection) {
+ /* Update secret flags and popup when editing the connection */
+ nma_cert_chooser_update_cert_password_storage (NMA_CERT_CHOOSER (method->ca_cert_chooser),
+ secret_flags, NM_SETTING (s_8021x),
+ method->ca_cert_password_flags_name);
+ g_object_set (s_8021x, method->ca_cert_password_flags_name,
+ nma_cert_chooser_get_cert_password (NMA_CERT_CHOOSER (method->ca_cert_chooser)),
+ NULL);
+ }
+
+ /* Save user certificate PIN and its flags flags to the connection */
+ secret_flags = nma_cert_chooser_get_cert_password_flags (NMA_CERT_CHOOSER
(method->client_cert_chooser));
+ nm_setting_set_secret_flags (NM_SETTING (s_8021x), method->client_cert_password_flags_name,
+ secret_flags, NULL);
+ if (method->editing_connection) {
+ nma_cert_chooser_update_cert_password_storage (NMA_CERT_CHOOSER (method->client_cert_chooser),
+ secret_flags, NM_SETTING (s_8021x),
+ method->client_cert_password_flags_name);
+ g_object_set (s_8021x, method->client_cert_password_flags_name,
+ nma_cert_chooser_get_cert_password (NMA_CERT_CHOOSER
(method->client_cert_chooser)),
+ NULL);
+ }
+
+ /* Save user private key password flags to the connection */
+ secret_flags = nma_cert_chooser_get_key_password_flags (NMA_CERT_CHOOSER
(method->client_cert_chooser));
+ nm_setting_set_secret_flags (NM_SETTING (s_8021x), method->client_key_password_flags_name,
+ secret_flags, NULL);
+ if (method->editing_connection) {
+ nma_cert_chooser_update_key_password_storage (NMA_CERT_CHOOSER (method->client_cert_chooser),
+ secret_flags, NM_SETTING (s_8021x),
+ method->client_key_password_flags_name);
+ }
+
+ /* TLS client certificate */
+ if (format != NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
+ /* If the key is pkcs#12 nm_setting_802_1x_set_private_key() already
+ * set the client certificate for us.
+ */
+ value = nma_cert_chooser_get_cert (NMA_CERT_CHOOSER (method->client_cert_chooser), &scheme);
+ format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ if (parent->phase2) {
+ if (!nm_setting_802_1x_set_phase2_client_cert (s_8021x, value, scheme, &format,
&error)) {
+ g_warning ("Couldn't read phase2 client certificate '%s': %s", value, error ?
error->message : "(unknown)");
+ g_clear_error (&error);
+ }
+ } else {
+ if (!nm_setting_802_1x_set_client_cert (s_8021x, value, scheme, &format, &error)) {
+ g_warning ("Couldn't read client certificate '%s': %s", value, error ?
error->message : "(unknown)");
+ g_clear_error (&error);
+ }
+ }
+ g_free (value);
+ }
+
+ /* TLS CA certificate */
+ if (gtk_widget_get_sensitive (method->ca_cert_chooser))
+ value = nma_cert_chooser_get_cert (NMA_CERT_CHOOSER (method->ca_cert_chooser), &scheme);
+ else
+ value = NULL;
+ format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ if (parent->phase2) {
+ if (!nm_setting_802_1x_set_phase2_ca_cert (s_8021x, value, scheme, &format, &error)) {
+ g_warning ("Couldn't read phase2 CA certificate '%s': %s", value, error ?
error->message : "(unknown)");
+ g_clear_error (&error);
+ ca_cert_error = TRUE;
+ }
+ } else {
+ if (!nm_setting_802_1x_set_ca_cert (s_8021x, value, scheme, &format, &error)) {
+ g_warning ("Couldn't read CA certificate '%s': %s", value, error ? error->message :
"(unknown)");
+ g_clear_error (&error);
+ ca_cert_error = TRUE;
+ }
+ }
+ nma_eap_ca_cert_ignore_set (parent, connection, value, ca_cert_error);
+ g_free (value);
+}
+
+static GError *
+client_cert_validate_cb (NMACertChooser *cert_chooser, gpointer user_data)
+{
+ NMSetting8021xCKScheme scheme;
+ NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ gs_unref_object NMSetting8021x *setting = NULL;
+ gs_free char *value = NULL;
+ GError *local = NULL;
+
+ setting = (NMSetting8021x *) nm_setting_802_1x_new ();
+
+ value = nma_cert_chooser_get_cert (cert_chooser, &scheme);
+ if (!value) {
+ return g_error_new_literal (NMA_ERROR, NMA_ERROR_GENERIC,
+ _("no user certificate selected"));
+ }
+ if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) {
+ if (!g_file_test (value, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
+ return g_error_new_literal (NMA_ERROR, NMA_ERROR_GENERIC,
+ _("selected user certificate file does not exist"));
+ }
+ }
+
+ if (!nm_setting_802_1x_set_client_cert (setting, value, scheme, &format, &local))
+ return local;
+
+ return NULL;
+}
+
+static GError *
+client_key_validate_cb (NMACertChooser *cert_chooser, gpointer user_data)
+{
+ NMSetting8021xCKScheme scheme;
+ gs_free char *value = NULL;
+
+
+ value = nma_cert_chooser_get_key (cert_chooser, &scheme);
+ if (!value) {
+ return g_error_new_literal (NMA_ERROR, NMA_ERROR_GENERIC,
+ _("no key selected"));
+ }
+ if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) {
+ if (!g_file_test (value, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
+ return g_error_new_literal (NMA_ERROR, NMA_ERROR_GENERIC,
+ _("selected key file does not exist"));
+ }
+ }
+
+ return NULL;
+}
+
+static GError *
+client_key_password_validate_cb (NMACertChooser *cert_chooser, gpointer user_data)
+{
+ NMSetting8021xCKScheme scheme;
+ NMSettingSecretFlags secret_flags;
+ gs_unref_object NMSetting8021x *setting = NULL;
+ gs_free char *value = NULL;
+ const char *password = NULL;
+ GError *local = NULL;
+
+ secret_flags = nma_cert_chooser_get_key_password_flags (cert_chooser);
+ if ( secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED
+ || secret_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)
+ return NULL;
+
+ setting = (NMSetting8021x *) nm_setting_802_1x_new ();
+
+ value = nma_cert_chooser_get_key (cert_chooser, &scheme);
+ password = nma_cert_chooser_get_key_password (cert_chooser);
+ if (!nm_setting_802_1x_set_private_key (setting, value, password, scheme, NULL, &local))
+ return local;
+
+ return NULL;
+}
+
+static void
+client_cert_fixup_pkcs12 (NMACertChooser *cert_chooser, gpointer user_data)
+{
+ NMSetting8021xCKScheme cert_scheme, key_scheme;
+ NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ gs_free char *cert_value = NULL;
+ gs_free char *key_value = NULL;
+ gs_unref_object NMSetting8021x *setting = NULL;
+
+ setting = (NMSetting8021x *) nm_setting_802_1x_new ();
+
+ cert_value = nma_cert_chooser_get_cert (cert_chooser, &cert_scheme);
+ key_value = nma_cert_chooser_get_key (cert_chooser, &key_scheme);
+
+ if ( !cert_value || key_value
+ || !nm_setting_802_1x_set_client_cert (setting, cert_value, cert_scheme, &format, NULL))
+ return;
+
+ if (format == NM_SETTING_802_1X_CK_FORMAT_PKCS12)
+ nma_cert_chooser_set_key (cert_chooser, cert_value, cert_scheme);
+}
+
+static void
+update_secrets (NMAEap *parent, NMConnection *connection)
+{
+ NMAEapTls *method = (NMAEapTls *) parent;
+
+ nma_eap_setup_cert_chooser (NMA_CERT_CHOOSER (method->client_cert_chooser),
+ nm_connection_get_setting_802_1x (connection),
+ NULL,
+ NULL,
+ NULL,
+ parent->phase2 ? nm_setting_802_1x_get_phase2_client_cert_password :
nm_setting_802_1x_get_client_cert_password,
+ parent->phase2 ? nm_setting_802_1x_get_phase2_private_key_scheme :
nm_setting_802_1x_get_private_key_scheme,
+ parent->phase2 ? nm_setting_802_1x_get_phase2_private_key_path :
nm_setting_802_1x_get_private_key_path,
+ parent->phase2 ? nm_setting_802_1x_get_phase2_private_key_uri :
nm_setting_802_1x_get_private_key_uri,
+ parent->phase2 ? nm_setting_802_1x_get_phase2_private_key_password :
nm_setting_802_1x_get_private_key_password);
+}
+
+NMAEapTls *
+nma_eap_tls_new (NMAWs8021x *ws_8021x,
+ NMConnection *connection,
+ gboolean phase2,
+ gboolean secrets_only)
+{
+ NMAEapTls *method;
+ NMAEap *parent;
+ GtkWidget *widget;
+ NMSetting8021x *s_8021x = NULL;
+ gboolean ca_not_required = FALSE;
+
+ parent = nma_eap_init (sizeof (NMAEapTls),
+ validate,
+ add_to_size_group,
+ fill_connection,
+ update_secrets,
+ NULL,
+ "/org/gnome/libnma/nma-eap-tls.ui",
+ "eap_tls_grid",
+ "eap_tls_identity_entry",
+ phase2);
+ if (!parent)
+ return NULL;
+
+ method = (NMAEapTls *) parent;
+ method->ca_cert_password_flags_name = phase2
+ ? NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD
+ : NM_SETTING_802_1X_CA_CERT_PASSWORD;
+ method->client_cert_password_flags_name = phase2
+ ? NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD
+ : NM_SETTING_802_1X_CLIENT_CERT_PASSWORD;
+ method->client_key_password_flags_name = phase2
+ ? NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD
+ : NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD;
+ method->editing_connection = secrets_only ? FALSE : TRUE;
+
+ if (connection)
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder,
"eap_tls_ca_cert_not_required_checkbox"));
+ g_assert (widget);
+ g_signal_connect (G_OBJECT (widget), "toggled",
+ (GCallback) ca_cert_not_required_toggled,
+ parent);
+ g_signal_connect (G_OBJECT (widget), "toggled",
+ (GCallback) nma_ws_changed_cb,
+ ws_8021x);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_identity_entry"));
+ g_assert (widget);
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) nma_ws_changed_cb,
+ ws_8021x);
+ if (s_8021x && nm_setting_802_1x_get_identity (s_8021x))
+ gtk_editable_set_text (GTK_EDITABLE (widget), nm_setting_802_1x_get_identity (s_8021x));
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_domain_entry"));
+ g_assert (widget);
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) nma_ws_changed_cb,
+ ws_8021x);
+ if (phase2) {
+ if (s_8021x && nm_setting_802_1x_get_phase2_domain_suffix_match (s_8021x))
+ gtk_editable_set_text (GTK_EDITABLE (widget),
nm_setting_802_1x_get_phase2_domain_suffix_match (s_8021x));
+ } else {
+ if (s_8021x && nm_setting_802_1x_get_domain_suffix_match (s_8021x))
+ gtk_editable_set_text (GTK_EDITABLE (widget),
nm_setting_802_1x_get_domain_suffix_match (s_8021x));
+ }
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_grid"));
+ g_assert (widget);
+
+ method->ca_cert_chooser = nma_cert_chooser_new ("CA",
+ NMA_CERT_CHOOSER_FLAG_CERT
+ | (secrets_only ? NMA_CERT_CHOOSER_FLAG_PASSWORDS :
0));
+ gtk_grid_attach (GTK_GRID (widget), method->ca_cert_chooser, 0, 2, 2, 1);
+ gtk_widget_show (method->ca_cert_chooser);
+
+ g_signal_connect (method->ca_cert_chooser,
+ "cert-validate",
+ G_CALLBACK (nma_eap_ca_cert_validate_cb),
+ NULL);
+ g_signal_connect (method->ca_cert_chooser,
+ "changed",
+ G_CALLBACK (nma_ws_changed_cb),
+ ws_8021x);
+
+ nma_eap_setup_cert_chooser (NMA_CERT_CHOOSER (method->ca_cert_chooser), s_8021x,
+ phase2 ? nm_setting_802_1x_get_phase2_ca_cert_scheme :
nm_setting_802_1x_get_ca_cert_scheme,
+ phase2 ? nm_setting_802_1x_get_phase2_ca_cert_path :
nm_setting_802_1x_get_ca_cert_path,
+ phase2 ? nm_setting_802_1x_get_phase2_ca_cert_uri :
nm_setting_802_1x_get_ca_cert_uri,
+ phase2 ? nm_setting_802_1x_get_phase2_ca_cert_password :
nm_setting_802_1x_get_ca_cert_password,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+
+ if (connection && nma_eap_ca_cert_ignore_get (parent, connection)) {
+ gchar *ca_cert;
+ NMSetting8021xCKScheme scheme;
+
+ ca_cert = nma_cert_chooser_get_cert (NMA_CERT_CHOOSER (method->ca_cert_chooser), &scheme);
+ if (ca_cert)
+ g_free (ca_cert);
+ else
+ ca_not_required = TRUE;
+ }
+
+ if (secrets_only)
+ ca_not_required = TRUE;
+
+ method->client_cert_chooser = nma_cert_chooser_new ("User",
+ secrets_only ? NMA_CERT_CHOOSER_FLAG_PASSWORDS :
0);
+ gtk_grid_attach (GTK_GRID (widget), method->client_cert_chooser, 0, 4, 2, 1);
+ gtk_widget_show (method->client_cert_chooser);
+
+ g_signal_connect (method->client_cert_chooser, "cert-validate",
+ G_CALLBACK (client_cert_validate_cb),
+ NULL);
+ g_signal_connect (method->client_cert_chooser,
+ "key-validate",
+ G_CALLBACK (client_key_validate_cb),
+ NULL);
+ g_signal_connect (method->client_cert_chooser,
+ "key-password-validate",
+ G_CALLBACK (client_key_password_validate_cb),
+ NULL);
+ g_signal_connect (method->client_cert_chooser,
+ "changed",
+ G_CALLBACK (client_cert_fixup_pkcs12),
+ ws_8021x);
+ g_signal_connect (method->client_cert_chooser,
+ "changed",
+ G_CALLBACK (nma_ws_changed_cb),
+ ws_8021x);
+
+ nma_eap_setup_cert_chooser (NMA_CERT_CHOOSER (method->client_cert_chooser), s_8021x,
+ phase2 ? nm_setting_802_1x_get_phase2_client_cert_scheme :
nm_setting_802_1x_get_client_cert_scheme,
+ phase2 ? nm_setting_802_1x_get_phase2_client_cert_path :
nm_setting_802_1x_get_client_cert_path,
+ phase2 ? nm_setting_802_1x_get_phase2_client_cert_uri :
nm_setting_802_1x_get_client_cert_uri,
+ phase2 ? nm_setting_802_1x_get_phase2_client_cert_password :
nm_setting_802_1x_get_client_cert_password,
+ phase2 ? nm_setting_802_1x_get_phase2_private_key_scheme :
nm_setting_802_1x_get_private_key_scheme,
+ phase2 ? nm_setting_802_1x_get_phase2_private_key_path :
nm_setting_802_1x_get_private_key_path,
+ phase2 ? nm_setting_802_1x_get_phase2_private_key_uri :
nm_setting_802_1x_get_private_key_uri,
+ phase2 ? nm_setting_802_1x_get_phase2_private_key_password :
nm_setting_802_1x_get_private_key_password);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder,
"eap_tls_ca_cert_not_required_checkbox"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), ca_not_required);
+
+ /* Create password-storage popup menus for password entries under their secondary icon */
+ nma_cert_chooser_setup_cert_password_storage (NMA_CERT_CHOOSER (method->ca_cert_chooser),
+ 0, (NMSetting *) s_8021x,
method->ca_cert_password_flags_name,
+ FALSE, secrets_only);
+ nma_cert_chooser_setup_cert_password_storage (NMA_CERT_CHOOSER (method->client_cert_chooser),
+ 0, (NMSetting *) s_8021x,
method->client_cert_password_flags_name,
+ FALSE, secrets_only);
+ nma_cert_chooser_setup_key_password_storage (NMA_CERT_CHOOSER (method->client_cert_chooser),
+ 0, (NMSetting *) s_8021x,
method->client_key_password_flags_name,
+ FALSE, secrets_only);
+
+ return method;
+}
diff --git a/src/nma-ws/nma-eap-tls.h b/src/nma-ws/nma-eap-tls.h
new file mode 100644
index 00000000..5de30814
--- /dev/null
+++ b/src/nma-ws/nma-eap-tls.h
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Dan Williams <dcbw redhat com>
+ *
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+
+#ifndef NMA_EAP_TLS_H
+#define NMA_EAP_TLS_H
+
+#include "nma-ws-802-1x.h"
+
+typedef struct _NMAEapTls NMAEapTls;
+
+NMAEapTls *nma_eap_tls_new (NMAWs8021x *ws_8021x,
+ NMConnection *connection,
+ gboolean phase2,
+ gboolean secrets_only);
+
+#endif /* NMA_EAP_TLS_H */
diff --git a/src/nma-ws/nma-eap-tls.ui b/src/nma-ws/nma-eap-tls.ui
new file mode 100644
index 00000000..127f4aa2
--- /dev/null
+++ b/src/nma-ws/nma-eap-tls.ui
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="nm-applet">
+ <requires lib="gtk+" version="3.10"/>
+ <object class="GtkGrid" id="eap_tls_grid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="eap_tls_identity_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">I_dentity</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_tls_identity_entry</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="eap_tls_identity_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="eap_tls_ca_cert_not_required_checkbox">
+ <property name="label" translatable="yes">No CA certificate is _required</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eap_tls_domain_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Suffix of the server certificate name.</property>
+ <property name="label" translatable="yes">_Domain</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_tls_domain_entry</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="eap_tls_domain_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+</interface>
diff --git a/src/nma-ws/nma-eap-ttls.c b/src/nma-ws/nma-eap-ttls.c
new file mode 100644
index 00000000..fee809f8
--- /dev/null
+++ b/src/nma-ws/nma-eap-ttls.c
@@ -0,0 +1,521 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Dan Williams <dcbw redhat com>
+ *
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+#include "nma-private.h"
+
+#include <ctype.h>
+#include <string.h>
+
+#include "nma-eap.h"
+#include "nma-ws.h"
+#include "nma-ws-private.h"
+#include "nma-cert-chooser.h"
+#include "utils.h"
+
+#define I_NAME_COLUMN 0
+#define I_METHOD_COLUMN 1
+
+struct _NMAEapTtls {
+ NMAEap parent;
+
+ const char *password_flags_name;
+ GtkSizeGroup *size_group;
+ NMAWs8021x *ws_8021x;
+ gboolean is_editor;
+
+ GtkWidget *ca_cert_chooser;
+};
+
+static void
+destroy (NMAEap *parent)
+{
+ NMAEapTtls *method = (NMAEapTtls *) parent;
+
+ if (method->size_group)
+ g_object_unref (method->size_group);
+}
+
+static gboolean
+validate (NMAEap *parent, GError **error)
+{
+ NMAEapTtls *method = (NMAEapTtls *) parent;
+ GtkWidget *widget;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ NMAEap *eap = NULL;
+ gboolean valid = FALSE;
+
+ if ( gtk_widget_get_sensitive (method->ca_cert_chooser)
+ && !nma_cert_chooser_validate (NMA_CERT_CHOOSER (method->ca_cert_chooser), error))
+ return FALSE;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_inner_auth_combo"));
+ g_assert (widget);
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+ gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+ g_assert (eap);
+ valid = nma_eap_validate (eap, error);
+ nma_eap_unref (eap);
+ return valid;
+}
+
+static void
+ca_cert_not_required_toggled (GtkWidget *button, gpointer user_data)
+{
+ NMAEapTtls *method = (NMAEapTtls *) user_data;
+
+ gtk_widget_set_sensitive (method->ca_cert_chooser,
+ !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)));
+}
+
+static void
+add_to_size_group (NMAEap *parent, GtkSizeGroup *group)
+{
+ NMAEapTtls *method = (NMAEapTtls *) parent;
+ GtkWidget *widget;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ NMAEap *eap;
+
+ if (method->size_group)
+ g_object_unref (method->size_group);
+ method->size_group = g_object_ref (group);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_anon_identity_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_domain_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ nma_cert_chooser_add_to_size_group (NMA_CERT_CHOOSER (method->ca_cert_chooser), group);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_inner_auth_label"));
+ g_assert (widget);
+ gtk_size_group_add_widget (group, widget);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_inner_auth_combo"));
+ g_assert (widget);
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+ gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+ g_assert (eap);
+ nma_eap_add_to_size_group (eap, group);
+ nma_eap_unref (eap);
+}
+
+static void
+fill_connection (NMAEap *parent, NMConnection *connection)
+{
+ NMAEapTtls *method = (NMAEapTtls *) parent;
+ NMSetting8021x *s_8021x;
+ NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ NMSettingSecretFlags secret_flags;
+ GtkWidget *widget;
+ const char *text;
+ char *value = NULL;
+ NMAEap *eap = NULL;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GError *error = NULL;
+ NMSetting8021xCKScheme scheme = NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
+ gboolean ca_cert_error = FALSE;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ g_assert (s_8021x);
+
+ nm_setting_802_1x_add_eap_method (s_8021x, "ttls");
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_anon_identity_entry"));
+ g_assert (widget);
+ text = gtk_editable_get_text (GTK_EDITABLE (widget));
+ if (text && strlen (text))
+ g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, text, NULL);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_domain_entry"));
+ g_assert (widget);
+ text = gtk_editable_get_text (GTK_EDITABLE (widget));
+ if (text && strlen (text))
+ g_object_set (s_8021x, NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH, text, NULL);
+
+ /* Save CA certificate PIN and its flags to the connection */
+ secret_flags = nma_cert_chooser_get_cert_password_flags (NMA_CERT_CHOOSER (method->ca_cert_chooser));
+ nm_setting_set_secret_flags (NM_SETTING (s_8021x), NM_SETTING_802_1X_CA_CERT_PASSWORD,
+ secret_flags, NULL);
+ if (method->is_editor) {
+ /* Update secret flags and popup when editing the connection */
+ nma_cert_chooser_update_cert_password_storage (NMA_CERT_CHOOSER (method->ca_cert_chooser),
+ secret_flags, NM_SETTING (s_8021x),
+ NM_SETTING_802_1X_CA_CERT_PASSWORD);
+ g_object_set (s_8021x, NM_SETTING_802_1X_CA_CERT_PASSWORD,
+ nma_cert_chooser_get_cert_password (NMA_CERT_CHOOSER (method->ca_cert_chooser)),
+ NULL);
+ }
+
+ /* TLS CA certificate */
+ if (gtk_widget_get_sensitive (method->ca_cert_chooser))
+ value = nma_cert_chooser_get_cert (NMA_CERT_CHOOSER (method->ca_cert_chooser), &scheme);
+ format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ if (!nm_setting_802_1x_set_ca_cert (s_8021x, value, scheme, &format, &error)) {
+ g_warning ("Couldn't read CA certificate '%s': %s", value, error ? error->message :
"(unknown)");
+ g_clear_error (&error);
+ ca_cert_error = TRUE;
+ }
+ nma_eap_ca_cert_ignore_set (parent, connection, value, ca_cert_error);
+ g_free (value);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_inner_auth_combo"));
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+ gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+ g_assert (eap);
+
+ nma_eap_fill_connection (eap, connection);
+ nma_eap_unref (eap);
+}
+
+static void
+inner_auth_combo_changed_cb (GtkWidget *combo, gpointer user_data)
+{
+ NMAEap *parent = (NMAEap *) user_data;
+ NMAEapTtls *method = (NMAEapTtls *) parent;
+ GtkWidget *vbox;
+ NMAEap *eap = NULL;
+ GList *elt, *children;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkWidget *eap_widget;
+
+ vbox = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_inner_auth_vbox"));
+ g_assert (vbox);
+
+ /* Remove any previous wireless security widgets */
+ children = gtk_container_get_children (GTK_CONTAINER (vbox));
+ for (elt = children; elt; elt = g_list_next (elt))
+ gtk_container_remove (GTK_CONTAINER (vbox), GTK_WIDGET (elt->data));
+ g_list_free (children);
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter);
+ gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
+ g_assert (eap);
+
+ eap_widget = nma_eap_get_widget (eap);
+ g_assert (eap_widget);
+ gtk_widget_unparent (eap_widget);
+
+ if (method->size_group)
+ nma_eap_add_to_size_group (eap, method->size_group);
+ gtk_container_add (GTK_CONTAINER (vbox), eap_widget);
+
+ nma_eap_unref (eap);
+
+ nma_ws_changed_cb (combo, method->ws_8021x);
+}
+
+static GtkWidget *
+inner_auth_combo_init (NMAEapTtls *method,
+ NMConnection *connection,
+ NMSetting8021x *s_8021x,
+ gboolean secrets_only)
+{
+ NMAEap *parent = (NMAEap *) method;
+ GtkWidget *combo;
+ GtkListStore *auth_model;
+ GtkTreeIter iter;
+ NMAEapSimple *em_pap;
+ NMAEapSimple *em_mschap;
+ NMAEapSimple *em_mschap_v2;
+ NMAEapSimple *em_plain_mschap_v2;
+ NMAEapSimple *em_chap;
+ NMAEapSimple *em_md5;
+ NMAEapSimple *em_gtc;
+ guint32 active = 0;
+ const char *phase2_auth = NULL;
+ NMAEapSimpleFlags simple_flags;
+
+ auth_model = gtk_list_store_new (2, G_TYPE_STRING, nma_eap_get_type ());
+
+ if (s_8021x) {
+ if (nm_setting_802_1x_get_phase2_auth (s_8021x))
+ phase2_auth = nm_setting_802_1x_get_phase2_auth (s_8021x);
+ else if (nm_setting_802_1x_get_phase2_autheap (s_8021x))
+ phase2_auth = nm_setting_802_1x_get_phase2_autheap (s_8021x);
+ }
+
+ simple_flags = NMA_EAP_SIMPLE_FLAG_PHASE2 | NMA_EAP_SIMPLE_FLAG_AUTHEAP_ALLOWED;
+ if (method->is_editor)
+ simple_flags |= NMA_EAP_SIMPLE_FLAG_IS_EDITOR;
+ if (secrets_only)
+ simple_flags |= NMA_EAP_SIMPLE_FLAG_SECRETS_ONLY;
+
+ em_pap = nma_eap_simple_new (method->ws_8021x,
+ connection,
+ NMA_EAP_SIMPLE_TYPE_PAP,
+ simple_flags,
+ NULL);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ I_NAME_COLUMN, _("PAP"),
+ I_METHOD_COLUMN, em_pap,
+ -1);
+ nma_eap_unref (NMA_EAP (em_pap));
+
+ /* Check for defaulting to PAP */
+ if (phase2_auth && !strcasecmp (phase2_auth, "pap"))
+ active = 0;
+
+ em_mschap = nma_eap_simple_new (method->ws_8021x,
+ connection,
+ NMA_EAP_SIMPLE_TYPE_MSCHAP,
+ simple_flags,
+ NULL);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ I_NAME_COLUMN, _("MSCHAP"),
+ I_METHOD_COLUMN, em_mschap,
+ -1);
+ nma_eap_unref (NMA_EAP (em_mschap));
+
+ /* Check for defaulting to MSCHAP */
+ if (phase2_auth && !strcasecmp (phase2_auth, "mschap"))
+ active = 1;
+
+ em_mschap_v2 = nma_eap_simple_new (method->ws_8021x,
+ connection,
+ NMA_EAP_SIMPLE_TYPE_MSCHAP_V2,
+ simple_flags,
+ NULL);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ I_NAME_COLUMN, _("MSCHAPv2"),
+ I_METHOD_COLUMN, em_mschap_v2,
+ -1);
+ nma_eap_unref (NMA_EAP (em_mschap_v2));
+
+ /* Check for defaulting to MSCHAPv2 */
+ if (phase2_auth && !strcasecmp (phase2_auth, "mschapv2") &&
+ nm_setting_802_1x_get_phase2_autheap (s_8021x) != NULL)
+ active = 2;
+
+ em_plain_mschap_v2 = nma_eap_simple_new (method->ws_8021x,
+ connection,
+ NMA_EAP_SIMPLE_TYPE_PLAIN_MSCHAP_V2,
+ simple_flags,
+ NULL);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ I_NAME_COLUMN, _("MSCHAPv2 (no EAP)"),
+ I_METHOD_COLUMN, em_plain_mschap_v2,
+ -1);
+ nma_eap_unref (NMA_EAP (em_plain_mschap_v2));
+
+ /* Check for defaulting to plain MSCHAPv2 */
+ if (phase2_auth && !strcasecmp (phase2_auth, "mschapv2") &&
+ nm_setting_802_1x_get_phase2_auth (s_8021x) != NULL)
+ active = 3;
+
+ em_chap = nma_eap_simple_new (method->ws_8021x,
+ connection,
+ NMA_EAP_SIMPLE_TYPE_CHAP,
+ simple_flags,
+ NULL);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ I_NAME_COLUMN, _("CHAP"),
+ I_METHOD_COLUMN, em_chap,
+ -1);
+ nma_eap_unref (NMA_EAP (em_chap));
+
+ /* Check for defaulting to CHAP */
+ if (phase2_auth && !strcasecmp (phase2_auth, "chap"))
+ active = 4;
+
+ em_md5 = nma_eap_simple_new (method->ws_8021x,
+ connection,
+ NMA_EAP_SIMPLE_TYPE_MD5,
+ simple_flags,
+ NULL);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ I_NAME_COLUMN, _("MD5"),
+ I_METHOD_COLUMN, em_md5,
+ -1);
+ nma_eap_unref (NMA_EAP (em_md5));
+
+ /* Check for defaulting to MD5 */
+ if (phase2_auth && !strcasecmp (phase2_auth, "md5"))
+ active = 5;
+
+ em_gtc = nma_eap_simple_new (method->ws_8021x,
+ connection,
+ NMA_EAP_SIMPLE_TYPE_GTC,
+ simple_flags,
+ NULL);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ I_NAME_COLUMN, _("GTC"),
+ I_METHOD_COLUMN, em_gtc,
+ -1);
+ nma_eap_unref (NMA_EAP (em_gtc));
+
+ /* Check for defaulting to GTC */
+ if (phase2_auth && !strcasecmp (phase2_auth, "gtc"))
+ active = 6;
+
+ combo = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_inner_auth_combo"));
+ g_assert (combo);
+
+ gtk_combo_box_set_model (GTK_COMBO_BOX (combo), GTK_TREE_MODEL (auth_model));
+ g_object_unref (G_OBJECT (auth_model));
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combo), active);
+
+ g_signal_connect (G_OBJECT (combo), "changed",
+ (GCallback) inner_auth_combo_changed_cb,
+ method);
+ return combo;
+}
+
+static void
+update_secrets (NMAEap *parent, NMConnection *connection)
+{
+ nma_eap_phase2_update_secrets_helper (parent,
+ connection,
+ "eap_ttls_inner_auth_combo",
+ I_METHOD_COLUMN);
+}
+
+NMAEapTtls *
+nma_eap_ttls_new (NMAWs8021x *ws_8021x,
+ NMConnection *connection,
+ gboolean is_editor,
+ gboolean secrets_only)
+{
+ NMAEap *parent;
+ NMAEapTtls *method;
+ GtkWidget *widget;
+ NMSetting8021x *s_8021x = NULL;
+ gboolean ca_not_required = FALSE;
+
+ parent = nma_eap_init (sizeof (NMAEapTtls),
+ validate,
+ add_to_size_group,
+ fill_connection,
+ update_secrets,
+ destroy,
+ "/org/gnome/libnma/nma-eap-ttls.ui",
+ "eap_ttls_grid",
+ "eap_ttls_anon_identity_entry",
+ FALSE);
+ if (!parent)
+ return NULL;
+
+ method = (NMAEapTtls *) parent;
+ method->password_flags_name = NM_SETTING_802_1X_PASSWORD;
+ method->ws_8021x = ws_8021x;
+ method->is_editor = is_editor;
+
+ if (connection)
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_grid"));
+ g_assert (widget);
+
+ method->ca_cert_chooser = nma_cert_chooser_new ("CA",
+ NMA_CERT_CHOOSER_FLAG_CERT
+ | (secrets_only ? NMA_CERT_CHOOSER_FLAG_PASSWORDS :
0));
+ gtk_grid_attach (GTK_GRID (widget), method->ca_cert_chooser, 0, 2, 2, 1);
+ gtk_widget_show (method->ca_cert_chooser);
+
+ g_signal_connect (method->ca_cert_chooser,
+ "cert-validate",
+ G_CALLBACK (nma_eap_ca_cert_validate_cb),
+ NULL);
+ g_signal_connect (method->ca_cert_chooser,
+ "changed",
+ G_CALLBACK (nma_ws_changed_cb),
+ ws_8021x);
+
+ nma_eap_setup_cert_chooser (NMA_CERT_CHOOSER (method->ca_cert_chooser), s_8021x,
+ nm_setting_802_1x_get_ca_cert_scheme,
+ nm_setting_802_1x_get_ca_cert_path,
+ nm_setting_802_1x_get_ca_cert_uri,
+ nm_setting_802_1x_get_ca_cert_password,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+
+ if (connection && nma_eap_ca_cert_ignore_get (parent, connection)) {
+ gchar *ca_cert;
+ NMSetting8021xCKScheme scheme;
+
+ ca_cert = nma_cert_chooser_get_cert (NMA_CERT_CHOOSER (method->ca_cert_chooser), &scheme);
+ if (ca_cert)
+ g_free (ca_cert);
+ else
+ ca_not_required = TRUE;
+ }
+
+ if (secrets_only)
+ ca_not_required = TRUE;
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder,
"eap_ttls_ca_cert_not_required_checkbox"));
+ g_assert (widget);
+ g_signal_connect (G_OBJECT (widget), "toggled",
+ (GCallback) ca_cert_not_required_toggled,
+ parent);
+ g_signal_connect (G_OBJECT (widget), "toggled",
+ (GCallback) nma_ws_changed_cb,
+ ws_8021x);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), ca_not_required);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_anon_identity_entry"));
+ if (s_8021x && nm_setting_802_1x_get_anonymous_identity (s_8021x))
+ gtk_editable_set_text (GTK_EDITABLE (widget), nm_setting_802_1x_get_anonymous_identity
(s_8021x));
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) nma_ws_changed_cb,
+ ws_8021x);
+
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_domain_entry"));
+ if (s_8021x && nm_setting_802_1x_get_domain_suffix_match (s_8021x))
+ gtk_editable_set_text (GTK_EDITABLE (widget), nm_setting_802_1x_get_domain_suffix_match
(s_8021x));
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) nma_ws_changed_cb,
+ ws_8021x);
+
+ widget = inner_auth_combo_init (method, connection, s_8021x, secrets_only);
+ inner_auth_combo_changed_cb (widget, (gpointer) method);
+
+ if (secrets_only) {
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder,
"eap_ttls_anon_identity_label"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder,
"eap_ttls_anon_identity_entry"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_domain_label"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_domain_entry"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder,
"eap_ttls_ca_cert_not_required_checkbox"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_inner_auth_label"));
+ gtk_widget_hide (widget);
+ widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_ttls_inner_auth_combo"));
+ gtk_widget_hide (widget);
+ }
+
+ nma_cert_chooser_setup_cert_password_storage (NMA_CERT_CHOOSER (method->ca_cert_chooser),
+ 0, (NMSetting *) s_8021x,
NM_SETTING_802_1X_CA_CERT_PASSWORD,
+ FALSE, secrets_only);
+
+ return method;
+}
diff --git a/src/nma-ws/nma-eap-ttls.h b/src/nma-ws/nma-eap-ttls.h
new file mode 100644
index 00000000..1e072336
--- /dev/null
+++ b/src/nma-ws/nma-eap-ttls.h
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Dan Williams <dcbw redhat com>
+ *
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+
+#ifndef NMA_EAP_TTLS_H
+#define NMA_EAP_TTLS_H
+
+#include "nma-ws.h"
+
+typedef struct _NMAEapTtls NMAEapTtls;
+
+NMAEapTtls *nma_eap_ttls_new (NMAWs8021x *ws_8021x,
+ NMConnection *connection,
+ gboolean is_editor,
+ gboolean secrets_only);
+
+#endif /* NMA_EAP_TLS_H */
diff --git a/src/nma-ws/nma-eap-ttls.ui b/src/nma-ws/nma-eap-ttls.ui
new file mode 100644
index 00000000..b5acde15
--- /dev/null
+++ b/src/nma-ws/nma-eap-ttls.ui
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="nm-applet">
+ <requires lib="gtk+" version="3.10"/>
+ <object class="GtkListStore" id="model6">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0"> </col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkGrid" id="eap_ttls_grid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkEntry" id="eap_ttls_anon_identity_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="eap_ttls_inner_auth_vbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">5</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="eap_ttls_inner_auth_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="model">model6</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer6"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eap_ttls_inner_auth_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Inner authentication</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_ttls_inner_auth_combo</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="eap_ttls_ca_cert_not_required_checkbox">
+ <property name="label" translatable="yes">No CA certificate is _required</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="eap_ttls_domain_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eap_ttls_anon_identity_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Anony_mous identity</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_ttls_anon_identity_entry</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="eap_ttls_domain_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Suffix of the server certificate name.</property>
+ <property name="label" translatable="yes">_Domain</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_ttls_domain_entry</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+</interface>
diff --git a/src/nma-ws/nma-eap.c b/src/nma-ws/nma-eap.c
new file mode 100644
index 00000000..f666dab9
--- /dev/null
+++ b/src/nma-ws/nma-eap.c
@@ -0,0 +1,424 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Dan Williams <dcbw redhat com>
+ *
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "nma-eap.h"
+#include "nm-utils.h"
+#include "utils.h"
+
+G_DEFINE_BOXED_TYPE (NMAEap, nma_eap, nma_eap_ref, nma_eap_unref)
+
+GtkWidget *
+nma_eap_get_widget (NMAEap *method)
+{
+ g_return_val_if_fail (method != NULL, NULL);
+
+ return method->ui_widget;
+}
+
+gboolean
+nma_eap_validate (NMAEap *method, GError **error)
+{
+ gboolean result;
+
+ g_return_val_if_fail (method != NULL, FALSE);
+
+ g_assert (method->validate);
+ result = (*(method->validate)) (method, error);
+ if (!result && error && !*error)
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("undefined error in 802.1X
security (wpa-eap)"));
+ return result;
+}
+
+void
+nma_eap_add_to_size_group (NMAEap *method, GtkSizeGroup *group)
+{
+ g_return_if_fail (method != NULL);
+ g_return_if_fail (group != NULL);
+
+ g_assert (method->add_to_size_group);
+ return (*(method->add_to_size_group)) (method, group);
+}
+
+void
+nma_eap_fill_connection (NMAEap *method,
+ NMConnection *connection)
+{
+ g_return_if_fail (method != NULL);
+ g_return_if_fail (connection != NULL);
+
+ g_assert (method->fill_connection);
+ return (*(method->fill_connection)) (method, connection);
+}
+
+void
+nma_eap_update_secrets (NMAEap *method, NMConnection *connection)
+{
+ g_return_if_fail (method != NULL);
+ g_return_if_fail (connection != NULL);
+
+ if (method->update_secrets)
+ method->update_secrets (method, connection);
+}
+
+void
+nma_eap_phase2_update_secrets_helper (NMAEap *method,
+ NMConnection *connection,
+ const char *combo_name,
+ guint32 column)
+{
+ GtkWidget *combo;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+
+ g_return_if_fail (method != NULL);
+ g_return_if_fail (connection != NULL);
+ g_return_if_fail (combo_name != NULL);
+
+ combo = GTK_WIDGET (gtk_builder_get_object (method->builder, combo_name));
+ g_assert (combo);
+
+ /* Let each EAP phase2 method try to update its secrets */
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
+ if (gtk_tree_model_get_iter_first (model, &iter)) {
+ do {
+ NMAEap *eap = NULL;
+
+ gtk_tree_model_get (model, &iter, column, &eap, -1);
+ if (eap) {
+ nma_eap_update_secrets (eap, connection);
+ nma_eap_unref (eap);
+ }
+ } while (gtk_tree_model_iter_next (model, &iter));
+ }
+}
+
+NMAEap *
+nma_eap_init (gsize obj_size,
+ NMAEapValidateFunc validate,
+ NMAEapAddToSizeGroupFunc add_to_size_group,
+ NMAEapFillConnectionFunc fill_connection,
+ NMAEapUpdateSecretsFunc update_secrets,
+ NMAEapDestroyFunc destroy,
+ const char *ui_resource,
+ const char *ui_widget_name,
+ const char *default_field,
+ gboolean phase2)
+{
+ NMAEap *method;
+ GError *error = NULL;
+
+ g_return_val_if_fail (obj_size > 0, NULL);
+ g_return_val_if_fail (ui_resource != NULL, NULL);
+ g_return_val_if_fail (ui_widget_name != NULL, NULL);
+
+ method = g_slice_alloc0 (obj_size);
+ g_assert (method);
+
+ method->refcount = 1;
+ method->obj_size = obj_size;
+ method->validate = validate;
+ method->add_to_size_group = add_to_size_group;
+ method->fill_connection = fill_connection;
+ method->update_secrets = update_secrets;
+ method->default_field = default_field;
+ method->phase2 = phase2;
+
+ method->builder = gtk_builder_new ();
+ if (!gtk_builder_add_from_resource (method->builder, ui_resource, &error)) {
+ g_warning ("Couldn't load UI builder resource %s: %s",
+ ui_resource, error->message);
+ nma_eap_unref (method);
+ return NULL;
+ }
+
+ method->ui_widget = GTK_WIDGET (gtk_builder_get_object (method->builder, ui_widget_name));
+ if (!method->ui_widget) {
+ g_warning ("Couldn't load UI widget '%s' from UI file %s",
+ ui_widget_name, ui_resource);
+ nma_eap_unref (method);
+ return NULL;
+ }
+ g_object_ref_sink (method->ui_widget);
+
+ method->destroy = destroy;
+
+ return method;
+}
+
+
+NMAEap *
+nma_eap_ref (NMAEap *method)
+{
+ g_return_val_if_fail (method != NULL, NULL);
+ g_return_val_if_fail (method->refcount > 0, NULL);
+
+ method->refcount++;
+ return method;
+}
+
+void
+nma_eap_unref (NMAEap *method)
+{
+ g_return_if_fail (method != NULL);
+ g_return_if_fail (method->refcount > 0);
+
+ method->refcount--;
+ if (method->refcount == 0) {
+ if (method->destroy)
+ method->destroy (method);
+
+ if (method->builder)
+ g_object_unref (method->builder);
+ if (method->ui_widget)
+ g_object_unref (method->ui_widget);
+
+ g_slice_free1 (method->obj_size, method);
+ }
+}
+
+/* Used as both GSettings keys and GObject data tags */
+#define IGNORE_CA_CERT_TAG "ignore-ca-cert"
+#define IGNORE_PHASE2_CA_CERT_TAG "ignore-phase2-ca-cert"
+
+/**
+ * nma_eap_ca_cert_ignore_set:
+ * @method: the #NMAEap object
+ * @connection: the #NMConnection
+ * @filename: the certificate file, if any
+ * @ca_cert_error: %TRUE if an error was encountered loading the given CA
+ * certificate, %FALSE if not or if a CA certificate is not present
+ *
+ * Updates the connection's CA cert ignore value to %TRUE if the "CA certificate
+ * not required" checkbox is checked. If @ca_cert_error is %TRUE, then the
+ * connection's CA cert ignore value will always be set to %FALSE, because it
+ * means that the user selected an invalid certificate (thus he does not want to
+ * ignore the CA cert)..
+ */
+void
+nma_eap_ca_cert_ignore_set (NMAEap *method,
+ NMConnection *connection,
+ const char *filename,
+ gboolean ca_cert_error)
+{
+ NMSetting8021x *s_8021x;
+ gboolean ignore;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ if (s_8021x) {
+ ignore = !ca_cert_error && filename == NULL;
+ g_object_set_data (G_OBJECT (s_8021x),
+ method->phase2 ? IGNORE_PHASE2_CA_CERT_TAG : IGNORE_CA_CERT_TAG,
+ GUINT_TO_POINTER (ignore));
+ }
+}
+
+/**
+ * nma_eap_ca_cert_ignore_get:
+ * @method: the #NMAEap object
+ * @connection: the #NMConnection
+ *
+ * Returns: %TRUE if a missing CA certificate can be ignored, %FALSE if a CA
+ * certificate should be required for the connection to be valid.
+ */
+gboolean
+nma_eap_ca_cert_ignore_get (NMAEap *method, NMConnection *connection)
+{
+ NMSetting8021x *s_8021x;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ if (s_8021x) {
+ return !!g_object_get_data (G_OBJECT (s_8021x),
+ method->phase2 ? IGNORE_PHASE2_CA_CERT_TAG : IGNORE_CA_CERT_TAG);
+ }
+ return FALSE;
+}
+
+static GSettings *
+_get_ca_ignore_settings (NMConnection *connection)
+{
+ GSettings *settings;
+ char *path = NULL;
+ const char *uuid;
+
+ g_return_val_if_fail (connection, NULL);
+
+ uuid = nm_connection_get_uuid (connection);
+ g_return_val_if_fail (uuid && *uuid, NULL);
+
+ path = g_strdup_printf ("/org/gnome/nm-applet/eap/%s/", uuid);
+ settings = g_settings_new_with_path ("org.gnome.nm-applet.eap", path);
+ g_free (path);
+
+ return settings;
+}
+
+/**
+ * nma_eap_ca_cert_ignore_save:
+ * @connection: the connection for which to save CA cert ignore values to GSettings
+ *
+ * Reads the CA cert ignore tags from the 802.1x setting GObject data and saves
+ * then to GSettings if present, using the connection UUID as the index.
+ */
+void
+nma_eap_ca_cert_ignore_save (NMConnection *connection)
+{
+ NMSetting8021x *s_8021x;
+ GSettings *settings;
+ gboolean ignore = FALSE, phase2_ignore = FALSE;
+
+ g_return_if_fail (connection);
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ if (s_8021x) {
+ ignore = !!g_object_get_data (G_OBJECT (s_8021x), IGNORE_CA_CERT_TAG);
+ phase2_ignore = !!g_object_get_data (G_OBJECT (s_8021x), IGNORE_PHASE2_CA_CERT_TAG);
+ }
+
+ settings = _get_ca_ignore_settings (connection);
+ if (!settings)
+ return;
+
+ g_settings_set_boolean (settings, IGNORE_CA_CERT_TAG, ignore);
+ g_settings_set_boolean (settings, IGNORE_PHASE2_CA_CERT_TAG, phase2_ignore);
+ g_object_unref (settings);
+}
+
+/**
+ * nma_eap_ca_cert_ignore_load:
+ * @connection: the connection for which to load CA cert ignore values to GSettings
+ *
+ * Reads the CA cert ignore tags from the 802.1x setting GObject data and saves
+ * then to GSettings if present, using the connection UUID as the index.
+ */
+void
+nma_eap_ca_cert_ignore_load (NMConnection *connection)
+{
+ GSettings *settings;
+ NMSetting8021x *s_8021x;
+ gboolean ignore, phase2_ignore;
+
+ g_return_if_fail (connection);
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ if (!s_8021x)
+ return;
+
+ settings = _get_ca_ignore_settings (connection);
+ if (!settings)
+ return;
+
+ ignore = g_settings_get_boolean (settings, IGNORE_CA_CERT_TAG);
+ phase2_ignore = g_settings_get_boolean (settings, IGNORE_PHASE2_CA_CERT_TAG);
+
+ g_object_set_data (G_OBJECT (s_8021x),
+ IGNORE_CA_CERT_TAG,
+ GUINT_TO_POINTER (ignore));
+ g_object_set_data (G_OBJECT (s_8021x),
+ IGNORE_PHASE2_CA_CERT_TAG,
+ GUINT_TO_POINTER (phase2_ignore));
+ g_object_unref (settings);
+}
+
+GError *
+nma_eap_ca_cert_validate_cb (NMACertChooser *cert_chooser, gpointer user_data)
+{
+ NMSetting8021xCKScheme scheme;
+ NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ gs_unref_object NMSetting8021x *setting = NULL;
+ gs_free char *value = NULL;
+ GError *local = NULL;
+
+ setting = (NMSetting8021x *) nm_setting_802_1x_new ();
+
+ value = nma_cert_chooser_get_cert (cert_chooser, &scheme);
+ if (!value) {
+ return g_error_new_literal (NMA_ERROR, NMA_ERROR_GENERIC,
+ _("no CA certificate selected"));
+ }
+ if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) {
+ if (!g_file_test (value, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
+ return g_error_new_literal (NMA_ERROR, NMA_ERROR_GENERIC,
+ _("selected CA certificate file does not exist"));
+ }
+ }
+
+ if (!nm_setting_802_1x_set_ca_cert (setting, value, scheme, &format, &local))
+ return local;
+
+ return NULL;
+}
+
+void
+nma_eap_setup_cert_chooser (NMACertChooser *cert_chooser,
+ NMSetting8021x *s_8021x,
+ NMSetting8021xCKScheme (*cert_scheme_func) (NMSetting8021x *setting),
+ const char *(*cert_path_func) (NMSetting8021x *setting),
+ const char *(*cert_uri_func) (NMSetting8021x *setting),
+ const char *(*cert_password_func) (NMSetting8021x *setting),
+ NMSetting8021xCKScheme (*key_scheme_func) (NMSetting8021x *setting),
+ const char *(*key_path_func) (NMSetting8021x *setting),
+ const char *(*key_uri_func) (NMSetting8021x *setting),
+ const char *(*key_password_func) (NMSetting8021x *setting))
+{
+ NMSetting8021xCKScheme scheme = NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
+ const char *value = NULL;
+ const char *password = NULL;
+
+
+ if (s_8021x && cert_path_func && cert_uri_func && cert_scheme_func) {
+ scheme = cert_scheme_func (s_8021x);
+ switch (scheme) {
+ case NM_SETTING_802_1X_CK_SCHEME_PATH:
+ value = cert_path_func (s_8021x);
+ break;
+ case NM_SETTING_802_1X_CK_SCHEME_PKCS11:
+ value = cert_uri_func (s_8021x);
+ password = cert_password_func ? cert_password_func (s_8021x) : NULL;
+ if (password)
+ nma_cert_chooser_set_cert_password (cert_chooser, password);
+ break;
+ case NM_SETTING_802_1X_CK_SCHEME_UNKNOWN:
+ /* No CA set. */
+ break;
+ default:
+ g_warning ("unhandled certificate scheme %d", scheme);
+ }
+
+ }
+ nma_cert_chooser_set_cert (cert_chooser, value, scheme);
+
+ if (s_8021x && key_path_func && key_uri_func && key_scheme_func) {
+ scheme = key_scheme_func (s_8021x);
+ switch (scheme) {
+ case NM_SETTING_802_1X_CK_SCHEME_PATH:
+ value = key_path_func (s_8021x);
+ break;
+ case NM_SETTING_802_1X_CK_SCHEME_PKCS11:
+ value = key_uri_func (s_8021x);
+ break;
+ case NM_SETTING_802_1X_CK_SCHEME_UNKNOWN:
+ /* No certificate set. */
+ break;
+ default:
+ g_warning ("unhandled key scheme %d", scheme);
+ }
+
+ nma_cert_chooser_set_key (cert_chooser, value, scheme);
+ }
+
+ password = s_8021x && key_password_func ? key_password_func (s_8021x) : NULL;
+ if (password)
+ nma_cert_chooser_set_key_password (cert_chooser, key_password_func (s_8021x));
+}
diff --git a/src/nma-ws/nma-eap.h b/src/nma-ws/nma-eap.h
new file mode 100644
index 00000000..db5c84a0
--- /dev/null
+++ b/src/nma-ws/nma-eap.h
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Dan Williams <dcbw redhat com>
+ *
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+
+#ifndef NMA_EAP_H
+#define NMA_EAP_H
+
+typedef struct _NMAEap NMAEap;
+
+typedef void (*NMAEapAddToSizeGroupFunc) (NMAEap *method, GtkSizeGroup *group);
+typedef void (*NMAEapFillConnectionFunc) (NMAEap *method, NMConnection *connection);
+typedef void (*NMAEapUpdateSecretsFunc) (NMAEap *method, NMConnection *connection);
+typedef void (*NMAEapDestroyFunc) (NMAEap *method);
+typedef gboolean (*NMAEapValidateFunc) (NMAEap *method, GError **error);
+
+struct _NMAEap {
+ guint32 refcount;
+ gsize obj_size;
+
+ GtkBuilder *builder;
+ GtkWidget *ui_widget;
+
+ const char *default_field;
+
+ gboolean phase2;
+ gboolean secrets_only;
+
+ NMAEapAddToSizeGroupFunc add_to_size_group;
+ NMAEapFillConnectionFunc fill_connection;
+ NMAEapUpdateSecretsFunc update_secrets;
+ NMAEapValidateFunc validate;
+ NMAEapDestroyFunc destroy;
+};
+
+#define NMA_EAP(x) ((NMAEap *) x)
+
+
+GtkWidget *nma_eap_get_widget (NMAEap *method);
+
+gboolean nma_eap_validate (NMAEap *method, GError **error);
+
+void nma_eap_add_to_size_group (NMAEap *method, GtkSizeGroup *group);
+
+void nma_eap_fill_connection (NMAEap *method,
+ NMConnection *connection);
+
+void nma_eap_update_secrets (NMAEap *method, NMConnection *connection);
+
+NMAEap *nma_eap_ref (NMAEap *method);
+
+void nma_eap_unref (NMAEap *method);
+
+GType nma_eap_get_type (void);
+
+/* Below for internal use only */
+
+#include "nma-cert-chooser.h"
+#include "nma-eap-tls.h"
+#include "nma-eap-leap.h"
+#include "nma-eap-fast.h"
+#include "nma-eap-ttls.h"
+#include "nma-eap-peap.h"
+#include "nma-eap-simple.h"
+
+NMAEap *nma_eap_init (gsize obj_size,
+ NMAEapValidateFunc validate,
+ NMAEapAddToSizeGroupFunc add_to_size_group,
+ NMAEapFillConnectionFunc fill_connection,
+ NMAEapUpdateSecretsFunc update_secrets,
+ NMAEapDestroyFunc destroy,
+ const char *ui_resource,
+ const char *ui_widget_name,
+ const char *default_field,
+ gboolean phase2);
+
+void nma_eap_phase2_update_secrets_helper (NMAEap *method,
+ NMConnection *connection,
+ const char *combo_name,
+ guint32 column);
+
+void nma_eap_ca_cert_ignore_set (NMAEap *method,
+ NMConnection *connection,
+ const char *filename,
+ gboolean ca_cert_error);
+gboolean nma_eap_ca_cert_ignore_get (NMAEap *method, NMConnection *connection);
+
+void nma_eap_ca_cert_ignore_save (NMConnection *connection);
+void nma_eap_ca_cert_ignore_load (NMConnection *connection);
+
+GError *nma_eap_ca_cert_validate_cb (NMACertChooser *cert_chooser, gpointer user_data);
+
+void nma_eap_setup_cert_chooser (NMACertChooser *cert_chooser,
+ NMSetting8021x *s_8021x,
+ NMSetting8021xCKScheme (*cert_scheme_func) (NMSetting8021x *setting),
+ const char *(*cert_path_func) (NMSetting8021x *setting),
+ const char *(*cert_uri_func) (NMSetting8021x *setting),
+ const char *(*cert_password_func) (NMSetting8021x *setting),
+ NMSetting8021xCKScheme (*key_scheme_func) (NMSetting8021x *setting),
+ const char *(*key_path_func) (NMSetting8021x *setting),
+ const char *(*key_uri_func) (NMSetting8021x *setting),
+ const char *(*key_password_func) (NMSetting8021x *setting));
+
+#endif /* NMA_EAP_H */
diff --git a/src/nma-ws/nma-ws-802-1x-private.h b/src/nma-ws/nma-ws-802-1x-private.h
new file mode 100644
index 00000000..23743eee
--- /dev/null
+++ b/src/nma-ws/nma-ws-802-1x-private.h
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+
+#ifndef NMA_WS_802_1X_PRIVATE_H
+#define NMA_WS_802_1X_PRIVATE_H
+
+struct _NMAWs8021xClass {
+ GtkGridClass parent;
+};
+
+struct _NMAWs8021x {
+ GtkGrid parent;
+
+ GtkWidget *eap_auth_combo;
+ GtkWidget *eap_auth_label;
+ GtkWidget *eap_vbox;
+
+ NMConnection *connection;
+ gboolean secrets_only;
+ gboolean is_editor;
+ char **secrets_hints;
+
+ char *username, *password;
+ gboolean always_ask, show_password;
+};
+
+void nma_ws_802_1x_fill_connection (NMAWs *ws, NMConnection *connection);
+
+void nma_ws_802_1x_set_userpass (NMAWs8021x *self,
+ const char *user,
+ const char *password,
+ gboolean always_ask,
+ gboolean show_password);
+
+#endif /* NMA_WS_802_1X_PRIVATE_H */
diff --git a/src/nma-ws/nma-ws-802-1x.c b/src/nma-ws/nma-ws-802-1x.c
new file mode 100644
index 00000000..ad0c13a5
--- /dev/null
+++ b/src/nma-ws/nma-ws-802-1x.c
@@ -0,0 +1,525 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+#include "nma-private.h"
+
+#include <ctype.h>
+#include <string.h>
+
+#include "nma-ws.h"
+#include "nma-ws-private.h"
+#include "nma-ws-802-1x.h"
+#include "nma-ws-802-1x-private.h"
+#include "nma-ws-helpers.h"
+#include "nma-ui-utils.h"
+
+#include "nma-eap-tls.h"
+#include "nma-eap-leap.h"
+#include "nma-eap-fast.h"
+#include "nma-eap-ttls.h"
+#include "nma-eap-peap.h"
+#include "nma-eap-simple.h"
+#include "nma-eap.h"
+
+#include "utils.h"
+
+#define AUTH_NAME_COLUMN 0
+#define AUTH_METHOD_COLUMN 1
+
+static void nma_ws_interface_init (NMAWsInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (NMAWs8021x, nma_ws_802_1x, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (NMA_TYPE_WS, nma_ws_interface_init))
+
+enum {
+ PROP_0,
+ PROP_CONNECTION,
+ PROP_SECRETS_ONLY,
+ PROP_IS_EDITOR,
+ PROP_SECRETS_HINTS,
+ PROP_LAST
+};
+
+void
+nma_ws_802_1x_set_userpass (NMAWs8021x *self,
+ const char *user,
+ const char *password,
+ gboolean always_ask,
+ gboolean show_password)
+{
+ g_free (self->username);
+ self->username = g_strdup (user);
+
+ if (self->password) {
+ memset (self->password, 0, strlen (self->password));
+ g_free (self->password);
+ }
+ self->password = g_strdup (password);
+
+ if (always_ask != (gboolean) -1)
+ self->always_ask = always_ask;
+ self->show_password = show_password;
+}
+
+static void
+init_userpass (NMAWs8021x *self, NMConnection *connection)
+{
+ const char *user = NULL, *password = NULL;
+ gboolean always_ask = FALSE, show_password = FALSE;
+ NMSetting8021x *setting;
+ NMSettingSecretFlags flags;
+
+ if (!connection)
+ goto set;
+
+ setting = nm_connection_get_setting_802_1x (connection);
+ if (!setting)
+ goto set;
+
+ user = nm_setting_802_1x_get_identity (setting);
+ password = nm_setting_802_1x_get_password (setting);
+
+ if (nm_setting_get_secret_flags (NM_SETTING (setting), NM_SETTING_802_1X_PASSWORD, &flags, NULL))
+ always_ask = !!(flags & NM_SETTING_SECRET_FLAG_NOT_SAVED);
+
+set:
+ nma_ws_802_1x_set_userpass (self, user, password, always_ask, show_password);
+}
+
+static gboolean
+validate (NMAWs *ws, GError **error)
+{
+ NMAWs8021x *self = NMA_WS_802_1X (ws);
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ NMAEap *eap = NULL;
+ gboolean valid = FALSE;
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (self->eap_auth_combo));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (self->eap_auth_combo), &iter);
+ gtk_tree_model_get (model, &iter, AUTH_METHOD_COLUMN, &eap, -1);
+ g_return_val_if_fail (eap, FALSE);
+ valid = nma_eap_validate (eap, error);
+ nma_eap_unref (eap);
+ return valid;
+}
+
+static void
+auth_combo_changed_cb (GtkWidget *combo, gpointer user_data)
+{
+ NMAWs8021x *self = NMA_WS_802_1X (user_data);
+
+ NMAEap *eap = NULL;
+ GList *elt, *children;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkWidget *eap_widget;
+ GtkWidget *eap_default_widget = NULL;
+
+ /* Remove any previous wireless security widgets */
+ children = gtk_container_get_children (GTK_CONTAINER (self->eap_vbox));
+ for (elt = children; elt; elt = g_list_next (elt))
+ gtk_container_remove (GTK_CONTAINER (self->eap_vbox), GTK_WIDGET (elt->data));
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter);
+ gtk_tree_model_get (model, &iter, AUTH_METHOD_COLUMN, &eap, -1);
+ g_return_if_fail (eap);
+
+ eap_widget = nma_eap_get_widget (eap);
+ g_return_if_fail (eap_widget);
+ gtk_widget_unparent (eap_widget);
+
+ gtk_container_add (GTK_CONTAINER (self->eap_vbox), eap_widget);
+
+ /* Refocus the EAP method's default widget */
+ if (eap->default_field) {
+ eap_default_widget = GTK_WIDGET (gtk_builder_get_object (eap->builder, eap->default_field));
+ if (eap_default_widget)
+ gtk_widget_grab_focus (eap_default_widget);
+ }
+
+ nma_eap_unref (eap);
+
+ nma_ws_changed_cb (combo, NMA_WS (self));
+}
+
+static void
+add_to_size_group (NMAWs *ws, GtkSizeGroup *group)
+{
+ NMAWs8021x *self = NMA_WS_802_1X (ws);
+ NMAEap *eap = NULL;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (self->eap_auth_combo));
+
+ /* Let each EAP method try to update its secrets */
+ if (gtk_tree_model_get_iter_first (model, &iter)) {
+ do {
+ gtk_tree_model_get (model, &iter, AUTH_METHOD_COLUMN, &eap, -1);
+ if (eap) {
+ nma_eap_add_to_size_group (eap, group);
+ nma_eap_unref (eap);
+ }
+ } while (gtk_tree_model_iter_next (model, &iter));
+ }
+
+ gtk_size_group_add_widget (group, self->eap_auth_label);
+}
+
+void
+nma_ws_802_1x_fill_connection (NMAWs *ws, NMConnection *connection)
+{
+ NMAWs8021x *self = NMA_WS_802_1X (ws);
+ NMSettingWirelessSecurity *s_wireless_sec;
+ NMSetting8021x *s_8021x;
+ NMAEap *eap = NULL;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ /* Get the NMAEap object */
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (self->eap_auth_combo));
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (self->eap_auth_combo), &iter);
+ gtk_tree_model_get (model, &iter, AUTH_METHOD_COLUMN, &eap, -1);
+ g_return_if_fail (eap);
+
+ /* Blow away the old wireless 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);
+
+ /* Blow away the old 802.1x setting by adding a clear one */
+ s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
+ nm_connection_add_setting (connection, (NMSetting *) s_8021x);
+
+ nma_eap_fill_connection (eap, connection);
+ nma_eap_unref (eap);
+}
+
+static void
+update_secrets (NMAWs *ws, NMConnection *connection)
+{
+ NMAWs8021x *self = NMA_WS_802_1X (ws);
+ NMAEap *eap = NULL;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ g_return_if_fail (connection != NULL);
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (self->eap_auth_combo));
+
+ /* Let each EAP method try to update its secrets */
+ if (gtk_tree_model_get_iter_first (model, &iter)) {
+ do {
+ gtk_tree_model_get (model, &iter, AUTH_METHOD_COLUMN, &eap, -1);
+ if (eap) {
+ nma_eap_update_secrets (eap, connection);
+ nma_eap_unref (eap);
+ }
+ } while (gtk_tree_model_iter_next (model, &iter));
+ }
+}
+
+static void
+get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ NMAWs8021x *self = NMA_WS_802_1X (object);
+
+ switch (prop_id) {
+ case PROP_CONNECTION:
+ g_value_set_object (value, self->connection);
+ break;
+ case PROP_SECRETS_ONLY:
+ g_value_set_boolean (value, self->secrets_only);
+ break;
+ case PROP_IS_EDITOR:
+ g_value_set_boolean (value, self->is_editor);
+ break;
+ case PROP_SECRETS_HINTS:
+ g_value_set_boxed (value, self->secrets_hints);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ NMAWs8021x *self = NMA_WS_802_1X (object);
+
+ switch (prop_id) {
+ case PROP_CONNECTION:
+ self->connection = g_value_dup_object (value);
+ break;
+ case PROP_SECRETS_ONLY:
+ self->secrets_only = g_value_get_boolean (value);
+ break;
+ case PROP_IS_EDITOR:
+ self->is_editor = g_value_get_boolean (value);
+ break;
+ case PROP_SECRETS_HINTS:
+ self->secrets_hints = g_value_dup_boxed (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nma_ws_802_1x_init (NMAWs8021x *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static void
+nma_ws_interface_init (NMAWsInterface *iface)
+{
+ iface->validate = validate;
+ iface->add_to_size_group = add_to_size_group;
+ iface->fill_connection = nma_ws_802_1x_fill_connection;
+ iface->update_secrets = update_secrets;
+ iface->adhoc_compatible = FALSE;
+ iface->hotspot_compatible = FALSE;
+}
+
+static void
+constructed (GObject *object)
+{
+ NMAWs8021x *self = NMA_WS_802_1X (object);
+ GtkListStore *auth_model;
+ GtkTreeIter iter;
+ NMAEapSimple *em_md5;
+ NMAEapTls *em_tls;
+ NMAEapLeap *em_leap;
+ NMAEapSimple *em_pwd;
+ NMAEapFast *em_fast;
+ NMAEapTtls *em_ttls;
+ NMAEapPeap *em_peap;
+ const char *default_method = NULL, *ctype = NULL;
+ int active = -1, item = 0;
+ gboolean wired = FALSE;
+ NMAEapSimpleFlags simple_flags = NMA_EAP_SIMPLE_FLAG_NONE;
+
+ /* Grab the default EAP method out of the security object */
+ if (self->connection) {
+ NMSettingConnection *s_con;
+ NMSetting8021x *s_8021x;
+
+ s_con = nm_connection_get_setting_connection (self->connection);
+ if (s_con)
+ ctype = nm_setting_connection_get_connection_type (s_con);
+ if ( (g_strcmp0 (ctype, NM_SETTING_WIRED_SETTING_NAME) == 0)
+ || nm_connection_get_setting_wired (self->connection))
+ wired = TRUE;
+
+ s_8021x = nm_connection_get_setting_802_1x (self->connection);
+ if (s_8021x && nm_setting_802_1x_get_num_eap_methods (s_8021x))
+ default_method = nm_setting_802_1x_get_eap_method (s_8021x, 0);
+ }
+
+ /* initialize NMAWs userpass from connection (clear if no connection) */
+ init_userpass (self, self->connection);
+
+ auth_model = gtk_list_store_new (2, G_TYPE_STRING, nma_eap_get_type ());
+
+ if (self->is_editor)
+ simple_flags |= NMA_EAP_SIMPLE_FLAG_IS_EDITOR;
+ if (self->secrets_only)
+ simple_flags |= NMA_EAP_SIMPLE_FLAG_SECRETS_ONLY;
+
+ if (wired) {
+ em_md5 = nma_eap_simple_new (self, self->connection, NMA_EAP_SIMPLE_TYPE_MD5, simple_flags,
NULL);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ AUTH_NAME_COLUMN, _("MD5"),
+ AUTH_METHOD_COLUMN, em_md5,
+ -1);
+ nma_eap_unref (NMA_EAP (em_md5));
+ if (default_method && (active < 0) && !strcmp (default_method, "md5"))
+ active = item;
+ item++;
+ }
+
+ em_tls = nma_eap_tls_new (self, self->connection, FALSE, self->secrets_only);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ AUTH_NAME_COLUMN, _("TLS"),
+ AUTH_METHOD_COLUMN, em_tls,
+ -1);
+ nma_eap_unref (NMA_EAP (em_tls));
+ if (default_method && (active < 0) && !strcmp (default_method, "tls"))
+ active = item;
+ item++;
+
+ if (!wired) {
+ em_leap = nma_eap_leap_new (self, self->connection, self->secrets_only);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ AUTH_NAME_COLUMN, _("LEAP"),
+ AUTH_METHOD_COLUMN, em_leap,
+ -1);
+ nma_eap_unref (NMA_EAP (em_leap));
+ if (default_method && (active < 0) && !strcmp (default_method, "leap"))
+ active = item;
+ item++;
+ }
+
+ em_pwd = nma_eap_simple_new (self, self->connection, NMA_EAP_SIMPLE_TYPE_PWD, simple_flags, NULL);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ AUTH_NAME_COLUMN, _("PWD"),
+ AUTH_METHOD_COLUMN, em_pwd,
+ -1);
+ nma_eap_unref (NMA_EAP (em_pwd));
+ if (default_method && (active < 0) && !strcmp (default_method, "pwd"))
+ active = item;
+ item++;
+
+ em_fast = nma_eap_fast_new (self, self->connection, self->is_editor, self->secrets_only);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ AUTH_NAME_COLUMN, _("FAST"),
+ AUTH_METHOD_COLUMN, em_fast,
+ -1);
+ nma_eap_unref (NMA_EAP (em_fast));
+ if (default_method && (active < 0) && !strcmp (default_method, "fast"))
+ active = item;
+ item++;
+
+ em_ttls = nma_eap_ttls_new (self, self->connection, self->is_editor, self->secrets_only);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ AUTH_NAME_COLUMN, _("Tunneled TLS"),
+ AUTH_METHOD_COLUMN, em_ttls,
+ -1);
+ nma_eap_unref (NMA_EAP (em_ttls));
+ if (default_method && (active < 0) && !strcmp (default_method, "ttls"))
+ active = item;
+ item++;
+
+ em_peap = nma_eap_peap_new (self, self->connection, self->is_editor, self->secrets_only);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ AUTH_NAME_COLUMN, _("Protected EAP (PEAP)"),
+ AUTH_METHOD_COLUMN, em_peap,
+ -1);
+ nma_eap_unref (NMA_EAP (em_peap));
+ if (default_method && (active < 0) && !strcmp (default_method, "peap"))
+ active = item;
+ item++;
+
+ if (self->secrets_hints && self->secrets_hints[0]) {
+ NMAEapSimple *em_hints;
+
+ em_hints = nma_eap_simple_new (self, self->connection, NMA_EAP_SIMPLE_TYPE_UNKNOWN,
+ simple_flags, (const char **)self->secrets_hints);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ AUTH_NAME_COLUMN, _("Unknown"),
+ AUTH_METHOD_COLUMN, em_hints,
+ -1);
+ nma_eap_unref (NMA_EAP (em_hints));
+ active = item;
+ item++;
+ } else if (default_method && !strcmp (default_method, "external")) {
+ NMAEapSimple *em_extern;
+ const char *empty_hints[] = { NULL };
+
+ em_extern = nma_eap_simple_new (self, self->connection, NMA_EAP_SIMPLE_TYPE_UNKNOWN,
+ simple_flags, empty_hints);
+ gtk_list_store_append (auth_model, &iter);
+ gtk_list_store_set (auth_model, &iter,
+ AUTH_NAME_COLUMN, _("Externally configured"),
+ AUTH_METHOD_COLUMN, em_extern,
+ -1);
+ nma_eap_unref (NMA_EAP (em_extern));
+ active = item;
+ item++;
+ }
+
+ gtk_combo_box_set_model (GTK_COMBO_BOX (self->eap_auth_combo), GTK_TREE_MODEL (auth_model));
+ g_object_unref (G_OBJECT (auth_model));
+ gtk_combo_box_set_active (GTK_COMBO_BOX (self->eap_auth_combo), active < 0 ? 0 : (guint32) active);
+
+ if (self->secrets_only) {
+ gtk_widget_hide (self->eap_auth_combo);
+ gtk_widget_hide (self->eap_auth_label);
+ }
+
+ G_OBJECT_CLASS (nma_ws_802_1x_parent_class)->constructed (object);
+}
+
+NMAWs8021x *
+nma_ws_802_1x_new (NMConnection *connection, gboolean secrets_only)
+{
+ return g_object_new (NMA_TYPE_WS_802_1X,
+ "connection", connection,
+ "secrets-only", secrets_only,
+ NULL);
+}
+
+static void
+dispose (GObject *object)
+{
+ NMAWs8021x *self = NMA_WS_802_1X (object);
+
+ g_clear_object (&self->connection);
+ g_clear_pointer (&self->secrets_hints, g_strfreev);
+ g_clear_pointer (&self->username, g_free);
+ g_clear_pointer (&self->password, g_free);
+}
+
+static void
+nma_ws_802_1x_class_init (NMAWs8021xClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->get_property = get_property;
+ object_class->set_property = set_property;
+ object_class->constructed = constructed;
+ object_class->dispose = dispose;
+
+ g_object_class_override_property (object_class,
+ PROP_CONNECTION, "connection");
+
+ g_object_class_override_property (object_class,
+ PROP_SECRETS_ONLY, "secrets-only");
+
+ g_object_class_install_property
+ (object_class, PROP_IS_EDITOR,
+ g_param_spec_boolean ("is-editor", "", "",
+ FALSE,
+ G_PARAM_READWRITE
+ | G_PARAM_CONSTRUCT
+ | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property
+ (object_class, PROP_SECRETS_HINTS,
+ g_param_spec_boxed ("secrets-hints", "", "",
+ G_TYPE_STRV,
+ G_PARAM_READWRITE
+ | G_PARAM_CONSTRUCT
+ | G_PARAM_STATIC_STRINGS));
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/libnma/nma-ws-802-1x.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, NMAWs8021x, eap_auth_combo);
+ gtk_widget_class_bind_template_child (widget_class, NMAWs8021x, eap_auth_label);
+ gtk_widget_class_bind_template_child (widget_class, NMAWs8021x, eap_vbox);
+
+ gtk_widget_class_bind_template_callback (widget_class, auth_combo_changed_cb);
+}
diff --git a/src/nma-ws/nma-ws-802-1x.h b/src/nma-ws/nma-ws-802-1x.h
new file mode 100644
index 00000000..ed330778
--- /dev/null
+++ b/src/nma-ws/nma-ws-802-1x.h
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+
+#ifndef NMA_WS_802_1X_H
+#define NMA_WS_802_1X_H
+
+#include "nma-version.h"
+
+G_BEGIN_DECLS
+
+typedef struct _NMAWs8021xClass NMAWs8021xClass;
+typedef struct _NMAWs8021x NMAWs8021x;
+
+#define NMA_TYPE_WS_802_1X (nma_ws_802_1x_get_type ())
+#define NMA_WS_802_1X(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMA_TYPE_WS_802_1X, NMAWs8021x))
+#define NMA_WS_802_1X_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NMA_TYPE_WS_802_1X,
NMAWs8021xClass))
+#define NMA_IS_WS_802_1X(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NMA_TYPE_WS_802_1X))
+#define NMA_IS_WS_802_1X_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NMA_TYPE_WS_802_1X))
+#define NMA_WS_802_1X_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NMA_TYPE_WS_802_1X,
NMAWs8021xClass))
+
+NMA_AVAILABLE_IN_1_8_28
+GType nma_ws_802_1x_get_type (void);
+
+NMA_AVAILABLE_IN_1_8_28
+NMAWs8021x *nma_ws_802_1x_new (NMConnection *connection, gboolean secrets_only);
+
+G_END_DECLS
+
+#endif /* NMA_WS_802_1X_H */
diff --git a/src/nma-ws/nma-ws-802-1x.ui b/src/nma-ws/nma-ws-802-1x.ui
new file mode 100644
index 00000000..74233203
--- /dev/null
+++ b/src/nma-ws/nma-ws-802-1x.ui
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="nm-applet">
+ <requires lib="gtk+" version="3.10"/>
+ <object class="GtkListStore" id="model5">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0"> </col>
+ </row>
+ </data>
+ </object>
+ <template class="NMAWs8021x" parent="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="eap_auth_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Au_thentication</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">eap_auth_combo</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="eap_auth_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="model">model5</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer5"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ <signal name="changed" handler="auth_combo_changed_cb" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="eap_vbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ </template>
+</interface>
diff --git a/src/nma-ws/nma-ws-dynamic-wep.c b/src/nma-ws/nma-ws-dynamic-wep.c
new file mode 100644
index 00000000..911d7db6
--- /dev/null
+++ b/src/nma-ws/nma-ws-dynamic-wep.c
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Dan Williams <dcbw redhat com>
+ *
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+#include "nm-default.h"
+#include "nma-private.h"
+
+#include "nma-ws.h"
+#include "nma-ws-private.h"
+#include "nma-ws-802-1x.h"
+#include "nma-ws-802-1x-private.h"
+#include "nma-ws-dynamic-wep.h"
+
+typedef struct {
+ NMAWs8021xClass parent;
+} NMAWsDynamicWepClass;
+
+struct _NMAWsDynamicWep {
+ NMAWs8021x parent;
+};
+
+static void nma_ws_interface_init (NMAWsInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (NMAWsDynamicWep, nma_ws_dynamic_wep, NMA_TYPE_WS_802_1X,
+ G_IMPLEMENT_INTERFACE (NMA_TYPE_WS, nma_ws_interface_init))
+
+static void
+fill_connection (NMAWs *ws, NMConnection *connection)
+{
+ NMSettingWirelessSecurity *s_wireless_sec;
+
+ nma_ws_802_1x_fill_connection (ws, connection);
+
+ s_wireless_sec = nm_connection_get_setting_wireless_security (connection);
+ g_return_if_fail (s_wireless_sec);
+
+ g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", NULL);
+}
+
+static void
+nma_ws_dynamic_wep_init (NMAWsDynamicWep *self)
+{
+}
+
+static void
+nma_ws_interface_init (NMAWsInterface *iface)
+{
+ iface->fill_connection = fill_connection;
+}
+
+NMAWsDynamicWep *
+nma_ws_dynamic_wep_new (NMConnection *connection,
+ gboolean is_editor,
+ gboolean secrets_only)
+{
+ return g_object_new (NMA_TYPE_WS_DYNAMIC_WEP,
+ "connection", connection,
+ "secrets-only", secrets_only,
+ "is-editor", is_editor,
+ NULL);
+}
+
+static void
+nma_ws_dynamic_wep_class_init (NMAWsDynamicWepClass *klass)
+{
+}
diff --git a/src/nma-ws/nma-ws-dynamic-wep.h b/src/nma-ws/nma-ws-dynamic-wep.h
new file mode 100644
index 00000000..9057c52c
--- /dev/null
+++ b/src/nma-ws/nma-ws-dynamic-wep.h
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Dan Williams <dcbw redhat com>
+ *
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+
+#ifndef NMA_WS_DYNAMIC_WEP_H
+#define NMA_WS_DYNAMIC_WEP_H
+
+#include "nma-version.h"
+
+G_BEGIN_DECLS
+
+typedef struct _NMAWsDynamicWep NMAWsDynamicWep;
+
+#define NMA_TYPE_WS_DYNAMIC_WEP (nma_ws_dynamic_wep_get_type ())
+#define NMA_WS_DYNAMIC_WEP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMA_TYPE_WS_SAE,
NMAWsDynamicWep))
+#define NMA_WS_DYNAMIC_WEP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NMA_TYPE_WS_SAE,
NMAWsDynamicWepClass))
+#define NMA_IS_WS_DYNAMIC_WEP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NMA_TYPE_WS_SAE))
+#define NMA_IS_WS_DYNAMIC_WEP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NMA_TYPE_WS_SAE))
+#define NMA_WS_DYNAMIC_WEP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NMA_TYPE_WS_SAE,
NMAWsDynamicWepClass))
+
+NMA_AVAILABLE_IN_1_8_28
+GType nma_ws_dynamic_wep_get_type (void);
+
+NMA_AVAILABLE_IN_1_8_28
+NMAWsDynamicWep *nma_ws_dynamic_wep_new (NMConnection *connection,
+ gboolean is_editor,
+ gboolean secrets_only);
+
+G_END_DECLS
+
+#endif /* NMA_WS_DYNAMIC_WEP_H */
diff --git a/src/nma-ws/nma-ws-helpers.c b/src/nma-ws/nma-ws-helpers.c
new file mode 100644
index 00000000..d517ae38
--- /dev/null
+++ b/src/nma-ws/nma-ws-helpers.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Dan Williams <dcbw redhat com>
+ *
+ * Copyright 2009 - 2019 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+#include "nma-private.h"
+#include "nma-ws-helpers.h"
+
+void
+nma_ws_helper_fill_secret_entry (NMConnection *connection,
+ GtkEditable *entry,
+ GType setting_type,
+ HelperSecretFunc func)
+{
+ NMSetting *setting;
+ const char *tmp;
+
+ g_return_if_fail (connection != NULL);
+ g_return_if_fail (entry != NULL);
+ g_return_if_fail (func != NULL);
+
+ setting = nm_connection_get_setting (connection, setting_type);
+ if (setting) {
+ tmp = (*func) (setting);
+ if (tmp)
+ gtk_editable_set_text (entry, tmp);
+ }
+}
diff --git a/src/nma-ws/nma-ws-helpers.h b/src/nma-ws/nma-ws-helpers.h
new file mode 100644
index 00000000..3f842646
--- /dev/null
+++ b/src/nma-ws/nma-ws-helpers.h
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Dan Williams <dcbw redhat com>
+ *
+ * Copyright 2009 - 2019 Red Hat, Inc.
+ */
+
+#ifndef _NMA_WS_HELPERS_H_
+#define _NMA_WS_HELPERS_H_
+
+typedef const char * (*HelperSecretFunc)(NMSetting *);
+
+void nma_ws_helper_fill_secret_entry (NMConnection *connection,
+ GtkEditable *entry,
+ GType setting_type,
+ HelperSecretFunc func);
+
+#endif /* _NMA_WS_HELPERS_H_ */
diff --git a/src/nma-ws/nma-ws-leap.c b/src/nma-ws/nma-ws-leap.c
new file mode 100644
index 00000000..ef2cf8bf
--- /dev/null
+++ b/src/nma-ws/nma-ws-leap.c
@@ -0,0 +1,293 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Dan Williams <dcbw redhat com>
+ *
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+#include "nma-private.h"
+
+#include <ctype.h>
+#include <string.h>
+
+#include "nma-ws.h"
+#include "nma-ws-private.h"
+#include "nma-ws-leap.h"
+#include "nma-ws-helpers.h"
+#include "nma-ui-utils.h"
+#include "utils.h"
+
+typedef struct {
+ GtkGridClass parent;
+} NMAWsLeapClass;
+
+struct _NMAWsLeap {
+ GtkGrid parent;
+
+ GtkWidget *leap_username_entry;
+ GtkWidget *leap_password_entry;
+ GtkWidget *leap_username_label;
+ GtkWidget *leap_password_label;
+ GtkWidget *show_checkbutton_leap;
+
+ NMConnection *connection;
+ gboolean secrets_only;
+};
+
+static void nma_ws_interface_init (NMAWsInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (NMAWsLeap, nma_ws_leap, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (NMA_TYPE_WS, nma_ws_interface_init))
+
+enum {
+ PROP_0,
+ PROP_CONNECTION,
+ PROP_SECRETS_ONLY,
+ PROP_LAST
+};
+
+static void
+show_toggled_cb (GtkCheckButton *button, gpointer user_data)
+{
+ NMAWsLeap *self = NMA_WS_LEAP (user_data);
+ gboolean visible;
+
+ visible = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+ gtk_entry_set_visibility (GTK_ENTRY (self->leap_password_entry), visible);
+}
+
+static gboolean
+validate (NMAWs *ws, GError **error)
+{
+ NMAWsLeap *self = NMA_WS_LEAP (ws);
+ NMSettingSecretFlags secret_flags;
+ const char *text;
+ gboolean ret = TRUE;
+
+ text = gtk_editable_get_text (GTK_EDITABLE (self->leap_username_entry));
+ if (!text || !strlen (text)) {
+ widget_set_error (self->leap_username_entry);
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("missing leap-username"));
+ ret = FALSE;
+ } else {
+ widget_unset_error (self->leap_username_entry);
+ }
+
+ secret_flags = nma_utils_menu_to_secret_flags (self->leap_password_entry);
+ text = gtk_editable_get_text (GTK_EDITABLE (self->leap_password_entry));
+
+ if ( secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED
+ || secret_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED
+ || (text && strlen (text))) {
+ widget_unset_error (self->leap_password_entry);
+ } else {
+ widget_set_error (self->leap_password_entry);
+ if (ret) {
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("missing leap-password"));
+ ret = FALSE;
+ }
+ }
+
+ return ret;
+}
+
+static void
+add_to_size_group (NMAWs *ws, GtkSizeGroup *group)
+{
+ NMAWsLeap *self = NMA_WS_LEAP (ws);
+
+ gtk_size_group_add_widget (group, self->leap_username_label);
+ gtk_size_group_add_widget (group, self->leap_password_label);
+}
+
+static void
+fill_connection (NMAWs *ws, NMConnection *connection)
+{
+ NMAWsLeap *self = NMA_WS_LEAP (ws);
+ NMSettingWirelessSecurity *s_wireless_sec;
+ NMSettingSecretFlags secret_flags;
+ const char *leap_password = NULL, *leap_username = NULL;
+
+ /* 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);
+
+ leap_username = gtk_editable_get_text (GTK_EDITABLE (self->leap_username_entry));
+ leap_password = gtk_editable_get_text (GTK_EDITABLE (self->leap_password_entry));
+
+ g_object_set (s_wireless_sec,
+ NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x",
+ NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "leap",
+ NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, leap_username,
+ NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD, leap_password,
+ NULL);
+
+ /* Save LEAP_PASSWORD_FLAGS to the connection */
+ secret_flags = nma_utils_menu_to_secret_flags (self->leap_password_entry);
+ nm_setting_set_secret_flags (NM_SETTING (s_wireless_sec), NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD,
+ secret_flags, NULL);
+
+ /* Update secret flags and popup when editing the connection */
+ if (!self->secrets_only) {
+ nma_utils_update_password_storage (self->leap_password_entry, secret_flags,
+ NM_SETTING (s_wireless_sec),
+ NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD);
+ }
+}
+
+static void
+update_secrets (NMAWs *ws, NMConnection *connection)
+{
+ NMAWsLeap *self = NMA_WS_LEAP (ws);
+
+ nma_ws_helper_fill_secret_entry (connection,
+ GTK_EDITABLE (self->leap_password_entry),
+ NM_TYPE_SETTING_WIRELESS_SECURITY,
+ (HelperSecretFunc) nm_setting_wireless_security_get_leap_password);
+}
+
+static void
+get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ NMAWsLeap *self = NMA_WS_LEAP (object);
+
+ switch (prop_id) {
+ case PROP_CONNECTION:
+ g_value_set_object (value, self->connection);
+ break;
+ case PROP_SECRETS_ONLY:
+ g_value_set_boolean (value, self->secrets_only);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ NMAWsLeap *self = NMA_WS_LEAP (object);
+
+ switch (prop_id) {
+ case PROP_CONNECTION:
+ self->connection = g_value_dup_object (value);
+ break;
+ case PROP_SECRETS_ONLY:
+ self->secrets_only = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nma_ws_leap_init (NMAWsLeap *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static void
+nma_ws_interface_init (NMAWsInterface *iface)
+{
+ iface->validate = validate;
+ iface->add_to_size_group = add_to_size_group;
+ iface->fill_connection = fill_connection;
+ iface->update_secrets = update_secrets;
+ iface->adhoc_compatible = FALSE;
+ iface->hotspot_compatible = FALSE;
+}
+
+static void
+constructed (GObject *object)
+{
+ NMAWsLeap *self = NMA_WS_LEAP (object);
+ NMSettingWirelessSecurity *wsec = NULL;
+
+ if (self->connection) {
+ wsec = nm_connection_get_setting_wireless_security (self->connection);
+ if (wsec) {
+ const char *auth_alg;
+
+ /* Ignore if wireless security doesn't specify LEAP */
+ auth_alg = nm_setting_wireless_security_get_auth_alg (wsec);
+ if (!auth_alg || strcmp (auth_alg, "leap"))
+ wsec = NULL;
+ }
+ }
+
+ /* Create password-storage popup menu for password entry under entry's secondary icon */
+ nma_utils_setup_password_storage (self->leap_password_entry, 0, (NMSetting *) wsec,
+ NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD,
+ FALSE, self->secrets_only);
+
+ if (wsec) {
+ update_secrets (NMA_WS (self), self->connection);
+ gtk_editable_set_text (GTK_EDITABLE (self->leap_username_entry),
+ nm_setting_wireless_security_get_leap_username (wsec));
+ }
+
+ if (self->secrets_only) {
+ gtk_widget_hide (self->leap_username_label);
+ gtk_widget_hide (self->leap_username_entry);
+ }
+
+ gtk_widget_grab_focus (self->leap_password_entry);
+
+ G_OBJECT_CLASS (nma_ws_leap_parent_class)->constructed (object);
+}
+
+NMAWsLeap *
+nma_ws_leap_new (NMConnection *connection, gboolean secrets_only)
+{
+ return g_object_new (NMA_TYPE_WS_LEAP,
+ "connection", connection,
+ "secrets-only", secrets_only,
+ NULL);
+}
+
+static void
+dispose (GObject *object)
+{
+ NMAWsLeap *self = NMA_WS_LEAP (object);
+
+ g_clear_object (&self->connection);
+}
+
+static void
+nma_ws_leap_class_init (NMAWsLeapClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->get_property = get_property;
+ object_class->set_property = set_property;
+ object_class->constructed = constructed;
+ object_class->dispose = dispose;
+
+ g_object_class_override_property (object_class,
+ PROP_CONNECTION, "connection");
+
+ g_object_class_override_property (object_class,
+ PROP_SECRETS_ONLY, "secrets-only");
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/libnma/nma-ws-leap.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, NMAWsLeap, leap_username_entry);
+ gtk_widget_class_bind_template_child (widget_class, NMAWsLeap, leap_password_entry);
+ gtk_widget_class_bind_template_child (widget_class, NMAWsLeap, leap_username_label);
+ gtk_widget_class_bind_template_child (widget_class, NMAWsLeap, leap_password_label);
+ gtk_widget_class_bind_template_child (widget_class, NMAWsLeap, show_checkbutton_leap);
+
+ gtk_widget_class_bind_template_callback (widget_class, nma_ws_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, show_toggled_cb);
+}
diff --git a/src/nma-ws/nma-ws-leap.h b/src/nma-ws/nma-ws-leap.h
new file mode 100644
index 00000000..0f99bc12
--- /dev/null
+++ b/src/nma-ws/nma-ws-leap.h
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Dan Williams <dcbw redhat com>
+ *
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+
+#ifndef NMA_WS_LEAP_H
+#define NMA_WS_LEAP_H
+
+#include "nma-version.h"
+
+G_BEGIN_DECLS
+
+typedef struct _NMAWsLeap NMAWsLeap;
+
+#define NMA_TYPE_WS_LEAP (nma_ws_leap_get_type ())
+#define NMA_WS_LEAP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMA_TYPE_WS_LEAP, NMAWsLeap))
+#define NMA_WS_LEAP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NMA_TYPE_WS_LEAP, NMAWsLeapClass))
+#define NMA_IS_WS_LEAP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NMA_TYPE_WS_LEAP))
+#define NMA_IS_WS_LEAP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NMA_TYPE_WS_LEAP))
+#define NMA_WS_LEAP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NMA_TYPE_WS_LEAP, NMAWsLeapClass))
+
+NMA_AVAILABLE_IN_1_8_28
+GType nma_ws_leap_get_type (void);
+
+NMA_AVAILABLE_IN_1_8_28
+NMAWsLeap *nma_ws_leap_new (NMConnection *connection, gboolean secrets_only);
+
+G_END_DECLS
+
+#endif /* NMA_WS_LEAP_H */
diff --git a/src/nma-ws/nma-ws-leap.ui b/src/nma-ws/nma-ws-leap.ui
new file mode 100644
index 00000000..da44a23b
--- /dev/null
+++ b/src/nma-ws/nma-ws-leap.ui
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="nm-applet">
+ <requires lib="gtk+" version="3.10"/>
+ <template class="NMAWsLeap" parent="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">start</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="leap_username_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Username</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">leap_username_entry</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="leap_password_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Password</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">leap_password_entry</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="leap_password_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="visibility">False</property>
+ <property name="activates_default">True</property>
+ <signal name="changed" handler="nma_ws_changed_cb" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="show_checkbutton_leap">
+ <property name="label" translatable="yes">Sho_w password</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="show_toggled_cb" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="leap_username_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <signal name="changed" handler="nma_ws_changed_cb" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </template>
+</interface>
diff --git a/src/nma-ws/nma-ws-private.h b/src/nma-ws/nma-ws-private.h
new file mode 100644
index 00000000..63bb97f2
--- /dev/null
+++ b/src/nma-ws/nma-ws-private.h
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Dan Williams <dcbw redhat com>
+ *
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+
+#ifndef NMA_WS_PRIVATE_H
+#define NMA_WS_PRIVATE_H
+
+typedef struct {
+ GTypeInterface parent;
+
+ void (*add_to_size_group) (NMAWs *self, GtkSizeGroup *group);
+ void (*fill_connection) (NMAWs *self, NMConnection *connection);
+ void (*update_secrets) (NMAWs *self, NMConnection *connection);
+ gboolean (*validate) (NMAWs *self, GError **error);
+
+ gboolean adhoc_compatible;
+ gboolean hotspot_compatible;
+} NMAWsInterface;
+
+void nma_ws_changed_cb (GtkWidget *entry, gpointer user_data);
+
+void nma_ws_clear_ciphers (NMConnection *connection);
+
+#endif /* NMA_WS_PRIVATE_H */
diff --git a/src/nma-ws/nma-ws-sae.c b/src/nma-ws/nma-ws-sae.c
new file mode 100644
index 00000000..a697b7c0
--- /dev/null
+++ b/src/nma-ws/nma-ws-sae.c
@@ -0,0 +1,285 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+#include "nma-private.h"
+
+#include <ctype.h>
+#include <string.h>
+
+#include "nma-ws.h"
+#include "nma-ws-private.h"
+#include "nma-ws-sae.h"
+#include "nma-ws-helpers.h"
+#include "nma-ui-utils.h"
+#include "utils.h"
+
+typedef struct {
+ GtkGridClass parent;
+} NMAWsSaeClass;
+
+struct _NMAWsSae {
+ GtkGrid parent;
+
+ GtkWidget *psk_entry;
+ GtkWidget *sae_label;
+ GtkWidget *sae_type_combo;
+ GtkWidget *sae_type_label;
+ GtkWidget *show_checkbutton_sae;
+
+ NMConnection *connection;
+ gboolean secrets_only;
+};
+
+static void nma_ws_interface_init (NMAWsInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (NMAWsSae, nma_ws_sae, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (NMA_TYPE_WS, nma_ws_interface_init))
+
+enum {
+ PROP_0,
+ PROP_CONNECTION,
+ PROP_SECRETS_ONLY,
+ PROP_LAST
+};
+
+static void
+show_toggled_cb (GtkCheckButton *button, gpointer user_data)
+{
+ NMAWsSae *self = NMA_WS_SAE (user_data);
+ gboolean visible;
+
+ visible = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+ gtk_entry_set_visibility (GTK_ENTRY (self->psk_entry), visible);
+}
+
+static gboolean
+validate (NMAWs *ws, GError **error)
+{
+ NMAWsSae *self = NMA_WS_SAE (ws);
+ NMSettingSecretFlags secret_flags;
+ const char *key;
+
+ secret_flags = nma_utils_menu_to_secret_flags (self->psk_entry);
+ key = gtk_editable_get_text (GTK_EDITABLE (self->psk_entry));
+
+ if ( secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED
+ || secret_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED) {
+ /* All good. */
+ } else if (key == NULL || key[0] == '\0') {
+ widget_set_error (self->psk_entry);
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("missing password"));
+ return FALSE;
+ }
+ widget_unset_error (self->psk_entry);
+
+ return TRUE;
+}
+
+static void
+add_to_size_group (NMAWs *ws, GtkSizeGroup *group)
+{
+ NMAWsSae *self = NMA_WS_SAE (ws);
+
+ gtk_size_group_add_widget (group, self->sae_type_label);
+ gtk_size_group_add_widget (group, self->sae_label);
+}
+
+static void
+fill_connection (NMAWs *ws, NMConnection *connection)
+{
+ NMAWsSae *self = NMA_WS_SAE (ws);
+ 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_return_if_fail (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_editable_get_text (GTK_EDITABLE (self->psk_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 (self->psk_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 */
+ if (!self->secrets_only) {
+ nma_utils_update_password_storage (self->psk_entry, secret_flags,
+ NM_SETTING (s_wireless_sec),
+ NM_SETTING_WIRELESS_SECURITY_PSK);
+ }
+
+ nma_ws_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 void
+update_secrets (NMAWs *ws, NMConnection *connection)
+{
+ NMAWsSae *self = NMA_WS_SAE (ws);
+
+ nma_ws_helper_fill_secret_entry (connection,
+ GTK_EDITABLE (self->psk_entry),
+ NM_TYPE_SETTING_WIRELESS_SECURITY,
+ (HelperSecretFunc) nm_setting_wireless_security_get_psk);
+}
+
+static void
+get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ NMAWsSae *self = NMA_WS_SAE (object);
+
+ switch (prop_id) {
+ case PROP_CONNECTION:
+ g_value_set_object (value, self->connection);
+ break;
+ case PROP_SECRETS_ONLY:
+ g_value_set_boolean (value, self->secrets_only);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ NMAWsSae *self = NMA_WS_SAE (object);
+
+ switch (prop_id) {
+ case PROP_CONNECTION:
+ self->connection = g_value_dup_object (value);
+ break;
+ case PROP_SECRETS_ONLY:
+ self->secrets_only = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nma_ws_sae_init (NMAWsSae *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static void
+nma_ws_interface_init (NMAWsInterface *iface)
+{
+ iface->validate = validate;
+ iface->add_to_size_group = add_to_size_group;
+ iface->fill_connection = fill_connection;
+ iface->update_secrets = update_secrets;
+ iface->adhoc_compatible = TRUE;
+ iface->hotspot_compatible = TRUE;
+}
+
+static void
+constructed (GObject *object)
+{
+ NMAWsSae *self = NMA_WS_SAE (object);
+ NMSetting *setting = NULL;
+
+ /* Create password-storage popup menu for password entry under entry's secondary icon */
+ if (self->connection)
+ setting = (NMSetting *) nm_connection_get_setting_wireless_security (self->connection);
+ nma_utils_setup_password_storage (self->psk_entry, 0, setting, NM_SETTING_WIRELESS_SECURITY_PSK,
+ FALSE, self->secrets_only);
+
+ /* Fill secrets, if any */
+ if (self->connection)
+ update_secrets (NMA_WS (self), self->connection);
+
+ gtk_widget_grab_focus (self->psk_entry);
+
+ /* Hide WPA/RSN for now since this can be autodetected by NM and the
+ * supplicant when connecting to the AP.
+ */
+ gtk_widget_hide (self->sae_type_combo);
+ gtk_widget_hide (self->sae_type_label);
+
+ G_OBJECT_CLASS (nma_ws_sae_parent_class)->constructed (object);
+}
+
+NMAWsSae *
+nma_ws_sae_new (NMConnection *connection, gboolean secrets_only)
+{
+ return g_object_new (NMA_TYPE_WS_SAE,
+ "connection", connection,
+ "secrets-only", secrets_only,
+ NULL);
+}
+
+static void
+dispose (GObject *object)
+{
+ NMAWsSae *self = NMA_WS_SAE (object);
+
+ g_clear_object (&self->connection);
+}
+
+static void
+nma_ws_sae_class_init (NMAWsSaeClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->get_property = get_property;
+ object_class->set_property = set_property;
+ object_class->constructed = constructed;
+ object_class->dispose = dispose;
+
+ g_object_class_override_property (object_class,
+ PROP_CONNECTION, "connection");
+
+ g_object_class_override_property (object_class,
+ PROP_SECRETS_ONLY, "secrets-only");
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/libnma/nma-ws-sae.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, NMAWsSae, psk_entry);
+ gtk_widget_class_bind_template_child (widget_class, NMAWsSae, sae_label);
+ gtk_widget_class_bind_template_child (widget_class, NMAWsSae, sae_type_combo);
+ gtk_widget_class_bind_template_child (widget_class, NMAWsSae, sae_type_label);
+ gtk_widget_class_bind_template_child (widget_class, NMAWsSae, show_checkbutton_sae);
+
+ gtk_widget_class_bind_template_callback (widget_class, nma_ws_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, show_toggled_cb);
+}
diff --git a/src/nma-ws/nma-ws-sae.h b/src/nma-ws/nma-ws-sae.h
new file mode 100644
index 00000000..14baad4b
--- /dev/null
+++ b/src/nma-ws/nma-ws-sae.h
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+
+#ifndef NMA_WS_SAE_H
+#define NMA_WS_SAE_H
+
+#include "nma-version.h"
+
+G_BEGIN_DECLS
+
+typedef struct _NMAWsSae NMAWsSae;
+
+#define NMA_TYPE_WS_SAE (nma_ws_sae_get_type ())
+#define NMA_WS_SAE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMA_TYPE_WS_SAE, NMAWsSae))
+#define NMA_WS_SAE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NMA_TYPE_WS_SAE, NMAWsSaeClass))
+#define NMA_IS_WS_SAE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NMA_TYPE_WS_SAE))
+#define NMA_IS_WS_SAE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NMA_TYPE_WS_SAE))
+#define NMA_WS_SAE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NMA_TYPE_WS_SAE, NMAWsSaeClass))
+
+NMA_AVAILABLE_IN_1_8_28
+GType nma_ws_sae_get_type (void);
+
+NMA_AVAILABLE_IN_1_8_28
+NMAWsSae *nma_ws_sae_new (NMConnection *connection, gboolean secrets_only);
+
+G_END_DECLS
+
+#endif /* NMA_WS_SAE_H */
diff --git a/src/nma-ws/nma-ws-sae.ui b/src/nma-ws/nma-ws-sae.ui
new file mode 100644
index 00000000..89094a18
--- /dev/null
+++ b/src/nma-ws/nma-ws-sae.ui
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="nm-applet">
+ <requires lib="gtk+" version="3.10"/>
+ <template class="NMAWsSae" parent="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="sae_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Password</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">psk_entry</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="psk_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="max_length">64</property>
+ <property name="visibility">False</property>
+ <property name="activates_default">True</property>
+ <property name="width_chars">28</property>
+ <signal name="changed" handler="nma_ws_changed_cb" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="sae_type_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Type</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">sae_type_combo</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="show_checkbutton_sae">
+ <property name="label" translatable="yes">Sho_w password</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="show_toggled_cb" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="sae_type_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </template>
+</interface>
diff --git a/src/nma-ws/nma-ws-wep-key.c b/src/nma-ws/nma-ws-wep-key.c
new file mode 100644
index 00000000..6150d282
--- /dev/null
+++ b/src/nma-ws/nma-ws-wep-key.c
@@ -0,0 +1,457 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+#include "nma-private.h"
+
+#include <ctype.h>
+#include <string.h>
+
+#include "nma-ws.h"
+#include "nma-ws-private.h"
+#include "nma-ws-wep-key.h"
+#include "nma-ws-helpers.h"
+#include "nma-ui-utils.h"
+#include "utils.h"
+
+typedef struct {
+ GtkGridClass parent;
+} NMAWsWepKeyClass;
+
+struct _NMAWsWepKey {
+ GtkGrid parent;
+
+ GtkWidget *auth_method_combo;
+ GtkWidget *auth_method_label;
+ GtkWidget *key_index_combo;
+ GtkWidget *key_index_label;
+ GtkWidget *show_checkbutton_wep;
+ GtkWidget *wep_key_entry;
+ GtkWidget *wep_key_label;
+
+ NMConnection *connection;
+ gboolean secrets_only;
+ NMWepKeyType adhoc_create;
+ NMWepKeyType key_type;
+
+ char keys[4][65];
+ guint8 cur_index;
+};
+
+static void nma_ws_interface_init (NMAWsInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (NMAWsWepKey, nma_ws_wep_key, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (NMA_TYPE_WS, nma_ws_interface_init))
+
+enum {
+ PROP_0,
+ PROP_CONNECTION,
+ PROP_SECRETS_ONLY,
+ PROP_KEY_TYPE,
+ PROP_ADHOC_CREATE,
+ PROP_LAST
+};
+
+static void
+show_toggled_cb (GtkCheckButton *button, gpointer user_data)
+{
+ NMAWsWepKey *self = NMA_WS_WEP_KEY (user_data);
+ gboolean visible;
+
+ visible = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+ gtk_entry_set_visibility (GTK_ENTRY (self->wep_key_entry), visible);
+}
+
+static void
+key_index_combo_changed_cb (GtkWidget *combo, NMAWs *ws)
+{
+ NMAWsWepKey *self = NMA_WS_WEP_KEY (ws);
+ GtkWidget *entry;
+ const char *key;
+ int key_index;
+
+ /* Save WEP key for old key index */
+ entry = GTK_WIDGET (self->wep_key_entry);
+ key = gtk_editable_get_text (GTK_EDITABLE (entry));
+ if (key)
+ g_strlcpy (self->keys[self->cur_index], key, sizeof (self->keys[self->cur_index]));
+ else
+ memset (self->keys[self->cur_index], 0, sizeof (self->keys[self->cur_index]));
+
+ key_index = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
+ g_return_if_fail (key_index <= 3);
+ g_return_if_fail (key_index >= 0);
+
+ /* Populate entry with key from new index */
+ gtk_editable_set_text (GTK_EDITABLE (entry), self->keys[key_index]);
+ self->cur_index = key_index;
+
+ nma_ws_changed_cb (combo, ws);
+}
+
+static gboolean
+validate (NMAWs *ws, GError **error)
+{
+ NMAWsWepKey *self = NMA_WS_WEP_KEY (ws);
+ NMSettingSecretFlags secret_flags;
+ const char *key;
+ int i;
+
+ secret_flags = nma_utils_menu_to_secret_flags (self->wep_key_entry);
+ key = gtk_editable_get_text (GTK_EDITABLE (self->wep_key_entry));
+
+ if ( secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED
+ || secret_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED) {
+ /* All good. */
+ } else if (!key) {
+ widget_set_error (self->wep_key_entry);
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("missing wep-key"));
+ return FALSE;
+ } else if (self->key_type == NM_WEP_KEY_TYPE_KEY) {
+ if ((strlen (key) == 10) || (strlen (key) == 26)) {
+ for (i = 0; i < strlen (key); i++) {
+ if (!g_ascii_isxdigit (key[i])) {
+ widget_set_error (self->wep_key_entry);
+ g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid wep-key:
key with a length of %zu must contain only hex-digits"), strlen (key));
+ return FALSE;
+ }
+ }
+ } else if ((strlen (key) == 5) || (strlen (key) == 13)) {
+ for (i = 0; i < strlen (key); i++) {
+ if (!utils_char_is_ascii_print (key[i])) {
+ widget_set_error (self->wep_key_entry);
+ g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid wep-key:
key with a length of %zu must contain only ascii characters"), strlen (key));
+ return FALSE;
+ }
+ }
+ } else {
+ widget_set_error (self->wep_key_entry);
+ g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid wep-key: wrong key
length %zu. A key must be either of length 5/13 (ascii) or 10/26 (hex)"), strlen (key));
+ return FALSE;
+ }
+ } else if (self->key_type == NM_WEP_KEY_TYPE_PASSPHRASE) {
+ if (!*key || (strlen (key) > 64)) {
+ widget_set_error (self->wep_key_entry);
+ if (!*key)
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid wep-key:
passphrase must be non-empty"));
+ else
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid wep-key:
passphrase must be shorter than 64 characters"));
+ return FALSE;
+ }
+ }
+ widget_unset_error (self->wep_key_entry);
+
+ return TRUE;
+}
+
+static void
+add_to_size_group (NMAWs *ws, GtkSizeGroup *group)
+{
+ NMAWsWepKey *self = NMA_WS_WEP_KEY (ws);
+
+ gtk_size_group_add_widget (group, self->auth_method_label);
+ gtk_size_group_add_widget (group, self->wep_key_label);
+ gtk_size_group_add_widget (group, self->key_index_label);
+}
+
+static void
+fill_connection (NMAWs *ws, NMConnection *connection)
+{
+ NMAWsWepKey *self = NMA_WS_WEP_KEY (ws);
+ NMSettingWirelessSecurity *s_wsec;
+ NMSettingSecretFlags secret_flags;
+ int auth_alg;
+ const char *key;
+ int i;
+
+ auth_alg = gtk_combo_box_get_active (GTK_COMBO_BOX (self->auth_method_combo));
+ key = gtk_editable_get_text (GTK_EDITABLE (self->wep_key_entry));
+ g_strlcpy (self->keys[self->cur_index], key, sizeof (self->keys[self->cur_index]));
+
+ /* Blow away the old security setting by adding a clear one */
+ s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+ nm_connection_add_setting (connection, (NMSetting *) s_wsec);
+
+ g_object_set (s_wsec,
+ NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none",
+ NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX, self->cur_index,
+ NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, (auth_alg == 1) ? "shared" : "open",
+ NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, self->key_type,
+ NULL);
+
+ for (i = 0; i < 4; i++) {
+ if (strlen (self->keys[i]))
+ nm_setting_wireless_security_set_wep_key (s_wsec, i, self->keys[i]);
+ }
+
+ /* Save WEP_KEY_FLAGS to the connection */
+ secret_flags = nma_utils_menu_to_secret_flags (self->wep_key_entry);
+ g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, secret_flags, NULL);
+
+ /* Update secret flags and popup when editing the connection */
+ if (!self->secrets_only) {
+ nma_utils_update_password_storage (self->wep_key_entry, secret_flags,
+ NM_SETTING (s_wsec),
+ NM_SETTING_WIRELESS_SECURITY_WEP_KEY0);
+ }
+}
+
+static void
+wep_entry_filter_cb (GtkEditable *editable,
+ char *text,
+ int length,
+ int *position,
+ gpointer data)
+{
+ NMAWsWepKey *self = NMA_WS_WEP_KEY (data);
+
+ if (self->key_type == NM_WEP_KEY_TYPE_KEY) {
+ utils_filter_editable_on_insert_text (editable,
+ text, length, position, data,
+ utils_char_is_ascii_print,
+ wep_entry_filter_cb);
+ }
+}
+
+
+static void
+update_secrets (NMAWs *ws, NMConnection *connection)
+{
+ NMAWsWepKey *self = NMA_WS_WEP_KEY (ws);
+ NMSettingWirelessSecurity *s_wsec;
+ const char *tmp;
+ int i;
+
+ s_wsec = nm_connection_get_setting_wireless_security (connection);
+ for (i = 0; s_wsec && i < 4; i++) {
+ tmp = nm_setting_wireless_security_get_wep_key (s_wsec, i);
+ if (tmp)
+ g_strlcpy (self->keys[i], tmp, sizeof (self->keys[i]));
+ }
+
+ if (strlen (self->keys[self->cur_index])) {
+ gtk_editable_set_text (GTK_EDITABLE (self->wep_key_entry),
+ self->keys[self->cur_index]);
+ }
+}
+
+
+static void
+get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ NMAWsWepKey *self = NMA_WS_WEP_KEY (object);
+
+ switch (prop_id) {
+ case PROP_CONNECTION:
+ g_value_set_object (value, self->connection);
+ break;
+ case PROP_SECRETS_ONLY:
+ g_value_set_boolean (value, self->secrets_only);
+ break;
+ case PROP_KEY_TYPE:
+ g_value_set_uint (value, self->key_type);
+ break;
+ case PROP_ADHOC_CREATE:
+ g_value_set_boolean (value, self->adhoc_create);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ NMAWsWepKey *self = NMA_WS_WEP_KEY (object);
+
+ switch (prop_id) {
+ case PROP_CONNECTION:
+ self->connection = g_value_dup_object (value);
+ break;
+ case PROP_SECRETS_ONLY:
+ self->secrets_only = g_value_get_boolean (value);
+ break;
+ case PROP_KEY_TYPE:
+ self->key_type = g_value_get_uint (value);
+ break;
+ case PROP_ADHOC_CREATE:
+ self->adhoc_create = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nma_ws_wep_key_init (NMAWsWepKey *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static void
+nma_ws_interface_init (NMAWsInterface *iface)
+{
+ iface->validate = validate;
+ iface->add_to_size_group = add_to_size_group;
+ iface->fill_connection = fill_connection;
+ iface->update_secrets = update_secrets;
+ iface->adhoc_compatible = TRUE;
+ iface->hotspot_compatible = TRUE;
+}
+
+static void
+constructed (GObject *object)
+{
+ NMAWsWepKey *self = NMA_WS_WEP_KEY (object);
+ NMSettingWirelessSecurity *s_wsec = NULL;
+ NMSetting *setting = NULL;
+ guint8 default_key_idx = 0;
+ gboolean is_adhoc = self->adhoc_create;
+ gboolean is_shared_key = FALSE;
+
+
+ /* Create password-storage popup menu for password entry under entry's secondary icon */
+ if (self->connection)
+ setting = (NMSetting *) nm_connection_get_setting_wireless_security (self->connection);
+ nma_utils_setup_password_storage (self->wep_key_entry, 0, setting,
+ NM_SETTING_WIRELESS_SECURITY_WEP_KEY0,
+ FALSE, self->secrets_only);
+
+ if (self->connection) {
+ NMSettingWireless *s_wireless;
+ const char *mode, *auth_alg;
+
+ s_wireless = nm_connection_get_setting_wireless (self->connection);
+ mode = s_wireless ? nm_setting_wireless_get_mode (s_wireless) : NULL;
+ if (mode && !strcmp (mode, "adhoc"))
+ is_adhoc = TRUE;
+
+ s_wsec = nm_connection_get_setting_wireless_security (self->connection);
+ if (s_wsec) {
+ auth_alg = nm_setting_wireless_security_get_auth_alg (s_wsec);
+ if (auth_alg && !strcmp (auth_alg, "shared"))
+ is_shared_key = TRUE;
+ }
+ }
+
+ if (self->key_type == NM_WEP_KEY_TYPE_KEY)
+ gtk_entry_set_max_length (GTK_ENTRY (self->wep_key_entry), 26);
+ else if (self->key_type == NM_WEP_KEY_TYPE_PASSPHRASE)
+ gtk_entry_set_max_length (GTK_ENTRY (self->wep_key_entry), 64);
+
+ if (self->connection && s_wsec)
+ default_key_idx = nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec);
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (self->key_index_combo), default_key_idx);
+ self->cur_index = default_key_idx;
+
+ /* Key index is useless with adhoc networks */
+ if (is_adhoc || self->secrets_only) {
+ gtk_widget_hide (self->key_index_combo);
+ gtk_widget_hide (self->key_index_label);
+ }
+
+ /* Fill the key entry with the key for that index */
+ if (self->connection)
+ update_secrets (NMA_WS (self), self->connection);
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (self->auth_method_combo),
+ is_shared_key ? 1 : 0);
+
+ /* Don't show auth method for adhoc (which always uses open-system) or
+ * when in "simple" mode.
+ */
+ if (is_adhoc || self->secrets_only) {
+ /* Ad-Hoc connections can't use Shared Key auth */
+ if (is_adhoc)
+ gtk_combo_box_set_active (GTK_COMBO_BOX (self->auth_method_combo), 0);
+ gtk_widget_hide (self->auth_method_combo);
+ gtk_widget_hide (self->auth_method_label);
+ }
+
+ gtk_widget_grab_focus (self->wep_key_entry);
+
+ G_OBJECT_CLASS (nma_ws_wep_key_parent_class)->constructed (object);
+}
+
+NMAWsWepKey *
+nma_ws_wep_key_new (NMConnection *connection,
+ NMWepKeyType key_type,
+ gboolean adhoc_create,
+ gboolean secrets_only)
+{
+ return g_object_new (NMA_TYPE_WS_WEP_KEY,
+ "connection", connection,
+ "key-type", key_type,
+ "adhoc-create", adhoc_create,
+ "secrets-only", secrets_only,
+ NULL);
+}
+
+static void
+dispose (GObject *object)
+{
+ NMAWsWepKey *self = NMA_WS_WEP_KEY (object);
+
+ g_clear_object (&self->connection);
+}
+
+static void
+nma_ws_wep_key_class_init (NMAWsWepKeyClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->get_property = get_property;
+ object_class->set_property = set_property;
+ object_class->constructed = constructed;
+ object_class->dispose = dispose;
+
+ g_object_class_override_property (object_class,
+ PROP_CONNECTION, "connection");
+
+ g_object_class_override_property (object_class,
+ PROP_SECRETS_ONLY, "secrets-only");
+
+ g_object_class_install_property
+ (object_class, PROP_KEY_TYPE,
+ g_param_spec_uint ("key-type", "", "",
+ 0, G_MAXUINT, 0,
+ G_PARAM_READWRITE
+ | G_PARAM_CONSTRUCT
+ | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property
+ (object_class, PROP_ADHOC_CREATE,
+ g_param_spec_boolean ("adhoc-create", "", "",
+ FALSE,
+ G_PARAM_READWRITE
+ | G_PARAM_CONSTRUCT
+ | G_PARAM_STATIC_STRINGS));
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/libnma/nma-ws-wep-key.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, NMAWsWepKey, auth_method_combo);
+ gtk_widget_class_bind_template_child (widget_class, NMAWsWepKey, auth_method_label);
+ gtk_widget_class_bind_template_child (widget_class, NMAWsWepKey, key_index_combo);
+ gtk_widget_class_bind_template_child (widget_class, NMAWsWepKey, key_index_label);
+ gtk_widget_class_bind_template_child (widget_class, NMAWsWepKey, show_checkbutton_wep);
+ gtk_widget_class_bind_template_child (widget_class, NMAWsWepKey, wep_key_entry);
+ gtk_widget_class_bind_template_child (widget_class, NMAWsWepKey, wep_key_label);
+
+ gtk_widget_class_bind_template_callback (widget_class, key_index_combo_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, nma_ws_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, show_toggled_cb);
+ gtk_widget_class_bind_template_callback (widget_class, wep_entry_filter_cb);
+}
diff --git a/src/nma-ws/nma-ws-wep-key.h b/src/nma-ws/nma-ws-wep-key.h
new file mode 100644
index 00000000..308f975c
--- /dev/null
+++ b/src/nma-ws/nma-ws-wep-key.h
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Dan Williams <dcbw redhat com>
+ *
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+
+#ifndef NMA_WS_WEP_KEY_H
+#define NMA_WS_WEP_KEY_H
+
+#include "nma-version.h"
+
+G_BEGIN_DECLS
+
+typedef struct _NMAWsWepKey NMAWsWepKey;
+
+#define NMA_TYPE_WS_WEP_KEY (nma_ws_wep_key_get_type ())
+#define NMA_WS_WEP_KEY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMA_TYPE_WS_WEP_KEY, NMAWsWepKey))
+#define NMA_WS_WEP_KEY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NMA_TYPE_WS_WEP_KEY,
NMAWsWepKeyClass))
+#define NMA_IS_WS_WEP_KEY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NMA_TYPE_WS_WEP_KEY))
+#define NMA_IS_WS_WEP_KEY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NMA_TYPE_WS_WEP_KEY))
+#define NMA_WS_WEP_KEY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NMA_TYPE_WS_WEP_KEY,
NMAWsWepKeyClass))
+
+NMA_AVAILABLE_IN_1_8_28
+GType nma_ws_wep_key_get_type (void);
+
+NMA_AVAILABLE_IN_1_8_28
+NMAWsWepKey *nma_ws_wep_key_new (NMConnection *connection,
+ NMWepKeyType type,
+ gboolean adhoc_create,
+ gboolean secrets_only);
+
+G_END_DECLS
+
+#endif /* NMA_WS_WEP_KEY_H */
diff --git a/src/nma-ws/nma-ws-wep-key.ui b/src/nma-ws/nma-ws-wep-key.ui
new file mode 100644
index 00000000..f3e627d1
--- /dev/null
+++ b/src/nma-ws/nma-ws-wep-key.ui
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="nm-applet">
+ <requires lib="gtk+" version="3.10"/>
+ <object class="GtkListStore" id="model3">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">Open System</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Shared Key</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="model4">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">1 (Default)</col>
+ </row>
+ <row>
+ <col id="0">2</col>
+ </row>
+ <row>
+ <col id="0">3</col>
+ </row>
+ <row>
+ <col id="0">4</col>
+ </row>
+ </data>
+ </object>
+ <template class="NMAWsWepKey" parent="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="wep_key_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Key</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">wep_key_entry</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="wep_key_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="max_length">64</property>
+ <property name="visibility">False</property>
+ <property name="activates_default">True</property>
+ <property name="width_chars">28</property>
+ <signal name="changed" handler="nma_ws_changed_cb" swapped="no"/>
+ <signal name="insert-text" handler="wep_entry_filter_cb" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="show_checkbutton_wep">
+ <property name="label" translatable="yes">Sho_w key</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="show_toggled_cb" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="auth_method_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Au_thentication</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">auth_method_combo</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="auth_method_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="model">model3</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer3"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ <signal name="changed" handler="nma_ws_changed_cb" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="key_index_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">WEP inde_x</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">key_index_combo</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="key_index_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="model">model4</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer4"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ <signal name="changed" handler="key_index_combo_changed_cb" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </template>
+</interface>
diff --git a/src/nma-ws/nma-ws-wpa-eap.c b/src/nma-ws/nma-ws-wpa-eap.c
new file mode 100644
index 00000000..f8c8daf0
--- /dev/null
+++ b/src/nma-ws/nma-ws-wpa-eap.c
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Dan Williams <dcbw redhat com>
+ *
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+#include "nm-default.h"
+#include "nma-private.h"
+
+#include "nma-ws.h"
+#include "nma-ws-private.h"
+#include "nma-ws-802-1x.h"
+#include "nma-ws-802-1x-private.h"
+#include "nma-ws-wpa-eap.h"
+
+typedef struct {
+ NMAWs8021xClass parent;
+} NMAWsWpaEapClass;
+
+struct _NMAWsWpaEap {
+ NMAWs8021x parent;
+};
+
+static void nma_ws_interface_init (NMAWsInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (NMAWsWpaEap, nma_ws_wpa_eap, NMA_TYPE_WS_802_1X,
+ G_IMPLEMENT_INTERFACE (NMA_TYPE_WS, nma_ws_interface_init))
+
+static void
+fill_connection (NMAWs *ws, NMConnection *connection)
+{
+ NMSettingWirelessSecurity *s_wireless_sec;
+
+ nma_ws_802_1x_fill_connection (ws, connection);
+
+ s_wireless_sec = nm_connection_get_setting_wireless_security (connection);
+ g_return_if_fail (s_wireless_sec);
+
+ g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap", NULL);
+}
+
+static void
+nma_ws_wpa_eap_init (NMAWsWpaEap *self)
+{
+}
+
+static void
+nma_ws_interface_init (NMAWsInterface *iface)
+{
+ iface->fill_connection = fill_connection;
+}
+
+NMAWsWpaEap *
+nma_ws_wpa_eap_new (NMConnection *connection,
+ gboolean is_editor,
+ gboolean secrets_only,
+ const char *const*secrets_hints)
+{
+ return g_object_new (NMA_TYPE_WS_WPA_EAP,
+ "connection", connection,
+ "secrets-only", secrets_only,
+ "is-editor", is_editor,
+ "secrets-hints", secrets_hints,
+ NULL);
+}
+
+static void
+nma_ws_wpa_eap_class_init (NMAWsWpaEapClass *klass)
+{
+}
diff --git a/src/nma-ws/nma-ws-wpa-eap.h b/src/nma-ws/nma-ws-wpa-eap.h
new file mode 100644
index 00000000..e53df74b
--- /dev/null
+++ b/src/nma-ws/nma-ws-wpa-eap.h
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Dan Williams <dcbw redhat com>
+ *
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+
+#ifndef NMA_WS_WPA_EAP_H
+#define NMA_WS_WPA_EAP_H
+
+#include "nma-version.h"
+
+G_BEGIN_DECLS
+
+typedef struct _NMAWsWpaEap NMAWsWpaEap;
+
+#define NMA_TYPE_WS_WPA_EAP (nma_ws_wpa_eap_get_type ())
+#define NMA_WS_WPA_EAP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMA_TYPE_WS_SAE, NMAWsWpaEap))
+#define NMA_WS_WPA_EAP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NMA_TYPE_WS_SAE, NMAWsWpaEapClass))
+#define NMA_IS_WS_WPA_EAP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NMA_TYPE_WS_SAE))
+#define NMA_IS_WS_WPA_EAP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NMA_TYPE_WS_SAE))
+#define NMA_WS_WPA_EAP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NMA_TYPE_WS_SAE, NMAWsWpaEapClass))
+
+NMA_AVAILABLE_IN_1_8_28
+GType nma_ws_wpa_eap_get_type (void);
+
+NMA_AVAILABLE_IN_1_8_28
+NMAWsWpaEap *nma_ws_wpa_eap_new (NMConnection *connection,
+ gboolean is_editor,
+ gboolean secrets_only,
+ const char *const*secrets_hints);
+
+G_END_DECLS
+
+#endif /* NMA_WS_WPA_EAP_H */
diff --git a/src/nma-ws/nma-ws-wpa-psk.c b/src/nma-ws/nma-ws-wpa-psk.c
new file mode 100644
index 00000000..a161243f
--- /dev/null
+++ b/src/nma-ws/nma-ws-wpa-psk.c
@@ -0,0 +1,303 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Dan Williams <dcbw redhat com>
+ *
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+#include "nma-private.h"
+
+#include <ctype.h>
+#include <string.h>
+
+#include "nma-ws.h"
+#include "nma-ws-private.h"
+#include "nma-ws-wpa-psk.h"
+#include "nma-ws-helpers.h"
+#include "nma-ui-utils.h"
+#include "utils.h"
+
+#define WPA_PMK_LEN 32
+
+typedef struct {
+ GtkGridClass parent;
+} NMAWsWpaPskClass;
+
+struct _NMAWsWpaPsk {
+ GtkGrid parent;
+
+ GtkWidget *wpa_psk_entry;
+ GtkWidget *wpa_psk_label;
+ GtkWidget *wpa_psk_type_combo;
+ GtkWidget *wpa_psk_type_label;
+ GtkWidget *show_checkbutton_wpa;
+
+ NMConnection *connection;
+ gboolean secrets_only;
+};
+
+static void nma_ws_interface_init (NMAWsInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (NMAWsWpaPsk, nma_ws_wpa_psk, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (NMA_TYPE_WS, nma_ws_interface_init))
+
+enum {
+ PROP_0,
+ PROP_CONNECTION,
+ PROP_SECRETS_ONLY,
+ PROP_LAST
+};
+
+static void
+show_toggled_cb (GtkCheckButton *button, gpointer user_data)
+{
+ NMAWsWpaPsk *self = NMA_WS_WPA_PSK (user_data);
+ gboolean visible;
+
+ visible = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+ gtk_entry_set_visibility (GTK_ENTRY (self->wpa_psk_entry), visible);
+}
+
+static gboolean
+validate (NMAWs *ws, GError **error)
+{
+ NMAWsWpaPsk *self = NMA_WS_WPA_PSK (ws);
+ NMSettingSecretFlags secret_flags;
+ const char *key;
+ gsize len;
+ int i;
+
+ secret_flags = nma_utils_menu_to_secret_flags (self->wpa_psk_entry);
+ key = gtk_editable_get_text (GTK_EDITABLE (self->wpa_psk_entry));
+ len = key ? strlen (key) : 0;
+
+ if ( secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED
+ || secret_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED) {
+ /* All good. */
+ } else if ((len < 8) || (len > 64)) {
+ widget_set_error (self->wpa_psk_entry);
+ g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid wpa-psk: invalid key-length %zu.
Must be [8,63] bytes or 64 hex digits"), len);
+ return FALSE;
+ } else if (len == 64) {
+ /* Hex PSK */
+ for (i = 0; i < len; i++) {
+ if (!isxdigit (key[i])) {
+ widget_set_error (self->wpa_psk_entry);
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid wpa-psk:
cannot interpret key with 64 bytes as hex"));
+ return FALSE;
+ }
+ }
+ }
+ widget_unset_error (self->wpa_psk_entry);
+
+ /* passphrase can be between 8 and 63 characters inclusive */
+
+ return TRUE;
+}
+
+static void
+add_to_size_group (NMAWs *ws, GtkSizeGroup *group)
+{
+ NMAWsWpaPsk *self = NMA_WS_WPA_PSK (ws);
+
+ gtk_size_group_add_widget (group, self->wpa_psk_type_label);
+ gtk_size_group_add_widget (group, self->wpa_psk_label);
+}
+
+static void
+fill_connection (NMAWs *ws, NMConnection *connection)
+{
+ NMAWsWpaPsk *self = NMA_WS_WPA_PSK (ws);
+ 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_return_if_fail (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_editable_get_text (GTK_EDITABLE (self->wpa_psk_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 (self->wpa_psk_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 */
+ if (!self->secrets_only) {
+ nma_utils_update_password_storage (self->wpa_psk_entry, secret_flags,
+ NM_SETTING (s_wireless_sec),
+ NM_SETTING_WIRELESS_SECURITY_PSK);
+ }
+
+ nma_ws_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, "wpa-psk", 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, "wpa-psk", NULL);
+
+ /* Just leave ciphers and protocol empty, the supplicant will
+ * figure that out magically based on the AP IEs and card capabilities.
+ */
+ }
+}
+
+static void
+update_secrets (NMAWs *ws, NMConnection *connection)
+{
+ NMAWsWpaPsk *self = NMA_WS_WPA_PSK (ws);
+
+ nma_ws_helper_fill_secret_entry (connection,
+ GTK_EDITABLE (self->wpa_psk_entry),
+ NM_TYPE_SETTING_WIRELESS_SECURITY,
+ (HelperSecretFunc) nm_setting_wireless_security_get_psk);
+}
+
+static void
+get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ NMAWsWpaPsk *self = NMA_WS_WPA_PSK (object);
+
+ switch (prop_id) {
+ case PROP_CONNECTION:
+ g_value_set_object (value, self->connection);
+ break;
+ case PROP_SECRETS_ONLY:
+ g_value_set_boolean (value, self->secrets_only);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ NMAWsWpaPsk *self = NMA_WS_WPA_PSK (object);
+
+ switch (prop_id) {
+ case PROP_CONNECTION:
+ self->connection = g_value_dup_object (value);
+ break;
+ case PROP_SECRETS_ONLY:
+ self->secrets_only = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nma_ws_wpa_psk_init (NMAWsWpaPsk *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static void
+nma_ws_interface_init (NMAWsInterface *iface)
+{
+ iface->validate = validate;
+ iface->add_to_size_group = add_to_size_group;
+ iface->fill_connection = fill_connection;
+ iface->update_secrets = update_secrets;
+ iface->adhoc_compatible = TRUE;
+ iface->hotspot_compatible = TRUE;
+}
+
+static void
+constructed (GObject *object)
+{
+ NMAWsWpaPsk *self = NMA_WS_WPA_PSK (object);
+ NMSetting *setting = NULL;
+
+ /* Create password-storage popup menu for password entry under entry's secondary icon */
+ if (self->connection)
+ setting = (NMSetting *) nm_connection_get_setting_wireless_security (self->connection);
+ nma_utils_setup_password_storage (self->wpa_psk_entry, 0, setting, NM_SETTING_WIRELESS_SECURITY_PSK,
+ FALSE, self->secrets_only);
+
+ /* Fill secrets, if any */
+ if (self->connection)
+ update_secrets (NMA_WS (self), self->connection);
+
+ gtk_widget_grab_focus (self->wpa_psk_entry);
+
+ /* Hide WPA/RSN for now since this can be autodetected by NM and the
+ * supplicant when connecting to the AP.
+ */
+ gtk_widget_hide (self->wpa_psk_type_combo);
+ gtk_widget_hide (self->wpa_psk_type_label);
+
+ G_OBJECT_CLASS (nma_ws_wpa_psk_parent_class)->constructed (object);
+}
+
+NMAWsWpaPsk *
+nma_ws_wpa_psk_new (NMConnection *connection, gboolean secrets_only)
+{
+ return g_object_new (NMA_TYPE_WS_WPA_PSK,
+ "connection", connection,
+ "secrets-only", secrets_only,
+ NULL);
+}
+
+static void
+dispose (GObject *object)
+{
+ NMAWsWpaPsk *self = NMA_WS_WPA_PSK (object);
+
+ g_clear_object (&self->connection);
+}
+
+static void
+nma_ws_wpa_psk_class_init (NMAWsWpaPskClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->get_property = get_property;
+ object_class->set_property = set_property;
+ object_class->constructed = constructed;
+ object_class->dispose = dispose;
+
+ g_object_class_override_property (object_class,
+ PROP_CONNECTION, "connection");
+
+ g_object_class_override_property (object_class,
+ PROP_SECRETS_ONLY, "secrets-only");
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/libnma/nma-ws-wpa-psk.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, NMAWsWpaPsk, wpa_psk_entry);
+ gtk_widget_class_bind_template_child (widget_class, NMAWsWpaPsk, wpa_psk_label);
+ gtk_widget_class_bind_template_child (widget_class, NMAWsWpaPsk, wpa_psk_type_combo);
+ gtk_widget_class_bind_template_child (widget_class, NMAWsWpaPsk, wpa_psk_type_label);
+ gtk_widget_class_bind_template_child (widget_class, NMAWsWpaPsk, show_checkbutton_wpa);
+
+ gtk_widget_class_bind_template_callback (widget_class, nma_ws_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, show_toggled_cb);
+}
diff --git a/src/nma-ws/nma-ws-wpa-psk.h b/src/nma-ws/nma-ws-wpa-psk.h
new file mode 100644
index 00000000..93e0b1ac
--- /dev/null
+++ b/src/nma-ws/nma-ws-wpa-psk.h
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Dan Williams <dcbw redhat com>
+ *
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+
+#ifndef NMA_WS_WPA_PSK_H
+#define NMA_WS_WPA_PSK_H
+
+#include "nma-version.h"
+
+G_BEGIN_DECLS
+
+typedef struct _NMAWsWpaPsk NMAWsWpaPsk;
+
+#define NMA_TYPE_WS_WPA_PSK (nma_ws_wpa_psk_get_type ())
+#define NMA_WS_WPA_PSK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMA_TYPE_WS_WPA_PSK, NMAWsWpaPsk))
+#define NMA_WS_WPA_PSK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NMA_TYPE_WS_WPA_PSK,
NMAWsWpaPskClass))
+#define NMA_IS_WS_WPA_PSK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NMA_TYPE_WS_WPA_PSK))
+#define NMA_IS_WS_WPA_PSK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NMA_TYPE_WS_WPA_PSK))
+#define NMA_WS_WPA_PSK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NMA_TYPE_WS_WPA_PSK,
NMAWsWpaPskClass))
+
+NMA_AVAILABLE_IN_1_8_28
+GType nma_ws_wpa_psk_get_type (void);
+
+NMA_AVAILABLE_IN_1_8_28
+NMAWsWpaPsk *nma_ws_wpa_psk_new (NMConnection *connection, gboolean secrets_only);
+
+G_END_DECLS
+
+#endif /* NMA_WS_WPA_PSK_H */
diff --git a/src/nma-ws/nma-ws-wpa-psk.ui b/src/nma-ws/nma-ws-wpa-psk.ui
new file mode 100644
index 00000000..17732468
--- /dev/null
+++ b/src/nma-ws/nma-ws-wpa-psk.ui
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="nm-applet">
+ <requires lib="gtk+" version="3.10"/>
+ <template class="NMAWsWpaPsk" parent="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="wpa_psk_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Password</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">wpa_psk_entry</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="wpa_psk_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="max_length">64</property>
+ <property name="visibility">False</property>
+ <property name="activates_default">True</property>
+ <signal name="changed" handler="nma_ws_changed_cb" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="wpa_psk_type_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Type</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">wpa_psk_type_combo</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="show_checkbutton_wpa">
+ <property name="label" translatable="yes">Sho_w password</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="show_toggled_cb" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="wpa_psk_type_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </template>
+</interface>
diff --git a/src/nma-ws/nma-ws.c b/src/nma-ws/nma-ws.c
new file mode 100644
index 00000000..1861f822
--- /dev/null
+++ b/src/nma-ws/nma-ws.c
@@ -0,0 +1,141 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Dan Williams <dcbw redhat com>
+ *
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+
+#include <string.h>
+
+#include "nma-ws.h"
+#include "nma-ws-private.h"
+#include "nma-eap.h"
+#include "utils.h"
+
+G_DEFINE_INTERFACE (NMAWs, nma_ws, G_TYPE_OBJECT)
+
+void
+nma_ws_changed_cb (GtkWidget *ignored, gpointer user_data)
+{
+ g_signal_emit_by_name (user_data, "ws-changed");
+}
+
+gboolean
+nma_ws_validate (NMAWs *self, GError **error)
+{
+ NMAWsInterface *iface;
+ gboolean result;
+
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (!error || !*error, FALSE);
+
+ iface = NMA_WS_GET_INTERFACE (self);
+ g_return_val_if_fail (iface->validate, FALSE);
+ result = (*(iface->validate)) (self, error);
+ if (!result && error && !*error)
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("Unknown error validating 802.1X
security"));
+ return result;
+}
+
+void
+nma_ws_add_to_size_group (NMAWs *self, GtkSizeGroup *group)
+{
+ NMAWsInterface *iface;
+
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (group != NULL);
+
+ iface = NMA_WS_GET_INTERFACE (self);
+ g_return_if_fail (iface->add_to_size_group);
+ return (*(iface->add_to_size_group)) (self, group);
+}
+
+void
+nma_ws_fill_connection (NMAWs *self,
+ NMConnection *connection)
+{
+ NMAWsInterface *iface;
+
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (connection != NULL);
+
+ iface = NMA_WS_GET_INTERFACE (self);
+ g_return_if_fail (iface->fill_connection);
+ return (*(iface->fill_connection)) (self, connection);
+}
+
+void
+nma_ws_update_secrets (NMAWs *self, NMConnection *connection)
+{
+ NMAWsInterface *iface;
+
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (connection != NULL);
+
+ iface = NMA_WS_GET_INTERFACE (self);
+ if (iface->update_secrets)
+ iface->update_secrets (self, connection);
+}
+
+void
+nma_ws_default_init (NMAWsInterface *iface)
+{
+ GType iface_type = G_TYPE_FROM_INTERFACE (iface);
+
+ g_signal_new ("ws-changed",
+ iface_type,
+ G_SIGNAL_RUN_FIRST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ iface->adhoc_compatible = TRUE;
+ iface->hotspot_compatible = TRUE;
+
+ g_object_interface_install_property (iface,
+ g_param_spec_object ("connection", "", "",
+ NM_TYPE_CONNECTION,
+ G_PARAM_READWRITE
+ | G_PARAM_CONSTRUCT
+ | G_PARAM_STATIC_STRINGS));
+
+ g_object_interface_install_property (iface,
+ g_param_spec_boolean ("secrets-only", "", "",
+ FALSE,
+ G_PARAM_READWRITE
+ | G_PARAM_CONSTRUCT
+ | G_PARAM_STATIC_STRINGS));
+}
+
+gboolean
+nma_ws_adhoc_compatible (NMAWs *self)
+{
+ g_return_val_if_fail (self != NULL, FALSE);
+
+ return NMA_WS_GET_INTERFACE (self)->adhoc_compatible;
+}
+
+gboolean
+nma_ws_hotspot_compatible (NMAWs *self)
+{
+ g_return_val_if_fail (self != NULL, FALSE);
+
+ return NMA_WS_GET_INTERFACE (self)->hotspot_compatible;
+}
+
+void
+nma_ws_clear_ciphers (NMConnection *connection)
+{
+ NMSettingWirelessSecurity *s_wireless_sec;
+
+ g_return_if_fail (connection != NULL);
+
+ s_wireless_sec = nm_connection_get_setting_wireless_security (connection);
+ g_return_if_fail (s_wireless_sec);
+
+ nm_setting_wireless_security_clear_protos (s_wireless_sec);
+ nm_setting_wireless_security_clear_pairwise (s_wireless_sec);
+ nm_setting_wireless_security_clear_groups (s_wireless_sec);
+}
diff --git a/src/nma-ws/nma-ws.h b/src/nma-ws/nma-ws.h
new file mode 100644
index 00000000..bbea4ded
--- /dev/null
+++ b/src/nma-ws/nma-ws.h
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Dan Williams <dcbw redhat com>
+ *
+ * Copyright 2007 - 2019 Red Hat, Inc.
+ */
+
+#ifndef NMA_WS_H
+#define NMA_WS_H
+
+#include "nma-version.h"
+
+G_BEGIN_DECLS
+
+typedef struct _NMAWs NMAWs;
+
+#define NMA_TYPE_WS (nma_ws_get_type ())
+#define NMA_WS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMA_TYPE_WS, NMAWs))
+#define NMA_IS_WS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NMA_TYPE_WS))
+#define NMA_WS_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NMA_TYPE_WS, NMAWsInterface))
+
+NMA_AVAILABLE_IN_1_8_28
+GType nma_ws_get_type (void);
+
+NMA_AVAILABLE_IN_1_8_28
+gboolean nma_ws_validate (NMAWs *self, GError **error);
+
+NMA_AVAILABLE_IN_1_8_28
+void nma_ws_add_to_size_group (NMAWs *self,
+ GtkSizeGroup *group);
+
+NMA_AVAILABLE_IN_1_8_28
+void nma_ws_fill_connection (NMAWs *self,
+ NMConnection *connection);
+
+NMA_AVAILABLE_IN_1_8_28
+void nma_ws_update_secrets (NMAWs *self,
+ NMConnection *connection);
+
+NMA_AVAILABLE_IN_1_8_28
+gboolean nma_ws_adhoc_compatible (NMAWs *self);
+
+NMA_AVAILABLE_IN_1_8_28
+gboolean nma_ws_hotspot_compatible (NMAWs *self);
+
+G_END_DECLS
+
+#include "nma-ws-802-1x.h"
+#include "nma-ws-dynamic-wep.h"
+#include "nma-ws-leap.h"
+#include "nma-ws-sae.h"
+#include "nma-ws-wep-key.h"
+#include "nma-ws-wpa-eap.h"
+#include "nma-ws-wpa-psk.h"
+
+#endif /* NMA_WS_H */
diff --git a/src/nma.gresource.xml b/src/nma.gresource.xml
index cfe41a7f..5c75f112 100644
--- a/src/nma.gresource.xml
+++ b/src/nma.gresource.xml
@@ -7,5 +7,16 @@
<file preprocess="xml-stripblanks">nma-mobile-wizard.ui</file>
<file preprocess="xml-stripblanks">nma-vpn-password-dialog.ui</file>
<file preprocess="xml-stripblanks">nma-bar-code-widget.ui</file>
+ <file preprocess="xml-stripblanks" alias="nma-ws-802-1x.ui">nma-ws/nma-ws-802-1x.ui</file>
+ <file preprocess="xml-stripblanks" alias="nma-ws-leap.ui">nma-ws/nma-ws-leap.ui</file>
+ <file preprocess="xml-stripblanks" alias="nma-ws-sae.ui">nma-ws/nma-ws-sae.ui</file>
+ <file preprocess="xml-stripblanks" alias="nma-ws-wep-key.ui">nma-ws/nma-ws-wep-key.ui</file>
+ <file preprocess="xml-stripblanks" alias="nma-ws-wpa-psk.ui">nma-ws/nma-ws-wpa-psk.ui</file>
+ <file preprocess="xml-stripblanks" alias="nma-eap-fast.ui">nma-ws/nma-eap-fast.ui</file>
+ <file preprocess="xml-stripblanks" alias="nma-eap-leap.ui">nma-ws/nma-eap-leap.ui</file>
+ <file preprocess="xml-stripblanks" alias="nma-eap-peap.ui">nma-ws/nma-eap-peap.ui</file>
+ <file preprocess="xml-stripblanks" alias="nma-eap-simple.ui">nma-ws/nma-eap-simple.ui</file>
+ <file preprocess="xml-stripblanks" alias="nma-eap-tls.ui">nma-ws/nma-eap-tls.ui</file>
+ <file preprocess="xml-stripblanks" alias="nma-eap-ttls.ui">nma-ws/nma-eap-ttls.ui</file>
</gresource>
</gresources>
diff --git a/src/wireless-security/ws-leap.ui b/src/wireless-security/ws-leap.ui
index a93121d6..e772c5a2 100644
--- a/src/wireless-security/ws-leap.ui
+++ b/src/wireless-security/ws-leap.ui
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.20.0 -->
+<!-- Generated with glade 3.22.1 -->
<interface domain="nm-applet">
<requires lib="gtk+" version="3.10"/>
<object class="GtkNotebook" id="leap_notebook">
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]