summary refs log tree commit diff
path: root/src/nmtui
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2023-02-10 11:50:34 +0100
committerMichael Biebl <biebl@debian.org>2023-02-10 11:50:34 +0100
commit1372848511cb896b80b51ed1a3e9606bd9816631 (patch)
tree674792b9385bdef935988894b45f06b2af39f88c /src/nmtui
parent40ec077ea305994c1fc2130add6787ca0c73e2c6 (diff)
New upstream version 1.42.0 upstream/1.42.0
Diffstat (limited to 'src/nmtui')
-rw-r--r--src/nmtui/meson.build2
-rw-r--r--src/nmtui/nm-editor-bindings.c95
-rw-r--r--src/nmtui/nm-editor-bindings.h11
-rw-r--r--src/nmtui/nm-editor-utils.c8
-rw-r--r--src/nmtui/nmt-8021x-fields.c693
-rw-r--r--src/nmtui/nmt-8021x-fields.h29
-rw-r--r--src/nmtui/nmt-address-list.h2
-rw-r--r--src/nmtui/nmt-connect-connection-list.c1
-rw-r--r--src/nmtui/nmt-connect-connection-list.h6
-rw-r--r--src/nmtui/nmt-device-entry.h2
-rw-r--r--src/nmtui/nmt-edit-connection-list.h2
-rw-r--r--src/nmtui/nmt-editor-grid.c12
-rw-r--r--src/nmtui/nmt-editor-grid.h2
-rw-r--r--src/nmtui/nmt-editor-page-device.h2
-rw-r--r--src/nmtui/nmt-editor-page.h2
-rw-r--r--src/nmtui/nmt-editor-section.h2
-rw-r--r--src/nmtui/nmt-editor.c3
-rw-r--r--src/nmtui/nmt-editor.h2
-rw-r--r--src/nmtui/nmt-ip-entry.c4
-rw-r--r--src/nmtui/nmt-ip-entry.h2
-rw-r--r--src/nmtui/nmt-mac-entry.h2
-rw-r--r--src/nmtui/nmt-mtu-entry.h2
-rw-r--r--src/nmtui/nmt-page-bond-port.h2
-rw-r--r--src/nmtui/nmt-page-bond.h2
-rw-r--r--src/nmtui/nmt-page-bridge-port.h2
-rw-r--r--src/nmtui/nmt-page-bridge.h2
-rw-r--r--src/nmtui/nmt-page-dsl.h2
-rw-r--r--src/nmtui/nmt-page-ethernet.c90
-rw-r--r--src/nmtui/nmt-page-ethernet.h13
-rw-r--r--src/nmtui/nmt-page-infiniband.h2
-rw-r--r--src/nmtui/nmt-page-ip-tunnel.h2
-rw-r--r--src/nmtui/nmt-page-ip4.h2
-rw-r--r--src/nmtui/nmt-page-ip6.h2
-rw-r--r--src/nmtui/nmt-page-macsec.c196
-rw-r--r--src/nmtui/nmt-page-macsec.h28
-rw-r--r--src/nmtui/nmt-page-ppp.h2
-rw-r--r--src/nmtui/nmt-page-team-port.h2
-rw-r--r--src/nmtui/nmt-page-team.h2
-rw-r--r--src/nmtui/nmt-page-vlan.h2
-rw-r--r--src/nmtui/nmt-page-wifi.c50
-rw-r--r--src/nmtui/nmt-page-wifi.h2
-rw-r--r--src/nmtui/nmt-page-wireguard.h2
-rw-r--r--src/nmtui/nmt-password-dialog.c2
-rw-r--r--src/nmtui/nmt-password-dialog.h2
-rw-r--r--src/nmtui/nmt-password-fields.c130
-rw-r--r--src/nmtui/nmt-password-fields.h7
-rw-r--r--src/nmtui/nmt-route-editor.h2
-rw-r--r--src/nmtui/nmt-route-entry.h2
-rw-r--r--src/nmtui/nmt-route-table.h2
-rw-r--r--src/nmtui/nmt-slave-list.h3
-rw-r--r--src/nmtui/nmt-widget-list.h2
-rw-r--r--src/nmtui/nmt-wireguard-peer-editor.h2
-rw-r--r--src/nmtui/nmt-wireguard-peer-list.h2
-rw-r--r--src/nmtui/nmtui-connect.c11
-rw-r--r--src/nmtui/nmtui-edit.c11
-rw-r--r--src/nmtui/nmtui-hostname.c2
-rw-r--r--src/nmtui/nmtui.c7
57 files changed, 1312 insertions, 168 deletions
diff --git a/src/nmtui/meson.build b/src/nmtui/meson.build
index e6cac268..48f2fbf4 100644
--- a/src/nmtui/meson.build
+++ b/src/nmtui/meson.build
@@ -5,6 +5,7 @@ executable(
   files(
     'nm-editor-bindings.c',
     'nm-editor-utils.c',
+    'nmt-8021x-fields.c',
     'nmt-address-list.c',
     'nmt-connect-connection-list.c',
     'nmt-device-entry.c',
@@ -27,6 +28,7 @@ executable(
     'nmt-page-ip4.c',
     'nmt-page-ip6.c',
     'nmt-page-ip-tunnel.c',
+    'nmt-page-macsec.c',
     'nmt-page-ppp.c',
     'nmt-page-team.c',
     'nmt-page-team-port.c',
diff --git a/src/nmtui/nm-editor-bindings.c b/src/nmtui/nm-editor-bindings.c
index 22ffdfd5..360cf3ad 100644
--- a/src/nmtui/nm-editor-bindings.c
+++ b/src/nmtui/nm-editor-bindings.c
@@ -54,6 +54,51 @@ nm_editor_bindings_init(void)
     g_value_register_transform_func(G_TYPE_STRING, G_TYPE_UINT, value_transform_string_uint);
 }
 
+gboolean
+certificate_to_string(GBinding     *binding,
+                      const GValue *source_value,
+                      GValue       *target_value,
+                      gpointer      user_data)
+{
+    GBytes *bytes;
+    char   *utf8;
+
+    bytes = g_value_get_boxed(source_value);
+    if (bytes)
+        utf8 = nm_utils_ssid_to_utf8(g_bytes_get_data(bytes, NULL), g_bytes_get_size(bytes));
+    else
+        utf8 = g_strdup("");
+    g_value_take_string(target_value, utf8);
+    return TRUE;
+}
+
+gboolean
+certificate_from_string(GBinding     *binding,
+                        const GValue *source_value,
+                        GValue       *target_value,
+                        gpointer      user_data)
+{
+    const char   *text;
+    gs_free char *cert  = NULL;
+    GBytes       *bytes = NULL;
+
+    text = g_value_get_string(source_value);
+
+    if (text[0]) {
+        /* Consider anything without a scheme prefix as an absolute path */
+        if (!g_str_has_prefix(text, "file://") && !g_str_has_prefix(text, "blob://")
+            && !g_str_has_prefix(text, "pkcs11://")) {
+            cert = g_strdup_printf("file://%s%s", text[0] == '/' ? "" : "/", text);
+            text = cert;
+        }
+
+        bytes = g_bytes_new(text, strlen(text) + 1);
+    }
+    g_value_take_boxed(target_value, bytes);
+
+    return TRUE;
+}
+
 static gboolean
 ip_addresses_with_prefix_to_strv(GBinding     *binding,
                                  const GValue *source_value,
@@ -116,7 +161,7 @@ ip_addresses_with_prefix_from_strv(GBinding     *binding,
         } else
             addr = addrs->pdata[i];
 
-        if (!nm_utils_parse_inaddr_prefix(addr_family, strings[i], &addrstr, &prefix)) {
+        if (!nm_inet_parse_with_prefix_str(addr_family, strings[i], &addrstr, &prefix)) {
             g_ptr_array_unref(addrs);
             return FALSE;
         }
@@ -126,7 +171,7 @@ ip_addresses_with_prefix_from_strv(GBinding     *binding,
                 in_addr_t v4;
 
                 inet_pton(addr_family, addrstr, &v4);
-                if (nm_utils_ip_is_site_local(AF_INET, &v4))
+                if (nm_ip_addr_is_site_local(AF_INET, &v4))
                     prefix = nm_utils_ip4_get_default_prefix(v4);
                 else
                     prefix = 32;
@@ -194,7 +239,7 @@ ip_addresses_check_and_copy(GBinding     *binding,
     strings = g_value_get_boxed(source_value);
 
     for (i = 0; strings[i]; i++) {
-        if (!nm_utils_ipaddr_is_valid(addr_family, strings[i]))
+        if (!nm_inet_is_valid(addr_family, strings[i]))
             return FALSE;
     }
 
@@ -256,7 +301,7 @@ ip_gateway_from_string(GBinding     *binding,
     const char *gateway;
 
     gateway = g_value_get_string(source_value);
-    if (gateway && !nm_utils_ipaddr_is_valid(addr_family, gateway))
+    if (gateway && !nm_inet_is_valid(addr_family, gateway))
         gateway = NULL;
 
     g_value_set_string(target_value, gateway);
@@ -428,7 +473,7 @@ ip_route_transform_from_dest_string(GBinding     *binding,
     int         prefix;
 
     text = g_value_get_string(source_value);
-    if (!nm_utils_parse_inaddr_prefix(addr_family, text, &addrstr, &prefix))
+    if (!nm_inet_parse_with_prefix_str(addr_family, text, &addrstr, &prefix))
         return FALSE;
 
     /* Fetch the original property value */
@@ -442,9 +487,9 @@ ip_route_transform_from_dest_string(GBinding     *binding,
             in_addr_t v4;
 
             inet_pton(addr_family, addrstr, &v4);
-            if (nm_utils_ip_is_site_local(AF_INET, &v4)) {
+            if (nm_ip_addr_is_site_local(AF_INET, &v4)) {
                 prefix = nm_utils_ip4_get_default_prefix(v4);
-                if (v4 & (~_nm_utils_ip4_prefix_to_netmask(prefix)))
+                if (v4 & (~nm_ip4_addr_netmask_from_prefix(prefix)))
                     prefix = 32;
             } else
                 prefix = 32;
@@ -472,7 +517,7 @@ ip_route_transform_from_next_hop_string(GBinding     *binding,
 
     text = g_value_get_string(source_value);
     if (*text) {
-        if (!nm_utils_ipaddr_is_valid(addr_family, text))
+        if (!nm_inet_is_valid(addr_family, text))
             return FALSE;
     } else
         text = NULL;
@@ -803,7 +848,9 @@ peer_transform_from_persistent_keepalive_string(GBinding     *binding,
 typedef struct {
     NMConnection              *connection;
     NMSettingWirelessSecurity *s_wsec;
+    NMSetting8021x            *s_8021x;
     gboolean                   s_wsec_in_use;
+    gboolean                   s_8021x_in_use;
 
     GObject *target;
     char    *target_property;
@@ -891,6 +938,7 @@ wireless_security_target_changed(GObject *object, GParamSpec *pspec, gpointer us
 {
     NMEditorWirelessSecurityMethodBinding *binding = user_data;
     char                                  *method;
+    gboolean                               need_8021x = FALSE;
 
     if (binding->updating)
         return;
@@ -900,11 +948,14 @@ wireless_security_target_changed(GObject *object, GParamSpec *pspec, gpointer us
     binding->updating = TRUE;
 
     if (!strcmp(method, "none")) {
-        if (!binding->s_wsec_in_use)
-            return;
-        binding->s_wsec_in_use = FALSE;
-        nm_connection_remove_setting(binding->connection, NM_TYPE_SETTING_WIRELESS_SECURITY);
-
+        if (binding->s_wsec_in_use) {
+            binding->s_wsec_in_use = FALSE;
+            nm_connection_remove_setting(binding->connection, NM_TYPE_SETTING_WIRELESS_SECURITY);
+        }
+        if (binding->s_8021x_in_use) {
+            binding->s_8021x_in_use = FALSE;
+            nm_connection_remove_setting(binding->connection, NM_TYPE_SETTING_802_1X);
+        }
         binding->updating = FALSE;
         return;
     }
@@ -985,10 +1036,21 @@ wireless_security_target_changed(GObject *object, GParamSpec *pspec, gpointer us
                      NULL,
                      NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE,
                      NM_WEP_KEY_TYPE_UNKNOWN,
+                     NM_SETTING_WIRELESS_SECURITY_PSK,
+                     NULL,
                      NULL);
+        need_8021x = TRUE;
     } else
         g_warn_if_reached();
 
+    if (need_8021x != binding->s_8021x_in_use) {
+        binding->s_8021x_in_use = need_8021x;
+        if (need_8021x)
+            nm_connection_add_setting(binding->connection, NM_SETTING(binding->s_8021x));
+        else
+            nm_connection_remove_setting(binding->connection, NM_TYPE_SETTING_802_1X);
+    }
+
     binding->updating = FALSE;
 }
 
@@ -1031,6 +1093,7 @@ wireless_security_target_destroyed(gpointer user_data, GObject *ex_target)
 void
 nm_editor_bind_wireless_security_method(NMConnection              *connection,
                                         NMSettingWirelessSecurity *s_wsec,
+                                        NMSetting8021x            *s_8021x,
                                         gpointer                   target,
                                         const char                *target_property,
                                         GBindingFlags              flags)
@@ -1054,9 +1117,11 @@ nm_editor_bind_wireless_security_method(NMConnection              *connection,
                      NM_CONNECTION_CHANGED,
                      G_CALLBACK(wireless_connection_changed),
                      binding);
-    binding->s_wsec_in_use = (nm_connection_get_setting_wireless_security(connection) != NULL);
+    binding->s_wsec_in_use  = (nm_connection_get_setting_wireless_security(connection) != NULL);
+    binding->s_wsec         = g_object_ref(s_wsec);
+    binding->s_8021x_in_use = (nm_connection_get_setting_802_1x(connection) != NULL);
+    binding->s_8021x        = g_object_ref(s_8021x);
 
-    binding->s_wsec = g_object_ref(s_wsec);
     g_signal_connect(s_wsec,
                      "notify::" NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,
                      G_CALLBACK(wireless_security_changed),
diff --git a/src/nmtui/nm-editor-bindings.h b/src/nmtui/nm-editor-bindings.h
index ef2f36f2..bbd5622a 100644
--- a/src/nmtui/nm-editor-bindings.h
+++ b/src/nmtui/nm-editor-bindings.h
@@ -8,6 +8,16 @@
 
 void nm_editor_bindings_init(void);
 
+gboolean certificate_from_string(GBinding     *binding,
+                                 const GValue *source_value,
+                                 GValue       *target_value,
+                                 gpointer      user_data);
+
+gboolean certificate_to_string(GBinding     *binding,
+                               const GValue *source_value,
+                               GValue       *target_value,
+                               gpointer      user_data);
+
 void nm_editor_bind_ip_addresses_with_prefix_to_strv(int           family,
                                                      gpointer      source,
                                                      const char   *source_property,
@@ -41,6 +51,7 @@ void nm_editor_bind_ip_route_to_strings(int           family,
 
 void nm_editor_bind_wireless_security_method(NMConnection              *connection,
                                              NMSettingWirelessSecurity *s_wsec,
+                                             NMSetting8021x            *s_8021x,
                                              gpointer                   target,
                                              const char                *target_property,
                                              GBindingFlags              flags);
diff --git a/src/nmtui/nm-editor-utils.c b/src/nmtui/nm-editor-utils.c
index a3ee7a75..0f69c962 100644
--- a/src/nmtui/nm-editor-utils.c
+++ b/src/nmtui/nm-editor-utils.c
@@ -235,6 +235,14 @@ nm_editor_utils_get_connection_type_list(void)
     item->id_format         = _("IP tunnel connection %d");
     g_ptr_array_add(array, item);
 
+    item                    = g_new0(NMEditorConnectionTypeDataReal, 1);
+    item->data.name         = _("MACsec");
+    item->data.setting_type = NM_TYPE_SETTING_MACSEC;
+    item->data.device_type  = NM_TYPE_DEVICE_MACSEC;
+    item->data.virtual      = TRUE;
+    item->id_format         = _("MACsec connection %d");
+    g_ptr_array_add(array, item);
+
 #if 0
     /* Add "VPN" only if there are plugins */
     vpn_plugins_hash = nm_vpn_get_plugin_infos ();
diff --git a/src/nmtui/nmt-8021x-fields.c b/src/nmtui/nmt-8021x-fields.c
new file mode 100644
index 00000000..3a2185cf
--- /dev/null
+++ b/src/nmtui/nmt-8021x-fields.c
@@ -0,0 +1,693 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2022 Red Hat, Inc.
+ */
+/**
+ * SECTION:nmt-8021x-fields
+ * @short_description: Widgets for 802.1X setting
+ *
+ * #Nmt8021xFields provides widgets to configure the 802.1X setting
+ */
+
+#include "libnm-client-aux-extern/nm-default-client.h"
+
+#include "nmt-8021x-fields.h"
+#include "nmt-editor-grid.h"
+#include "nmt-password-fields.h"
+#include "nm-editor-bindings.h"
+
+typedef struct _EapMethod EapMethod;
+
+typedef struct {
+    const char *id;
+    const char *label;
+    gboolean    only_for_wired;
+    void (*populate)(EapMethod *method, NmtNewtWidget *grid);
+    void (*selected)(EapMethod *method);
+} EapMethodDesc;
+
+struct _EapMethod {
+    const EapMethodDesc *desc;
+    NMSetting8021x      *setting;
+    NmtNewtWidget       *inner_popup;
+};
+
+typedef struct {
+    NMSetting8021x *setting;
+    NmtNewtWidget  *authentication;
+    NmtNewtWidget  *phase2_auth;
+    gboolean        is_wired;
+    gboolean        is_updating;
+    EapMethod      *eap_methods;
+} Nmt8021xFieldsPrivate;
+
+struct _Nmt8021xFields {
+    NmtNewtGrid           parent;
+    Nmt8021xFieldsPrivate _priv;
+};
+
+struct _Nmt8021xFieldsClass {
+    NmtNewtGridClass parent;
+};
+
+G_DEFINE_TYPE(Nmt8021xFields, nmt_8021x_fields, NMT_TYPE_EDITOR_GRID)
+
+#define NMT_8021X_FIELDS_GET_PRIVATE(self) \
+    _NM_GET_PRIVATE(self, Nmt8021xFields, NMT_IS_8021X_FIELDS)
+
+enum {
+    PROP_0,
+    PROP_IS_WIRED,
+    PROP_SETTING,
+
+    LAST_PROP
+};
+
+static void
+nmt_8021x_fields_init(Nmt8021xFields *fields)
+{}
+
+/**
+ * nmt_8021x_fields_new:
+ * @setting: the backing 802.1X setting
+ * @is_wired: whether the setting is for a wired connection or wireless
+ *
+ * Creates a new #Nmt8021xFields
+ *
+ * Returns: a new #Nmt8021xFields
+ */
+NmtNewtWidget *
+nmt_8021x_fields_new(NMSetting8021x *setting, gboolean is_wired)
+{
+    return g_object_new(NMT_TYPE_8021X_FIELDS, "setting", setting, "is-wired", is_wired, NULL);
+}
+
+static gboolean
+eap_methods_to_string(GBinding     *binding,
+                      const GValue *source_value,
+                      GValue       *target_value,
+                      gpointer      user_data)
+{
+    char **strv;
+
+    strv = g_value_get_boxed(source_value);
+    if (!strv)
+        return FALSE;
+
+    /* The API allows multiple EAP methods. The UI to
+     * support this would be complicate, only allow
+     * one for now. */
+    g_value_set_string(target_value, strv[0]);
+    return TRUE;
+}
+
+static gboolean
+eap_methods_from_string(GBinding     *binding,
+                        const GValue *source_value,
+                        GValue       *target_value,
+                        gpointer      user_data)
+{
+    const char *text;
+    char      **strv = g_new(char *, 2);
+
+    text    = g_value_get_string(source_value);
+    strv[0] = g_strdup(text);
+    strv[1] = NULL;
+
+    g_value_take_boxed(target_value, strv);
+    return TRUE;
+}
+
+static gboolean
+cert_validate(NmtNewtEntry *entry, const char *text, gpointer user_data)
+{
+    NMSetting8021xCKScheme scheme;
+
+    scheme = nm_setting_802_1x_check_cert_scheme(text, strlen(text) + 1, NULL);
+    return scheme != NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
+}
+
+static void
+phase2_auth_widget_changed(GObject *object, GParamSpec *pspec, gpointer user_data)
+{
+    NmtNewtWidget  *widget  = NMT_NEWT_WIDGET(object);
+    NMSetting8021x *setting = user_data;
+    const char     *active_id;
+    const char     *auth_eap;
+    const char     *auth;
+
+    active_id = nmt_newt_popup_get_active_id(NMT_NEWT_POPUP(widget));
+
+    if (g_str_has_prefix(active_id, "eap-")) {
+        auth_eap = &active_id[NM_STRLEN("eap-")];
+        auth     = NULL;
+    } else {
+        auth_eap = NULL;
+        auth     = active_id;
+    }
+
+    if (!nm_streq0(auth, nm_setting_802_1x_get_phase2_auth(setting)))
+        g_object_set(setting, NM_SETTING_802_1X_PHASE2_AUTH, auth, NULL);
+    if (!nm_streq0(auth_eap, nm_setting_802_1x_get_phase2_autheap(setting)))
+        g_object_set(setting, NM_SETTING_802_1X_PHASE2_AUTHEAP, auth_eap, NULL);
+}
+
+static void
+phase2_auth_setting_changed(GObject *object, GParamSpec *pspec, gpointer user_data)
+{
+    NMSetting8021x *setting   = NM_SETTING_802_1X(object);
+    NmtNewtWidget  *widget    = user_data;
+    gs_free char   *active_id = NULL;
+    const char     *auth;
+
+    auth = nm_setting_802_1x_get_phase2_auth(setting);
+    if (auth) {
+        active_id = g_strdup(auth);
+    } else {
+        auth = nm_setting_802_1x_get_phase2_autheap(setting);
+        if (auth)
+            active_id = g_strdup_printf("eap-%s", auth);
+    }
+
+    if (active_id)
+        nmt_newt_popup_set_active_id(NMT_NEWT_POPUP(widget), active_id);
+}
+
+static void
+eap_method_populate_simple(EapMethod *method, NmtNewtWidget *subgrid)
+{
+    NmtNewtWidget *widget;
+
+    widget = nmt_newt_entry_new(40, NMT_NEWT_ENTRY_NONEMPTY);
+    nmt_editor_grid_append(NMT_EDITOR_GRID(subgrid), _("Username"), widget, NULL);
+    g_object_bind_property(method->setting,
+                           NM_SETTING_802_1X_IDENTITY,
+                           widget,
+                           "text",
+                           G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+
+    widget = nmt_password_fields_new(40, NMT_PASSWORD_FIELDS_SHOW_PASSWORD);
+    g_object_bind_property(method->setting,
+                           NM_SETTING_802_1X_PASSWORD,
+                           widget,
+                           "password",
+                           G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+    nmt_editor_grid_append(NMT_EDITOR_GRID(subgrid), _("Password"), widget, NULL);
+}
+
+static void
+eap_method_populate_tls(EapMethod *method, NmtNewtWidget *subgrid)
+{
+    NmtNewtWidget *widget;
+
+    widget = nmt_newt_entry_new(40, NMT_NEWT_ENTRY_NONEMPTY);
+    nmt_editor_grid_append(NMT_EDITOR_GRID(subgrid), _("Identity"), widget, NULL);
+    g_object_bind_property(method->setting,
+                           NM_SETTING_802_1X_IDENTITY,
+                           widget,
+                           "text",
+                           G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+
+    widget = nmt_newt_entry_new(40, 0);
+    nmt_editor_grid_append(NMT_EDITOR_GRID(subgrid), _("Domain"), widget, NULL);
+    g_object_bind_property(method->setting,
+                           NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH,
+                           widget,
+                           "text",
+                           G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+
+    widget = nmt_newt_entry_new(40, 0);
+    nmt_editor_grid_append(NMT_EDITOR_GRID(subgrid), _("CA cert"), widget, NULL);
+    nmt_newt_entry_set_validator(NMT_NEWT_ENTRY(widget), cert_validate, NULL);
+    g_object_bind_property_full(method->setting,
+                                NM_SETTING_802_1X_CA_CERT,
+                                widget,
+                                "text",
+                                G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL,
+                                certificate_to_string,
+                                certificate_from_string,
+                                NULL,
+                                NULL);
+
+    widget =
+        nmt_password_fields_new(40,
+                                NMT_PASSWORD_FIELDS_SHOW_PASSWORD | NMT_PASSWORD_FIELDS_NOT_EMPTY);
+    g_object_bind_property(method->setting,
+                           NM_SETTING_802_1X_CA_CERT_PASSWORD,
+                           widget,
+                           "password",
+                           G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+    nmt_editor_grid_append(NMT_EDITOR_GRID(subgrid), _("CA cert password"), widget, NULL);
+
+    widget = nmt_newt_entry_new(40, NMT_NEWT_ENTRY_NONEMPTY);
+    nmt_editor_grid_append(NMT_EDITOR_GRID(subgrid), _("User cert"), widget, NULL);
+    nmt_newt_entry_set_validator(NMT_NEWT_ENTRY(widget), cert_validate, NULL);
+    g_object_bind_property_full(method->setting,
+                                NM_SETTING_802_1X_CLIENT_CERT,
+                                widget,
+                                "text",
+                                G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL,
+                                certificate_to_string,
+                                certificate_from_string,
+                                NULL,
+                                NULL);
+
+    widget =
+        nmt_password_fields_new(40,
+                                NMT_PASSWORD_FIELDS_SHOW_PASSWORD | NMT_PASSWORD_FIELDS_NOT_EMPTY);
+    g_object_bind_property(method->setting,
+                           NM_SETTING_802_1X_CLIENT_CERT_PASSWORD,
+                           widget,
+                           "password",
+                           G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+    nmt_editor_grid_append(NMT_EDITOR_GRID(subgrid), _("User cert password"), widget, NULL);
+
+    widget = nmt_newt_entry_new(40, NMT_NEWT_ENTRY_NONEMPTY);
+    nmt_editor_grid_append(NMT_EDITOR_GRID(subgrid), _("User private key"), widget, NULL);
+    nmt_newt_entry_set_validator(NMT_NEWT_ENTRY(widget), cert_validate, NULL);
+    g_object_bind_property_full(method->setting,
+                                NM_SETTING_802_1X_PRIVATE_KEY,
+                                widget,
+                                "text",
+                                G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL,
+                                certificate_to_string,
+                                certificate_from_string,
+                                NULL,
+                                NULL);
+
+    widget = nmt_password_fields_new(40, NMT_PASSWORD_FIELDS_SHOW_PASSWORD);
+    g_object_bind_property(method->setting,
+                           NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD,
+                           widget,
+                           "password",
+                           G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+    nmt_editor_grid_append(NMT_EDITOR_GRID(subgrid), _("User privkey password"), widget, NULL);
+}
+
+static void
+eap_method_populate_ttls(EapMethod *method, NmtNewtWidget *subgrid)
+{
+    NmtNewtWidget    *widget;
+    NmtNewtPopupEntry ttls_inner_methods[] = {{N_("PAP"), "pap"},
+                                              {N_("MSCHAP"), "mschap"},
+                                              {N_("MSCHAPv2"), "eap-mschapv2"},
+                                              {N_("MSCHAPv2 (no EAP)"), "mschapv2"},
+                                              {N_("CHAP"), "chap"},
+                                              {N_("MD5"), "eap-md5"},
+                                              {N_("GTC"), "eap-gtc"},
+                                              {NULL, NULL}};
+
+    widget = nmt_newt_entry_new(40, NMT_NEWT_ENTRY_NONEMPTY);
+    nmt_editor_grid_append(NMT_EDITOR_GRID(subgrid), _("Anonymous identity"), widget, NULL);
+    g_object_bind_property(method->setting,
+                           NM_SETTING_802_1X_ANONYMOUS_IDENTITY,
+                           widget,
+                           "text",
+                           G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+
+    widget = nmt_newt_entry_new(40, 0);
+    nmt_editor_grid_append(NMT_EDITOR_GRID(subgrid), _("CA cert"), widget, NULL);
+    nmt_newt_entry_set_validator(NMT_NEWT_ENTRY(widget), cert_validate, NULL);
+    g_object_bind_property_full(method->setting,
+                                NM_SETTING_802_1X_CA_CERT,
+                                widget,
+                                "text",
+                                G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL,
+                                certificate_to_string,
+                                certificate_from_string,
+                                NULL,
+                                NULL);
+
+    widget =
+        nmt_password_fields_new(40,
+                                NMT_PASSWORD_FIELDS_SHOW_PASSWORD | NMT_PASSWORD_FIELDS_NOT_EMPTY);
+    g_object_bind_property(method->setting,
+                           NM_SETTING_802_1X_CA_CERT_PASSWORD,
+                           widget,
+                           "password",
+                           G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+    nmt_editor_grid_append(NMT_EDITOR_GRID(subgrid), _("CA cert password"), widget, NULL);
+
+    widget              = nmt_newt_popup_new(ttls_inner_methods);
+    method->inner_popup = widget;
+    g_signal_connect(widget,
+                     "notify::active-id",
+                     G_CALLBACK(phase2_auth_widget_changed),
+                     method->setting);
+    g_signal_connect(method->setting,
+                     "notify::" NM_SETTING_802_1X_PHASE2_AUTH,
+                     G_CALLBACK(phase2_auth_setting_changed),
+                     widget);
+    g_signal_connect(method->setting,
+                     "notify::" NM_SETTING_802_1X_PHASE2_AUTHEAP,
+                     G_CALLBACK(phase2_auth_setting_changed),
+                     widget);
+    nmt_editor_grid_append(NMT_EDITOR_GRID(subgrid), _("Inner authentication"), widget, NULL);
+
+    if (nm_setting_802_1x_get_num_eap_methods(method->setting) > 0
+        && nm_streq0(nm_setting_802_1x_get_eap_method(method->setting, 0), "ttls")) {
+        phase2_auth_setting_changed(G_OBJECT(method->setting), NULL, widget);
+    }
+
+    widget = nmt_newt_entry_new(40, NMT_NEWT_ENTRY_NONEMPTY);
+    nmt_editor_grid_append(NMT_EDITOR_GRID(subgrid), _("Username"), widget, NULL);
+    g_object_bind_property(method->setting,
+                           NM_SETTING_802_1X_IDENTITY,
+                           widget,
+                           "text",
+                           G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+
+    widget = nmt_password_fields_new(40,
+                                     NMT_PASSWORD_FIELDS_SHOW_PASSWORD
+                                         | NMT_PASSWORD_FIELDS_SHOW_SECRET_FLAGS);
+    g_object_bind_property(method->setting,
+                           NM_SETTING_802_1X_PASSWORD,
+                           widget,
+                           "password",
+                           G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+    g_object_bind_property(method->setting,
+                           NM_SETTING_802_1X_PASSWORD_FLAGS,
+                           widget,
+                           "secret-flags",
+                           G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+    nmt_editor_grid_append(NMT_EDITOR_GRID(subgrid), _("Password"), widget, NULL);
+}
+
+static void
+eap_method_populate_peap(EapMethod *method, NmtNewtWidget *subgrid)
+{
+    NmtNewtWidget           *widget;
+    static NmtNewtPopupEntry peap_version_entries[] = {{N_("Automatic"), NULL},
+                                                       {N_("Version 0"), "0"},
+                                                       {N_("Version 1"), "1"},
+                                                       {NULL, NULL}};
+    static NmtNewtPopupEntry peap_inner_methods[]   = {{N_("MSCHAPv2"), "mschapv2"},
+                                                       {N_("MD5"), "md5"},
+                                                       {N_("GTC"), "gtc"},
+                                                       {NULL, NULL}};
+
+    widget = nmt_newt_entry_new(40, NMT_NEWT_ENTRY_NONEMPTY);
+    nmt_editor_grid_append(NMT_EDITOR_GRID(subgrid), _("Anonymous identity"), widget, NULL);
+    g_object_bind_property(method->setting,
+                           NM_SETTING_802_1X_ANONYMOUS_IDENTITY,
+                           widget,
+                           "text",
+                           G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+    widget = nmt_newt_entry_new(40, 0);
+    nmt_editor_grid_append(NMT_EDITOR_GRID(subgrid), _("Domain"), widget, NULL);
+    g_object_bind_property(method->setting,
+                           NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH,
+                           widget,
+                           "text",
+                           G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+
+    widget = nmt_newt_entry_new(40, 0);
+    nmt_editor_grid_append(NMT_EDITOR_GRID(subgrid), _("CA cert"), widget, NULL);
+    nmt_newt_entry_set_validator(NMT_NEWT_ENTRY(widget), cert_validate, NULL);
+    g_object_bind_property_full(method->setting,
+                                NM_SETTING_802_1X_CA_CERT,
+                                widget,
+                                "text",
+                                G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL,
+                                certificate_to_string,
+                                certificate_from_string,
+                                NULL,
+                                NULL);
+
+    widget =
+        nmt_password_fields_new(40,
+                                NMT_PASSWORD_FIELDS_SHOW_PASSWORD | NMT_PASSWORD_FIELDS_NOT_EMPTY);
+    g_object_bind_property(method->setting,
+                           NM_SETTING_802_1X_CA_CERT_PASSWORD,
+                           widget,
+                           "password",
+                           G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+    nmt_editor_grid_append(NMT_EDITOR_GRID(subgrid), _("CA cert password"), widget, NULL);
+
+    widget = nmt_newt_popup_new(peap_version_entries);
+    g_object_bind_property(method->setting,
+                           NM_SETTING_802_1X_PHASE1_PEAPVER,
+                           widget,
+                           "active-id",
+                           G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+    nmt_editor_grid_append(NMT_EDITOR_GRID(subgrid), _("PEAP version"), widget, NULL);
+
+    widget              = nmt_newt_popup_new(peap_inner_methods);
+    method->inner_popup = widget;
+    g_signal_connect(widget,
+                     "notify::active-id",
+                     G_CALLBACK(phase2_auth_widget_changed),
+                     method->setting);
+    g_signal_connect(method->setting,
+                     "notify::" NM_SETTING_802_1X_PHASE2_AUTH,
+                     G_CALLBACK(phase2_auth_setting_changed),
+                     widget);
+    g_signal_connect(method->setting,
+                     "notify::" NM_SETTING_802_1X_PHASE2_AUTHEAP,
+                     G_CALLBACK(phase2_auth_setting_changed),
+                     widget);
+    nmt_editor_grid_append(NMT_EDITOR_GRID(subgrid), _("Inner authentication"), widget, NULL);
+
+    if (nm_setting_802_1x_get_num_eap_methods(method->setting) > 0
+        && nm_streq0(nm_setting_802_1x_get_eap_method(method->setting, 0), "peap")) {
+        phase2_auth_setting_changed(G_OBJECT(method->setting), NULL, widget);
+    }
+
+    widget = nmt_newt_entry_new(40, NMT_NEWT_ENTRY_NONEMPTY);
+    nmt_editor_grid_append(NMT_EDITOR_GRID(subgrid), _("Username"), widget, NULL);
+    g_object_bind_property(method->setting,
+                           NM_SETTING_802_1X_IDENTITY,
+                           widget,
+                           "text",
+                           G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+
+    widget = nmt_password_fields_new(40,
+                                     NMT_PASSWORD_FIELDS_SHOW_PASSWORD
+                                         | NMT_PASSWORD_FIELDS_SHOW_SECRET_FLAGS);
+    g_object_bind_property(method->setting,
+                           NM_SETTING_802_1X_PASSWORD,
+                           widget,
+                           "password",
+                           G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+    g_object_bind_property(method->setting,
+                           NM_SETTING_802_1X_PASSWORD_FLAGS,
+                           widget,
+                           "secret-flags",
+                           G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+    nmt_editor_grid_append(NMT_EDITOR_GRID(subgrid), _("Password"), widget, NULL);
+}
+
+static void
+eap_method_selected_tunneled(EapMethod *method)
+{
+    phase2_auth_widget_changed(G_OBJECT(method->inner_popup), NULL, method->setting);
+}
+
+static const EapMethodDesc eap_method_descs[] = {
+    {
+        .id             = "md5",
+        .label          = N_("MD5"),
+        .only_for_wired = TRUE,
+        .populate       = eap_method_populate_simple,
+    },
+    {
+        .id       = "pwd",
+        .label    = N_("PWD"),
+        .populate = eap_method_populate_simple,
+    },
+    {
+        .id       = "tls",
+        .label    = N_("TLS"),
+        .populate = eap_method_populate_tls,
+    },
+    {
+        .id       = "ttls",
+        .label    = N_("TTLS"),
+        .populate = eap_method_populate_ttls,
+        .selected = eap_method_selected_tunneled,
+    },
+    {
+        .id       = "peap",
+        .label    = N_("PEAP"),
+        .populate = eap_method_populate_peap,
+        .selected = eap_method_selected_tunneled,
+    },
+    {},
+};
+
+static void
+eap_method_changed(GObject *object, GParamSpec *pspec, gpointer user_data)
+{
+    Nmt8021xFields        *self = user_data;
+    Nmt8021xFieldsPrivate *priv = NMT_8021X_FIELDS_GET_PRIVATE(self);
+    int                    active;
+
+    active = nmt_newt_popup_get_active(NMT_NEWT_POPUP(priv->authentication));
+    if (priv->eap_methods[active].desc->selected)
+        priv->eap_methods[active].desc->selected(&priv->eap_methods[active]);
+}
+
+static void
+nmt_8021x_fields_constructed(GObject *object)
+{
+    Nmt8021xFields        *self    = NMT_8021X_FIELDS(object);
+    Nmt8021xFieldsPrivate *priv    = NMT_8021X_FIELDS_GET_PRIVATE(self);
+    NmtEditorGrid         *grid    = NMT_EDITOR_GRID(object);
+    gs_unref_array GArray *entries = NULL;
+    NmtNewtStack          *stack;
+    NmtNewtWidget         *subgrid;
+    NmtNewtWidget         *widget;
+    guint                  i, j;
+    EapMethod             *method;
+
+    /* Create the EAP methods popup */
+    entries = g_array_new(TRUE, TRUE, sizeof(NmtNewtPopupEntry));
+    for (i = 0; eap_method_descs[i].id; i++) {
+        NmtNewtPopupEntry entry;
+
+        if (eap_method_descs[i].only_for_wired && !priv->is_wired)
+            continue;
+
+        entry.label = (char *) eap_method_descs[i].label;
+        entry.id    = (char *) eap_method_descs[i].id;
+        g_array_append_val(entries, entry);
+    }
+    priv->authentication = nmt_newt_popup_new(nm_g_array_index_p(entries, NmtNewtPopupEntry, 0));
+    nmt_editor_grid_append(grid, "Authentication", NMT_NEWT_WIDGET(priv->authentication), NULL);
+
+    widget = nmt_newt_stack_new();
+    stack  = NMT_NEWT_STACK(widget);
+
+    /* Instantiate EAP methods and populate widgets */
+    priv->eap_methods = g_new0(EapMethod, G_N_ELEMENTS(eap_method_descs));
+    for (i = 0, j = 0; eap_method_descs[i].id; i++) {
+        if (eap_method_descs[i].only_for_wired && !priv->is_wired)
+            continue;
+
+        method          = &priv->eap_methods[j++];
+        method->desc    = &eap_method_descs[i];
+        method->setting = priv->setting;
+
+        subgrid = nmt_editor_grid_new();
+        method->desc->populate(method, subgrid);
+        nmt_newt_stack_add(stack, method->desc->id, subgrid);
+    }
+
+    g_object_bind_property(priv->authentication,
+                           "active-id",
+                           stack,
+                           "active-id",
+                           G_BINDING_SYNC_CREATE);
+    g_object_bind_property_full(priv->setting,
+                                NM_SETTING_802_1X_EAP,
+                                priv->authentication,
+                                "active-id",
+                                G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE,
+                                eap_methods_to_string,
+                                eap_methods_from_string,
+                                NULL,
+                                NULL);
+
+    /* When the popup value changes, in addition to updating the stack and the setting,
+     * we need to refresh the selected EAP method's widget to ensure the setting and
+     * the widget are in sync. */
+    g_signal_connect(priv->authentication,
+                     "notify::active-id",
+                     G_CALLBACK(eap_method_changed),
+                     self);
+
+    nmt_editor_grid_append(grid, NULL, NMT_NEWT_WIDGET(stack), NULL);
+
+    G_OBJECT_CLASS(nmt_8021x_fields_parent_class)->constructed(object);
+}
+
+static void
+nmt_8021x_fields_finalize(GObject *object)
+{
+    Nmt8021xFields        *self = NMT_8021X_FIELDS(object);
+    Nmt8021xFieldsPrivate *priv = NMT_8021X_FIELDS_GET_PRIVATE(self);
+
+    nm_clear_g_free(&priv->eap_methods);
+    g_clear_object(&priv->authentication);
+
+    G_OBJECT_CLASS(nmt_8021x_fields_parent_class)->finalize(object);
+}
+
+static void
+nmt_8021x_fields_set_property(GObject      *object,
+                              guint         prop_id,
+                              const GValue *value,
+                              GParamSpec   *pspec)
+{
+    Nmt8021xFields        *self = NMT_8021X_FIELDS(object);
+    Nmt8021xFieldsPrivate *priv = NMT_8021X_FIELDS_GET_PRIVATE(self);
+
+    switch (prop_id) {
+    case PROP_SETTING:
+        priv->setting = g_object_ref(g_value_get_object(value));
+        break;
+    case PROP_IS_WIRED:
+        priv->is_wired = g_value_get_boolean(value);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+nmt_8021x_fields_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+    Nmt8021xFields        *self = NMT_8021X_FIELDS(object);
+    Nmt8021xFieldsPrivate *priv = NMT_8021X_FIELDS_GET_PRIVATE(self);
+
+    switch (prop_id) {
+    case PROP_SETTING:
+        g_value_set_object(value, priv->setting);
+        break;
+    case PROP_IS_WIRED:
+        g_value_set_boolean(value, priv->is_wired);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+nmt_8021x_fields_class_init(Nmt8021xFieldsClass *entry_class)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS(entry_class);
+
+    object_class->constructed  = nmt_8021x_fields_constructed;
+    object_class->finalize     = nmt_8021x_fields_finalize;
+    object_class->set_property = nmt_8021x_fields_set_property;
+    object_class->get_property = nmt_8021x_fields_get_property;
+
+    /**
+     * Nmt8021xFields:setting:
+     *
+     * The backing 802.1X setting
+     */
+    g_object_class_install_property(
+        object_class,
+        PROP_SETTING,
+        g_param_spec_object("setting",
+                            "",
+                            "",
+                            NM_TYPE_SETTING_802_1X,
+                            G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+    /**
+     * Nmt8021xFields:is-wired
+     *
+     * Whether the setting is for a wired connection
+     */
+    g_object_class_install_property(
+        object_class,
+        PROP_IS_WIRED,
+        g_param_spec_boolean("is-wired",
+                             "",
+                             "",
+                             FALSE,
+                             G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+}
diff --git a/src/nmtui/nmt-8021x-fields.h b/src/nmtui/nmt-8021x-fields.h
new file mode 100644
index 00000000..dcff3852
--- /dev/null
+++ b/src/nmtui/nmt-8021x-fields.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2022 Red Hat, Inc.
+ */
+
+#ifndef NMT_8021X_FIELDS_H
+#define NMT_8021X_FIELDS_H
+
+#include "libnmt-newt/nmt-newt.h"
+
+#define NMT_TYPE_8021X_FIELDS (nmt_8021x_fields_get_type())
+#define NMT_8021X_FIELDS(obj) \
+    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_8021X_FIELDS, Nmt8021xFields))
+#define NMT_8021X_FIELDS_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_8021X_FIELDS, Nmt8021xFieldsClass))
+#define NMT_IS_8021X_FIELDS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_8021X_FIELDS))
+#define NMT_IS_8021X_FIELDS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NMT_TYPE_8021X_FIELDS))
+#define NMT_8021X_FIELDS_GET_CLASS(obj) \
+    (G_TYPE_INSTANCE_GET_CLASS((obj), NMT_TYPE_8021X_FIELDS, Nmt8021xFieldsClass))
+
+typedef struct _Nmt8021xFields Nmt8021xFields;
+
+typedef struct _Nmt8021xFieldsClass Nmt8021xFieldsClass;
+
+GType nmt_8021x_fields_get_type(void);
+
+NmtNewtWidget *nmt_8021x_fields_new(NMSetting8021x *setting, gboolean is_wired);
+
+#endif /* NMT_8021X_FIELDS_H */
diff --git a/src/nmtui/nmt-address-list.h b/src/nmtui/nmt-address-list.h
index fa356601..01669fbd 100644
--- a/src/nmtui/nmt-address-list.h
+++ b/src/nmtui/nmt-address-list.h
@@ -10,7 +10,7 @@
 
 #define NMT_TYPE_ADDRESS_LIST (nmt_address_list_get_type())
 #define NMT_ADDRESS_LIST(obj) \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_ADDRESS_LIST, NmtAddressList))
+    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_ADDRESS_LIST, NmtAddressList))
 #define NMT_ADDRESS_LIST_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_ADDRESS_LIST, NmtAddressListClass))
 #define NMT_IS_ADDRESS_LIST(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_ADDRESS_LIST))
diff --git a/src/nmtui/nmt-connect-connection-list.c b/src/nmtui/nmt-connect-connection-list.c
index f111e657..5d771b61 100644
--- a/src/nmtui/nmt-connect-connection-list.c
+++ b/src/nmtui/nmt-connect-connection-list.c
@@ -100,6 +100,7 @@ static const char *device_sort_order[]   = {"NMDeviceEthernet",
                                             NM_SETTING_TEAM_SETTING_NAME,
                                             NM_SETTING_BRIDGE_SETTING_NAME,
                                             NM_SETTING_IP_TUNNEL_SETTING_NAME,
+                                            NM_SETTING_MACSEC_SETTING_NAME,
                                             NM_SETTING_WIREGUARD_SETTING_NAME,
                                             NM_SETTING_TUN_SETTING_NAME,
                                             "NMDeviceModem",
diff --git a/src/nmtui/nmt-connect-connection-list.h b/src/nmtui/nmt-connect-connection-list.h
index 1eea4d04..bfc0c007 100644
--- a/src/nmtui/nmt-connect-connection-list.h
+++ b/src/nmtui/nmt-connect-connection-list.h
@@ -9,8 +9,10 @@
 #include "libnmt-newt/nmt-newt.h"
 
 #define NMT_TYPE_CONNECT_CONNECTION_LIST (nmt_connect_connection_list_get_type())
-#define NMT_CONNECT_CONNECTION_LIST(obj) \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_CONNECT_CONNECTION_LIST, NmtConnectConnectionList))
+#define NMT_CONNECT_CONNECTION_LIST(obj)                              \
+    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj),                            \
+                                    NMT_TYPE_CONNECT_CONNECTION_LIST, \
+                                    NmtConnectConnectionList))
 #define NMT_CONNECT_CONNECTION_LIST_CLASS(klass)               \
     (G_TYPE_CHECK_CLASS_CAST((klass),                          \
                              NMT_TYPE_CONNECT_CONNECTION_LIST, \
diff --git a/src/nmtui/nmt-device-entry.h b/src/nmtui/nmt-device-entry.h
index f66c3d8d..6265ce01 100644
--- a/src/nmtui/nmt-device-entry.h
+++ b/src/nmtui/nmt-device-entry.h
@@ -10,7 +10,7 @@
 
 #define NMT_TYPE_DEVICE_ENTRY (nmt_device_entry_get_type())
 #define NMT_DEVICE_ENTRY(obj) \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_DEVICE_ENTRY, NmtDeviceEntry))
+    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_DEVICE_ENTRY, NmtDeviceEntry))
 #define NMT_DEVICE_ENTRY_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_DEVICE_ENTRY, NmtDeviceEntryClass))
 #define NMT_IS_DEVICE_ENTRY(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_DEVICE_ENTRY))
diff --git a/src/nmtui/nmt-edit-connection-list.h b/src/nmtui/nmt-edit-connection-list.h
index a5375be4..0d23f8b1 100644
--- a/src/nmtui/nmt-edit-connection-list.h
+++ b/src/nmtui/nmt-edit-connection-list.h
@@ -10,7 +10,7 @@
 
 #define NMT_TYPE_EDIT_CONNECTION_LIST (nmt_edit_connection_list_get_type())
 #define NMT_EDIT_CONNECTION_LIST(obj) \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_EDIT_CONNECTION_LIST, NmtEditConnectionList))
+    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_EDIT_CONNECTION_LIST, NmtEditConnectionList))
 #define NMT_EDIT_CONNECTION_LIST_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_EDIT_CONNECTION_LIST, NmtEditConnectionListClass))
 #define NMT_IS_EDIT_CONNECTION_LIST(obj) \
diff --git a/src/nmtui/nmt-editor-grid.c b/src/nmtui/nmt-editor-grid.c
index b4beda92..e3524084 100644
--- a/src/nmtui/nmt-editor-grid.c
+++ b/src/nmtui/nmt-editor-grid.c
@@ -147,7 +147,7 @@ static int
 nmt_editor_grid_find_widget(NmtEditorGrid *grid, NmtNewtWidget *widget)
 {
     NmtEditorGridPrivate *priv = NMT_EDITOR_GRID_GET_PRIVATE(grid);
-    NmtEditorGridRow     *rows = (NmtEditorGridRow *) priv->rows->data;
+    NmtEditorGridRow     *rows = nm_g_array_first_p(priv->rows, NmtEditorGridRow);
     int                   i;
 
     for (i = 0; i < priv->rows->len; i++) {
@@ -182,7 +182,7 @@ nmt_editor_grid_set_row_flags(NmtEditorGrid        *grid,
                               NmtEditorGridRowFlags flags)
 {
     NmtEditorGridPrivate *priv = NMT_EDITOR_GRID_GET_PRIVATE(grid);
-    NmtEditorGridRow     *rows = (NmtEditorGridRow *) priv->rows->data;
+    NmtEditorGridRow     *rows = nm_g_array_first_p(priv->rows, NmtEditorGridRow);
     int                   i;
 
     i = nmt_editor_grid_find_widget(grid, widget);
@@ -196,7 +196,7 @@ nmt_editor_grid_remove(NmtNewtContainer *container, NmtNewtWidget *widget)
     NmtEditorGrid         *grid         = NMT_EDITOR_GRID(container);
     NmtEditorGridPrivate  *priv         = NMT_EDITOR_GRID_GET_PRIVATE(grid);
     NmtNewtContainerClass *parent_class = NMT_NEWT_CONTAINER_CLASS(nmt_editor_grid_parent_class);
-    NmtEditorGridRow      *rows         = (NmtEditorGridRow *) priv->rows->data;
+    NmtEditorGridRow      *rows         = nm_g_array_first_p(priv->rows, NmtEditorGridRow);
     int                    i;
 
     i = nmt_editor_grid_find_widget(grid, widget);
@@ -219,7 +219,7 @@ static newtComponent *
 nmt_editor_grid_get_components(NmtNewtWidget *widget)
 {
     NmtEditorGridPrivate *priv = NMT_EDITOR_GRID_GET_PRIVATE(widget);
-    NmtEditorGridRow     *rows = (NmtEditorGridRow *) priv->rows->data;
+    NmtEditorGridRow     *rows = nm_g_array_first_p(priv->rows, NmtEditorGridRow);
     newtComponent        *child_cos;
     GPtrArray            *cos;
     int                   i, c;
@@ -308,7 +308,7 @@ static void
 nmt_editor_grid_size_request(NmtNewtWidget *widget, int *width, int *height)
 {
     NmtEditorGridPrivate   *priv        = NMT_EDITOR_GRID_GET_PRIVATE(widget);
-    NmtEditorGridRow       *rows        = (NmtEditorGridRow *) priv->rows->data;
+    NmtEditorGridRow       *rows        = nm_g_array_first_p(priv->rows, NmtEditorGridRow);
     NmtEditorGridFormState *state       = get_form_state(widget);
     gboolean                add_padding = FALSE;
     int                     i;
@@ -356,7 +356,7 @@ static void
 nmt_editor_grid_size_allocate(NmtNewtWidget *widget, int x, int y, int width, int height)
 {
     NmtEditorGridPrivate   *priv  = NMT_EDITOR_GRID_GET_PRIVATE(widget);
-    NmtEditorGridRow       *rows  = (NmtEditorGridRow *) priv->rows->data;
+    NmtEditorGridRow       *rows  = nm_g_array_first_p(priv->rows, NmtEditorGridRow);
     NmtEditorGridFormState *state = get_form_state(widget);
     int                     col0_width, col1_width, col2_width;
     int                     i, row;
diff --git a/src/nmtui/nmt-editor-grid.h b/src/nmtui/nmt-editor-grid.h
index 3a917536..bf3ee491 100644
--- a/src/nmtui/nmt-editor-grid.h
+++ b/src/nmtui/nmt-editor-grid.h
@@ -10,7 +10,7 @@
 
 #define NMT_TYPE_EDITOR_GRID (nmt_editor_grid_get_type())
 #define NMT_EDITOR_GRID(obj) \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_EDITOR_GRID, NmtEditorGrid))
+    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_EDITOR_GRID, NmtEditorGrid))
 #define NMT_EDITOR_GRID_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_EDITOR_GRID, NmtEditorGridClass))
 #define NMT_IS_EDITOR_GRID(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_EDITOR_GRID))
diff --git a/src/nmtui/nmt-editor-page-device.h b/src/nmtui/nmt-editor-page-device.h
index c8dbfad9..73ebd925 100644
--- a/src/nmtui/nmt-editor-page-device.h
+++ b/src/nmtui/nmt-editor-page-device.h
@@ -11,7 +11,7 @@
 
 #define NMT_TYPE_EDITOR_PAGE_DEVICE (nmt_editor_page_device_get_type())
 #define NMT_EDITOR_PAGE_DEVICE(obj) \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_EDITOR_PAGE_DEVICE, NmtEditorPageDevice))
+    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_EDITOR_PAGE_DEVICE, NmtEditorPageDevice))
 #define NMT_EDITOR_PAGE_DEVICE_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_EDITOR_PAGE_DEVICE, NmtEditorPageDeviceClass))
 #define NMT_IS_EDITOR_PAGE_DEVICE(obj) \
diff --git a/src/nmtui/nmt-editor-page.h b/src/nmtui/nmt-editor-page.h
index 74b9e09f..f00efbf2 100644
--- a/src/nmtui/nmt-editor-page.h
+++ b/src/nmtui/nmt-editor-page.h
@@ -11,7 +11,7 @@
 
 #define NMT_TYPE_EDITOR_PAGE (nmt_editor_page_get_type())
 #define NMT_EDITOR_PAGE(obj) \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_EDITOR_PAGE, NmtEditorPage))
+    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_EDITOR_PAGE, NmtEditorPage))
 #define NMT_EDITOR_PAGE_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_EDITOR_PAGE, NmtEditorPageClass))
 #define NMT_IS_EDITOR_PAGE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_EDITOR_PAGE))
diff --git a/src/nmtui/nmt-editor-section.h b/src/nmtui/nmt-editor-section.h
index 43e6852b..e8a05b29 100644
--- a/src/nmtui/nmt-editor-section.h
+++ b/src/nmtui/nmt-editor-section.h
@@ -11,7 +11,7 @@
 
 #define NMT_TYPE_EDITOR_SECTION (nmt_editor_section_get_type())
 #define NMT_EDITOR_SECTION(obj) \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_EDITOR_SECTION, NmtEditorSection))
+    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_EDITOR_SECTION, NmtEditorSection))
 #define NMT_EDITOR_SECTION_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_EDITOR_SECTION, NmtEditorSectionClass))
 #define NMT_IS_EDITOR_SECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_EDITOR_SECTION))
diff --git a/src/nmtui/nmt-editor.c b/src/nmtui/nmt-editor.c
index 427ac017..9a64333a 100644
--- a/src/nmtui/nmt-editor.c
+++ b/src/nmtui/nmt-editor.c
@@ -35,6 +35,7 @@
 #include "nmt-page-ip-tunnel.h"
 #include "nmt-page-ip4.h"
 #include "nmt-page-ip6.h"
+#include "nmt-page-macsec.h"
 #include "nmt-page-ppp.h"
 #include "nmt-page-team.h"
 #include "nmt-page-team-port.h"
@@ -362,6 +363,8 @@ nmt_editor_constructed(GObject *object)
         page = nmt_page_bridge_new(priv->edit_connection, deventry);
     else if (nm_connection_is_type(priv->edit_connection, NM_SETTING_INFINIBAND_SETTING_NAME))
         page = nmt_page_infiniband_new(priv->edit_connection, deventry);
+    else if (nm_connection_is_type(priv->edit_connection, NM_SETTING_MACSEC_SETTING_NAME))
+        page = nmt_page_macsec_new(priv->edit_connection, deventry);
     else if (nm_connection_is_type(priv->edit_connection, NM_SETTING_PPPOE_SETTING_NAME))
         page = nmt_page_dsl_new(priv->edit_connection, deventry);
     else if (nm_connection_is_type(priv->edit_connection, NM_SETTING_TEAM_SETTING_NAME))
diff --git a/src/nmtui/nmt-editor.h b/src/nmtui/nmt-editor.h
index 602a61ae..f135fca9 100644
--- a/src/nmtui/nmt-editor.h
+++ b/src/nmtui/nmt-editor.h
@@ -9,7 +9,7 @@
 #include "libnmt-newt/nmt-newt.h"
 
 #define NMT_TYPE_EDITOR            (nmt_editor_get_type())
-#define NMT_EDITOR(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_EDITOR, NmtEditor))
+#define NMT_EDITOR(obj)            (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_EDITOR, NmtEditor))
 #define NMT_EDITOR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_EDITOR, NmtEditorClass))
 #define NMT_IS_EDITOR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_EDITOR))
 #define NMT_IS_EDITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NMT_TYPE_EDITOR))
diff --git a/src/nmtui/nmt-ip-entry.c b/src/nmtui/nmt-ip-entry.c
index 9bd0f12d..9bac888b 100644
--- a/src/nmtui/nmt-ip-entry.c
+++ b/src/nmtui/nmt-ip-entry.c
@@ -110,8 +110,8 @@ ip_entry_validate(NmtNewtEntry *entry, const char *text, gpointer user_data)
     if (!*text)
         return priv->optional;
     if (priv->prefix)
-        return nm_utils_parse_inaddr_prefix(priv->family, text, NULL, NULL);
-    return nm_utils_parse_inaddr(priv->family, text, NULL);
+        return nm_inet_parse_with_prefix_str(priv->family, text, NULL, NULL);
+    return nm_inet_parse_str(priv->family, text, NULL);
 }
 
 static void
diff --git a/src/nmtui/nmt-ip-entry.h b/src/nmtui/nmt-ip-entry.h
index 1489326d..caec5f8d 100644
--- a/src/nmtui/nmt-ip-entry.h
+++ b/src/nmtui/nmt-ip-entry.h
@@ -9,7 +9,7 @@
 #include "libnmt-newt/nmt-newt.h"
 
 #define NMT_TYPE_IP_ENTRY (nmt_ip_entry_get_type())
-#define NMT_IP_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_IP_ENTRY, NmtIPEntry))
+#define NMT_IP_ENTRY(obj) (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_IP_ENTRY, NmtIPEntry))
 #define NMT_IP_ENTRY_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_IP_ENTRY, NmtIPEntryClass))
 #define NMT_IS_IP_ENTRY(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_IP_ENTRY))
diff --git a/src/nmtui/nmt-mac-entry.h b/src/nmtui/nmt-mac-entry.h
index de44fb9d..6b5b2896 100644
--- a/src/nmtui/nmt-mac-entry.h
+++ b/src/nmtui/nmt-mac-entry.h
@@ -15,7 +15,7 @@ typedef enum {
 } NmtMacEntryType;
 
 #define NMT_TYPE_MAC_ENTRY (nmt_mac_entry_get_type())
-#define NMT_MAC_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_MAC_ENTRY, NmtMacEntry))
+#define NMT_MAC_ENTRY(obj) (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_MAC_ENTRY, NmtMacEntry))
 #define NMT_MAC_ENTRY_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_MAC_ENTRY, NmtMacEntryClass))
 #define NMT_IS_MAC_ENTRY(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_MAC_ENTRY))
diff --git a/src/nmtui/nmt-mtu-entry.h b/src/nmtui/nmt-mtu-entry.h
index 4654dabf..c81a6d5d 100644
--- a/src/nmtui/nmt-mtu-entry.h
+++ b/src/nmtui/nmt-mtu-entry.h
@@ -9,7 +9,7 @@
 #include "libnmt-newt/nmt-newt.h"
 
 #define NMT_TYPE_MTU_ENTRY (nmt_mtu_entry_get_type())
-#define NMT_MTU_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_MTU_ENTRY, NmtMtuEntry))
+#define NMT_MTU_ENTRY(obj) (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_MTU_ENTRY, NmtMtuEntry))
 #define NMT_MTU_ENTRY_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_MTU_ENTRY, NmtMtuEntryClass))
 #define NMT_IS_MTU_ENTRY(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_MTU_ENTRY))
diff --git a/src/nmtui/nmt-page-bond-port.h b/src/nmtui/nmt-page-bond-port.h
index 387acf4c..70583f94 100644
--- a/src/nmtui/nmt-page-bond-port.h
+++ b/src/nmtui/nmt-page-bond-port.h
@@ -10,7 +10,7 @@
 
 #define NMT_TYPE_PAGE_BOND_PORT (nmt_page_bond_port_get_type())
 #define NMT_PAGE_BOND_PORT(obj) \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_BOND_PORT, NmtPageBondPort))
+    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_BOND_PORT, NmtPageBondPort))
 #define NMT_PAGE_BOND_PORT_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_PAGE_BOND_PORT, NmtPageBondPortClass))
 #define NMT_IS_PAGE_BOND_PORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_PAGE_BOND_PORT))
diff --git a/src/nmtui/nmt-page-bond.h b/src/nmtui/nmt-page-bond.h
index 9481ec45..80e2ca23 100644
--- a/src/nmtui/nmt-page-bond.h
+++ b/src/nmtui/nmt-page-bond.h
@@ -9,7 +9,7 @@
 #include "nmt-editor-page-device.h"
 
 #define NMT_TYPE_PAGE_BOND (nmt_page_bond_get_type())
-#define NMT_PAGE_BOND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_BOND, NmtPageBond))
+#define NMT_PAGE_BOND(obj) (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_BOND, NmtPageBond))
 #define NMT_PAGE_BOND_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_PAGE_BOND, NmtPageBondClass))
 #define NMT_IS_PAGE_BOND(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_PAGE_BOND))
diff --git a/src/nmtui/nmt-page-bridge-port.h b/src/nmtui/nmt-page-bridge-port.h
index dc6a479c..af4dc0c5 100644
--- a/src/nmtui/nmt-page-bridge-port.h
+++ b/src/nmtui/nmt-page-bridge-port.h
@@ -10,7 +10,7 @@
 
 #define NMT_TYPE_PAGE_BRIDGE_PORT (nmt_page_bridge_port_get_type())
 #define NMT_PAGE_BRIDGE_PORT(obj) \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_BRIDGE_PORT, NmtPageBridgePort))
+    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_BRIDGE_PORT, NmtPageBridgePort))
 #define NMT_PAGE_BRIDGE_PORT_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_PAGE_BRIDGE_PORT, NmtPageBridgePortClass))
 #define NMT_IS_PAGE_BRIDGE_PORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_PAGE_BRIDGE_PORT))
diff --git a/src/nmtui/nmt-page-bridge.h b/src/nmtui/nmt-page-bridge.h
index c5c7a39c..9d621822 100644
--- a/src/nmtui/nmt-page-bridge.h
+++ b/src/nmtui/nmt-page-bridge.h
@@ -10,7 +10,7 @@
 
 #define NMT_TYPE_PAGE_BRIDGE (nmt_page_bridge_get_type())
 #define NMT_PAGE_BRIDGE(obj) \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_BRIDGE, NmtPageBridge))
+    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_BRIDGE, NmtPageBridge))
 #define NMT_PAGE_BRIDGE_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_PAGE_BRIDGE, NmtPageBridgeClass))
 #define NMT_IS_PAGE_BRIDGE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_PAGE_BRIDGE))
diff --git a/src/nmtui/nmt-page-dsl.h b/src/nmtui/nmt-page-dsl.h
index e14d67be..73aca611 100644
--- a/src/nmtui/nmt-page-dsl.h
+++ b/src/nmtui/nmt-page-dsl.h
@@ -9,7 +9,7 @@
 #include "nmt-editor-page-device.h"
 
 #define NMT_TYPE_PAGE_DSL (nmt_page_dsl_get_type())
-#define NMT_PAGE_DSL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_DSL, NmtPageDsl))
+#define NMT_PAGE_DSL(obj) (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_DSL, NmtPageDsl))
 #define NMT_PAGE_DSL_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_PAGE_DSL, NmtPageDslClass))
 #define NMT_IS_PAGE_DSL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_PAGE_DSL))
diff --git a/src/nmtui/nmt-page-ethernet.c b/src/nmtui/nmt-page-ethernet.c
index 89026d0f..77abbb40 100644
--- a/src/nmtui/nmt-page-ethernet.c
+++ b/src/nmtui/nmt-page-ethernet.c
@@ -18,9 +18,27 @@
 #include "libnm-core-aux-intern/nm-libnm-core-utils.h"
 #include "nmt-mac-entry.h"
 #include "nmt-mtu-entry.h"
+#include "nmt-8021x-fields.h"
+
+typedef struct {
+    NMSetting8021x *s_8021x;
+    NmtNewtWidget  *dot1x_fields;
+} NmtPageEthernetPrivate;
+
+struct _NmtPageEthernet {
+    NmtEditorPageDevice    parent;
+    NmtPageEthernetPrivate _priv;
+};
+
+struct _NmtPageEthernetClass {
+    NmtEditorPageDeviceClass parent;
+};
 
 G_DEFINE_TYPE(NmtPageEthernet, nmt_page_ethernet, NMT_TYPE_EDITOR_PAGE_DEVICE)
 
+#define NMT_PAGE_ETHERNET_GET_PRIVATE(self) \
+    _NM_GET_PRIVATE(self, NmtPageEthernet, NMT_IS_PAGE_ETHERNET)
+
 NmtEditorPage *
 nmt_page_ethernet_new(NMConnection *conn, NmtDeviceEntry *deventry)
 {
@@ -32,19 +50,53 @@ nmt_page_ethernet_init(NmtPageEthernet *ethernet)
 {}
 
 static void
+checkbox_8021x_changed(NmtNewtWidget *widget, GParamSpec *pspec, gpointer user_data)
+{
+    NMConnection           *conn;
+    NmtPageEthernet        *ethernet = NMT_PAGE_ETHERNET(user_data);
+    NmtPageEthernetPrivate *priv     = NMT_PAGE_ETHERNET_GET_PRIVATE(ethernet);
+    gboolean                active;
+    gboolean                has;
+
+    conn   = nmt_editor_page_get_connection(NMT_EDITOR_PAGE(ethernet));
+    active = nmt_newt_checkbox_get_active(NMT_NEWT_CHECKBOX(widget));
+    has    = !!nm_connection_get_setting(conn, NM_TYPE_SETTING_802_1X);
+
+    if (active != has) {
+        if (active)
+            nm_connection_add_setting(conn, NM_SETTING(priv->s_8021x));
+        else
+            nm_connection_remove_setting(conn, NM_TYPE_SETTING_802_1X);
+    }
+
+    nmt_newt_widget_set_visible(NMT_NEWT_WIDGET(priv->dot1x_fields), active);
+}
+
+static void
 nmt_page_ethernet_constructed(GObject *object)
 {
-    NmtPageEthernet  *ethernet = NMT_PAGE_ETHERNET(object);
-    NmtDeviceEntry   *deventry;
-    NmtEditorSection *section;
-    NmtEditorGrid    *grid;
-    NMSettingWired   *s_wired;
-    NmtNewtWidget    *widget;
-    NMConnection     *conn;
+    NmtPageEthernet        *ethernet = NMT_PAGE_ETHERNET(object);
+    NmtPageEthernetPrivate *priv     = NMT_PAGE_ETHERNET_GET_PRIVATE(object);
+    NmtDeviceEntry         *deventry;
+    NmtEditorSection       *section;
+    NmtEditorGrid          *grid;
+    NMSettingWired         *s_wired;
+    NMSetting8021x         *s_8021x;
+    NmtNewtWidget          *widget;
+    NMConnection           *conn;
+    gboolean                has_8021x;
 
     conn    = nmt_editor_page_get_connection(NMT_EDITOR_PAGE(ethernet));
     s_wired = _nm_connection_ensure_setting(conn, NM_TYPE_SETTING_WIRED);
 
+    s_8021x   = nm_connection_get_setting_802_1x(conn);
+    has_8021x = !!s_8021x;
+    if (!s_8021x) {
+        s_8021x = NM_SETTING_802_1X(nm_setting_802_1x_new());
+        nm_setting_802_1x_add_eap_method(s_8021x, "TLS");
+    }
+    priv->s_8021x = g_object_ref(s_8021x);
+
     deventry = nmt_editor_page_device_get_device_entry(NMT_EDITOR_PAGE_DEVICE(object));
     g_object_bind_property(s_wired,
                            NM_SETTING_WIRED_MAC_ADDRESS,
@@ -73,13 +125,37 @@ nmt_page_ethernet_constructed(GObject *object)
 
     nmt_editor_page_add_section(NMT_EDITOR_PAGE(ethernet), section);
 
+    /* 802.1X security */
+    section = nmt_editor_section_new(_("802.1X SECURITY"), NULL, has_8021x);
+    grid    = nmt_editor_section_get_body(section);
+    widget  = nmt_newt_checkbox_new(_("Enable 802.1X security"));
+
+    nmt_newt_checkbox_set_active(NMT_NEWT_CHECKBOX(widget), has_8021x);
+    g_signal_connect(widget, "notify::active", G_CALLBACK(checkbox_8021x_changed), ethernet);
+    nmt_editor_grid_append(grid, NULL, widget, NULL);
+    priv->dot1x_fields = NMT_NEWT_WIDGET(nmt_8021x_fields_new(s_8021x, TRUE));
+    checkbox_8021x_changed(widget, NULL, ethernet);
+    nmt_editor_grid_append(grid, NULL, priv->dot1x_fields, NULL);
+    nmt_editor_page_add_section(NMT_EDITOR_PAGE(ethernet), section);
+
     G_OBJECT_CLASS(nmt_page_ethernet_parent_class)->constructed(object);
 }
 
 static void
+nmt_page_ethernet_finalize(GObject *object)
+{
+    NmtPageEthernetPrivate *priv = NMT_PAGE_ETHERNET_GET_PRIVATE(object);
+
+    g_clear_object(&priv->s_8021x);
+
+    G_OBJECT_CLASS(nmt_page_ethernet_parent_class)->finalize(object);
+}
+
+static void
 nmt_page_ethernet_class_init(NmtPageEthernetClass *ethernet_class)
 {
     GObjectClass *object_class = G_OBJECT_CLASS(ethernet_class);
 
     object_class->constructed = nmt_page_ethernet_constructed;
+    object_class->finalize    = nmt_page_ethernet_finalize;
 }
diff --git a/src/nmtui/nmt-page-ethernet.h b/src/nmtui/nmt-page-ethernet.h
index f7e6cf15..65c2f74c 100644
--- a/src/nmtui/nmt-page-ethernet.h
+++ b/src/nmtui/nmt-page-ethernet.h
@@ -10,7 +10,7 @@
 
 #define NMT_TYPE_PAGE_ETHERNET (nmt_page_ethernet_get_type())
 #define NMT_PAGE_ETHERNET(obj) \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_ETHERNET, NmtPageEthernet))
+    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_ETHERNET, NmtPageEthernet))
 #define NMT_PAGE_ETHERNET_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_PAGE_ETHERNET, NmtPageEthernetClass))
 #define NMT_IS_PAGE_ETHERNET(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_PAGE_ETHERNET))
@@ -18,15 +18,8 @@
 #define NMT_PAGE_ETHERNET_GET_CLASS(obj) \
     (G_TYPE_INSTANCE_GET_CLASS((obj), NMT_TYPE_PAGE_ETHERNET, NmtPageEthernetClass))
 
-typedef struct {
-    NmtEditorPageDevice parent;
-
-} NmtPageEthernet;
-
-typedef struct {
-    NmtEditorPageDeviceClass parent;
-
-} NmtPageEthernetClass;
+typedef struct _NmtPageEthernet      NmtPageEthernet;
+typedef struct _NmtPageEthernetClass NmtPageEthernetClass;
 
 GType nmt_page_ethernet_get_type(void);
 
diff --git a/src/nmtui/nmt-page-infiniband.h b/src/nmtui/nmt-page-infiniband.h
index da8fb3d6..80fc479f 100644
--- a/src/nmtui/nmt-page-infiniband.h
+++ b/src/nmtui/nmt-page-infiniband.h
@@ -10,7 +10,7 @@
 
 #define NMT_TYPE_PAGE_INFINIBAND (nmt_page_infiniband_get_type())
 #define NMT_PAGE_INFINIBAND(obj) \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_INFINIBAND, NmtPageInfiniband))
+    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_INFINIBAND, NmtPageInfiniband))
 #define NMT_PAGE_INFINIBAND_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_PAGE_INFINIBAND, NmtPageInfinibandClass))
 #define NMT_IS_PAGE_INFINIBAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_PAGE_INFINIBAND))
diff --git a/src/nmtui/nmt-page-ip-tunnel.h b/src/nmtui/nmt-page-ip-tunnel.h
index dcc27880..0709dfb0 100644
--- a/src/nmtui/nmt-page-ip-tunnel.h
+++ b/src/nmtui/nmt-page-ip-tunnel.h
@@ -10,7 +10,7 @@
 
 #define NMT_TYPE_PAGE_IP_TUNNEL (nmt_page_ip_tunnel_get_type())
 #define NMT_PAGE_IP_TUNNEL(obj) \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_IP_TUNNEL, NmtPageIPTunnel))
+    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_IP_TUNNEL, NmtPageIPTunnel))
 #define NMT_PAGE_IP_TUNNEL_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_PAGE_IP_TUNNEL, NmtPageIPTunnelClass))
 #define NMT_IS_PAGE_IP_TUNNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_PAGE_IP_TUNNEL))
diff --git a/src/nmtui/nmt-page-ip4.h b/src/nmtui/nmt-page-ip4.h
index 52d3c842..2c3a16cb 100644
--- a/src/nmtui/nmt-page-ip4.h
+++ b/src/nmtui/nmt-page-ip4.h
@@ -9,7 +9,7 @@
 #include "nmt-editor-page.h"
 
 #define NMT_TYPE_PAGE_IP4 (nmt_page_ip4_get_type())
-#define NMT_PAGE_IP4(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_IP4, NmtPageIP4))
+#define NMT_PAGE_IP4(obj) (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_IP4, NmtPageIP4))
 #define NMT_PAGE_IP4_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_PAGE_IP4, NmtPageIP4Class))
 #define NMT_IS_PAGE_IP4(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_PAGE_IP4))
diff --git a/src/nmtui/nmt-page-ip6.h b/src/nmtui/nmt-page-ip6.h
index cefb36b9..457e0825 100644
--- a/src/nmtui/nmt-page-ip6.h
+++ b/src/nmtui/nmt-page-ip6.h
@@ -9,7 +9,7 @@
 #include "nmt-editor-page.h"
 
 #define NMT_TYPE_PAGE_IP6 (nmt_page_ip6_get_type())
-#define NMT_PAGE_IP6(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_IP6, NmtPageIP6))
+#define NMT_PAGE_IP6(obj) (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_IP6, NmtPageIP6))
 #define NMT_PAGE_IP6_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_PAGE_IP6, NmtPageIP6Class))
 #define NMT_IS_PAGE_IP6(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_PAGE_IP6))
diff --git a/src/nmtui/nmt-page-macsec.c b/src/nmtui/nmt-page-macsec.c
new file mode 100644
index 00000000..6a017486
--- /dev/null
+++ b/src/nmtui/nmt-page-macsec.c
@@ -0,0 +1,196 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2022 Red Hat, Inc.
+ */
+/**
+ * SECTION:nmt-page-macsec
+ * @short_description: The editor page for MACsec connections
+ */
+
+#include "libnm-client-aux-extern/nm-default-client.h"
+
+#include "nmt-page-macsec.h"
+
+#include "libnm-core-aux-intern/nm-libnm-core-utils.h"
+#include "nmt-device-entry.h"
+#include "nmt-password-fields.h"
+#include "nmt-8021x-fields.h"
+
+typedef struct {
+    NMSetting8021x *s_8021x;
+} NmtPageMacsecPrivate;
+
+struct _NmtPageMacsec {
+    NmtEditorPageDevice  parent;
+    NmtPageMacsecPrivate _priv;
+};
+
+struct _NmtPageMacsecClass {
+    NmtEditorPageDeviceClass parent;
+};
+
+G_DEFINE_TYPE(NmtPageMacsec, nmt_page_macsec, NMT_TYPE_EDITOR_PAGE_DEVICE)
+
+#define NMT_PAGE_MACSEC_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NmtPageMacsec, NMT_IS_PAGE_MACSEC)
+
+static void
+nmt_page_macsec_init(NmtPageMacsec *macsec)
+{}
+
+NmtEditorPage *
+nmt_page_macsec_new(NMConnection *conn, NmtDeviceEntry *deventry)
+{
+    return g_object_new(NMT_TYPE_PAGE_MACSEC, "connection", conn, "device-entry", deventry, NULL);
+}
+
+static void
+macsec_mode_changed(NmtNewtWidget *widget, GParamSpec *pspec, gpointer user_data)
+{
+    NmtPageMacsec        *macsec = user_data;
+    NmtPageMacsecPrivate *priv   = NMT_PAGE_MACSEC_GET_PRIVATE(macsec);
+    NMConnection         *conn;
+    gboolean              mode_eap;
+    gboolean              has_setting;
+
+    conn        = nmt_editor_page_get_connection(NMT_EDITOR_PAGE(macsec));
+    has_setting = !!nm_connection_get_setting(conn, NM_TYPE_SETTING_802_1X);
+    mode_eap    = nmt_newt_popup_get_active(NMT_NEWT_POPUP(widget)) == NM_SETTING_MACSEC_MODE_EAP;
+
+    if (mode_eap != has_setting) {
+        if (mode_eap)
+            nm_connection_add_setting(conn, NM_SETTING(priv->s_8021x));
+        else
+            nm_connection_remove_setting(conn, NM_TYPE_SETTING_802_1X);
+    }
+}
+
+static NmtNewtPopupEntry macsec_mode[] = {{N_("PSK"), "psk"}, {N_("EAP"), "eap"}, {NULL, NULL}};
+
+static NmtNewtPopupEntry macsec_validation[] = {{N_("Disabled"), "disabled"},
+                                                {N_("Check"), "check"},
+                                                {N_("Strict"), "strict"},
+                                                {NULL, NULL}};
+
+static void
+nmt_page_macsec_constructed(GObject *object)
+{
+    NmtPageMacsec        *macsec = NMT_PAGE_MACSEC(object);
+    NmtPageMacsecPrivate *priv   = NMT_PAGE_MACSEC_GET_PRIVATE(macsec);
+    NMConnection         *conn;
+    NMSettingMacsec      *s_macsec;
+    NMSetting8021x       *s_8021x;
+    NmtNewtStack         *stack;
+    NmtEditorSection     *section;
+    NmtEditorGrid        *grid;
+    NmtNewtWidget        *subgrid;
+    NmtNewtWidget        *widget;
+    NmtNewtWidget        *mode;
+
+    conn     = nmt_editor_page_get_connection(NMT_EDITOR_PAGE(macsec));
+    s_macsec = _nm_connection_ensure_setting(conn, NM_TYPE_SETTING_MACSEC);
+
+    s_8021x = nm_connection_get_setting_802_1x(conn);
+    if (!s_8021x) {
+        s_8021x = NM_SETTING_802_1X(nm_setting_802_1x_new());
+        nm_setting_802_1x_add_eap_method(s_8021x, "MD5");
+    }
+    priv->s_8021x = g_object_ref(s_8021x);
+
+    section = nmt_editor_section_new(_("MACsec"), NULL, TRUE);
+    grid    = nmt_editor_section_get_body(section);
+
+    widget = nmt_device_entry_new(_("Parent device"), 40, G_TYPE_NONE);
+    g_object_bind_property(s_macsec,
+                           NM_SETTING_MACSEC_PARENT,
+                           widget,
+                           "interface-name",
+                           G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+    nmt_editor_grid_append(grid, NULL, widget, NULL);
+
+    nmt_editor_grid_append(grid, NULL, nmt_newt_separator_new(), NULL);
+
+    widget = nmt_newt_popup_new((NmtNewtPopupEntry *) &macsec_mode);
+    nmt_editor_grid_append(grid, _("Mode"), widget, NULL);
+    mode = widget;
+
+    widget = nmt_newt_stack_new();
+    stack  = NMT_NEWT_STACK(widget);
+
+    /* PSK stack grid */
+    subgrid = nmt_editor_grid_new();
+    widget =
+        nmt_password_fields_new(40,
+                                NMT_PASSWORD_FIELDS_SHOW_PASSWORD | NMT_PASSWORD_FIELDS_NOT_EMPTY);
+    g_object_bind_property(s_macsec,
+                           NM_SETTING_MACSEC_MKA_CAK,
+                           widget,
+                           "password",
+                           G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+    nmt_editor_grid_append(NMT_EDITOR_GRID(subgrid), _("CAK"), widget, NULL);
+
+    widget = nmt_newt_entry_new(40, 0);
+    nmt_editor_grid_append(NMT_EDITOR_GRID(subgrid), _("CKN"), widget, NULL);
+    g_object_bind_property(s_macsec,
+                           NM_SETTING_MACSEC_MKA_CKN,
+                           widget,
+                           "text",
+                           G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+
+    nmt_newt_stack_add(stack, "psk", subgrid);
+
+    /* EAP stack grid */
+    subgrid = nmt_editor_grid_new();
+    widget  = NMT_NEWT_WIDGET(nmt_8021x_fields_new(s_8021x, TRUE));
+    nmt_editor_grid_append(NMT_EDITOR_GRID(subgrid), NULL, widget, NULL);
+    nmt_newt_stack_add(stack, "eap", subgrid);
+
+    g_object_bind_property(mode, "active-id", stack, "active-id", G_BINDING_SYNC_CREATE);
+    nmt_editor_grid_append(grid, NULL, NMT_NEWT_WIDGET(stack), NULL);
+
+    g_object_bind_property(s_macsec,
+                           NM_SETTING_MACSEC_MODE,
+                           mode,
+                           "active",
+                           G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+    g_signal_connect(mode, "notify::active", G_CALLBACK(macsec_mode_changed), macsec);
+    macsec_mode_changed(mode, NULL, macsec);
+
+    nmt_editor_grid_append(grid, NULL, nmt_newt_separator_new(), NULL);
+
+    /* Other MACsec options */
+    widget = nmt_newt_popup_new((NmtNewtPopupEntry *) &macsec_validation);
+    nmt_editor_grid_append(grid, _("Validation"), widget, NULL);
+    g_object_bind_property(s_macsec,
+                           NM_SETTING_MACSEC_VALIDATION,
+                           widget,
+                           "active",
+                           G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+
+    widget = nmt_newt_entry_new(40, 0);
+    nmt_editor_grid_append(grid, _("SCI port"), widget, NULL);
+    g_object_bind_property(s_macsec,
+                           NM_SETTING_MACSEC_PORT,
+                           widget,
+                           "text",
+                           G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+
+    widget = nmt_newt_checkbox_new(_("Encrypt traffic"));
+    nmt_editor_grid_append(grid, NULL, widget, NULL);
+    g_object_bind_property(s_macsec,
+                           NM_SETTING_MACSEC_ENCRYPT,
+                           widget,
+                           "active",
+                           G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+
+    nmt_editor_page_add_section(NMT_EDITOR_PAGE(macsec), section);
+
+    G_OBJECT_CLASS(nmt_page_macsec_parent_class)->constructed(object);
+}
+
+static void
+nmt_page_macsec_class_init(NmtPageMacsecClass *macsec_class)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS(macsec_class);
+
+    object_class->constructed = nmt_page_macsec_constructed;
+}
diff --git a/src/nmtui/nmt-page-macsec.h b/src/nmtui/nmt-page-macsec.h
new file mode 100644
index 00000000..963bdba0
--- /dev/null
+++ b/src/nmtui/nmt-page-macsec.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2022 Red Hat, Inc.
+ */
+
+#ifndef NMT_PAGE_MACSEC_H
+#define NMT_PAGE_MACSEC_H
+
+#include "nmt-editor-page-device.h"
+
+#define NMT_TYPE_PAGE_MACSEC (nmt_page_macsec_get_type())
+#define NMT_PAGE_MACSEC(obj) \
+    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_MACSEC, NmtPageMacsec))
+#define NMT_PAGE_MACSEC_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_PAGE_MACSEC, NmtPageMacsecClass))
+#define NMT_IS_PAGE_MACSEC(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_PAGE_MACSEC))
+#define NMT_IS_PAGE_MACSEC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NMT_TYPE_PAGE_MACSEC))
+#define NMT_PAGE_MACSEC_GET_CLASS(obj) \
+    (G_TYPE_INSTANCE_GET_CLASS((obj), NMT_TYPE_PAGE_MACSEC, NmtPageMacsecClass))
+
+typedef struct _NmtPageMacsec      NmtPageMacsec;
+typedef struct _NmtPageMacsecClass NmtPageMacsecClass;
+
+GType nmt_page_macsec_get_type(void);
+
+NmtEditorPage *nmt_page_macsec_new(NMConnection *conn, NmtDeviceEntry *deventry);
+
+#endif /* NMT_PAGE_MACSEC_H */
diff --git a/src/nmtui/nmt-page-ppp.h b/src/nmtui/nmt-page-ppp.h
index 8538c102..e587ea31 100644
--- a/src/nmtui/nmt-page-ppp.h
+++ b/src/nmtui/nmt-page-ppp.h
@@ -9,7 +9,7 @@
 #include "nmt-editor-page.h"
 
 #define NMT_TYPE_PAGE_PPP (nmt_page_ppp_get_type())
-#define NMT_PAGE_PPP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_PPP, NmtPagePpp))
+#define NMT_PAGE_PPP(obj) (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_PPP, NmtPagePpp))
 #define NMT_PAGE_PPP_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_PAGE_PPP, NmtPagePppClass))
 #define NMT_IS_PAGE_PPP(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_PAGE_PPP))
diff --git a/src/nmtui/nmt-page-team-port.h b/src/nmtui/nmt-page-team-port.h
index de6e744e..9d88e91b 100644
--- a/src/nmtui/nmt-page-team-port.h
+++ b/src/nmtui/nmt-page-team-port.h
@@ -10,7 +10,7 @@
 
 #define NMT_TYPE_PAGE_TEAM_PORT (nmt_page_team_port_get_type())
 #define NMT_PAGE_TEAM_PORT(obj) \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_TEAM_PORT, NmtPageTeamPort))
+    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_TEAM_PORT, NmtPageTeamPort))
 #define NMT_PAGE_TEAM_PORT_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_PAGE_TEAM_PORT, NmtPageTeamPortClass))
 #define NMT_IS_PAGE_TEAM_PORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_PAGE_TEAM_PORT))
diff --git a/src/nmtui/nmt-page-team.h b/src/nmtui/nmt-page-team.h
index 5eb792ae..3cdca03c 100644
--- a/src/nmtui/nmt-page-team.h
+++ b/src/nmtui/nmt-page-team.h
@@ -9,7 +9,7 @@
 #include "nmt-editor-page-device.h"
 
 #define NMT_TYPE_PAGE_TEAM (nmt_page_team_get_type())
-#define NMT_PAGE_TEAM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_TEAM, NmtPageTeam))
+#define NMT_PAGE_TEAM(obj) (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_TEAM, NmtPageTeam))
 #define NMT_PAGE_TEAM_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_PAGE_TEAM, NmtPageTeamClass))
 #define NMT_IS_PAGE_TEAM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_PAGE_TEAM))
diff --git a/src/nmtui/nmt-page-vlan.h b/src/nmtui/nmt-page-vlan.h
index deebda00..086d4836 100644
--- a/src/nmtui/nmt-page-vlan.h
+++ b/src/nmtui/nmt-page-vlan.h
@@ -9,7 +9,7 @@
 #include "nmt-editor-page-device.h"
 
 #define NMT_TYPE_PAGE_VLAN (nmt_page_vlan_get_type())
-#define NMT_PAGE_VLAN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_VLAN, NmtPageVlan))
+#define NMT_PAGE_VLAN(obj) (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_VLAN, NmtPageVlan))
 #define NMT_PAGE_VLAN_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_PAGE_VLAN, NmtPageVlanClass))
 #define NMT_IS_PAGE_VLAN(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_PAGE_VLAN))
diff --git a/src/nmtui/nmt-page-wifi.c b/src/nmtui/nmt-page-wifi.c
index 60960e64..55feaee2 100644
--- a/src/nmtui/nmt-page-wifi.c
+++ b/src/nmtui/nmt-page-wifi.c
@@ -23,6 +23,7 @@
 #include "nmt-mac-entry.h"
 #include "nmt-mtu-entry.h"
 #include "nmt-password-fields.h"
+#include "nmt-8021x-fields.h"
 
 #include "nm-editor-bindings.h"
 
@@ -33,6 +34,7 @@ G_DEFINE_TYPE(NmtPageWifi, nmt_page_wifi, NMT_TYPE_EDITOR_PAGE_DEVICE)
 
 typedef struct {
     NMSettingWirelessSecurity *s_wsec;
+    NMSetting8021x            *s_8021x;
 
 } NmtPageWifiPrivate;
 
@@ -58,16 +60,22 @@ static NmtNewtPopupEntry wifi_band[] = {{NC_("Wi-Fi", "Automatic"), NULL},
                                         {N_("B/G (2.4 GHz)"), "bg"},
                                         {NULL, NULL}};
 
-static NmtNewtPopupEntry wifi_security[] = {{NC_("Wi-Fi security", "None"), "none"},
-                                            {N_("WPA & WPA2 Personal"), "wpa-personal"},
-                                            {N_("WPA3 Personal"), "wpa3-personal"},
-                                            {N_("WPA & WPA2 Enterprise"), "wpa-enterprise"},
-                                            {N_("WEP 40/128-bit Key (Hex or ASCII)"), "wep-key"},
-                                            {N_("WEP 128-bit Passphrase"), "wep-passphrase"},
-                                            {N_("Dynamic WEP (802.1x)"), "dynamic-wep"},
-                                            {N_("LEAP"), "leap"},
-                                            {N_("Enhanced Open (OWE)"), "owe"},
-                                            {NULL, NULL}};
+static struct {
+    NmtNewtPopupEntry common[6];
+    NmtNewtPopupEntry wep[4];
+} wifi_security = {
+    {{NC_("Wi-Fi security", "None"), "none"},
+     {N_("WPA & WPA2 Personal"), "wpa-personal"},
+     {N_("WPA3 Personal"), "wpa3-personal"},
+     {N_("WPA & WPA2 Enterprise"), "wpa-enterprise"},
+     {N_("LEAP"), "leap"},
+     {N_("Enhanced Open (OWE)"), "owe"}},
+    {{N_("WEP 40/128-bit Key (Hex or ASCII)"), "wep-key"},
+     {N_("WEP 128-bit Passphrase"), "wep-passphrase"},
+     {N_("Dynamic WEP (802.1x)"), "dynamic-wep"},
+     {NULL, NULL}},
+
+};
 
 static NmtNewtPopupEntry wep_index[] = {{NC_("WEP key index", "1 (Default)"), "1"},
                                         {NC_("WEP key index", "2"), "2"},
@@ -160,6 +168,7 @@ nmt_page_wifi_constructed(GObject *object)
     NmtEditorGrid             *grid;
     NMSettingWireless         *s_wireless;
     NMSettingWirelessSecurity *s_wsec;
+    NMSetting8021x            *s_8021x;
     NmtNewtWidget             *widget, *hbox, *subgrid;
     NmtNewtWidget             *mode, *band, *security, *entry;
     NmtNewtStack              *stack;
@@ -175,7 +184,14 @@ nmt_page_wifi_constructed(GObject *object)
          */
         s_wsec = NM_SETTING_WIRELESS_SECURITY(nm_setting_wireless_security_new());
     }
-    priv->s_wsec = g_object_ref_sink(s_wsec);
+    priv->s_wsec = g_object_ref(s_wsec);
+
+    s_8021x = nm_connection_get_setting_802_1x(conn);
+    if (!s_8021x) {
+        s_8021x = NM_SETTING_802_1X(nm_setting_802_1x_new());
+        nm_setting_802_1x_add_eap_method(s_8021x, "TLS");
+    }
+    priv->s_8021x = g_object_ref(s_8021x);
 
     deventry = nmt_editor_page_device_get_device_entry(NMT_EDITOR_PAGE_DEVICE(object));
     g_object_bind_property(s_wireless,
@@ -249,7 +265,7 @@ nmt_page_wifi_constructed(GObject *object)
 
     nmt_editor_grid_append(grid, NULL, nmt_newt_separator_new(), NULL);
 
-    widget = nmt_newt_popup_new(wifi_security);
+    widget = nmt_newt_popup_new((NmtNewtPopupEntry *) &wifi_security);
     nmt_editor_grid_append(grid, _("Security"), widget, NULL);
     security = widget;
 
@@ -273,9 +289,7 @@ nmt_page_wifi_constructed(GObject *object)
     nmt_newt_stack_add(stack, "wpa3-personal", subgrid);
 
     /* "wpa-enterprise" */
-    // FIXME
-    widget = nmt_newt_label_new(_("(No support for wpa-enterprise yet...)"));
-    nmt_newt_stack_add(stack, "wpa-enterprise", widget);
+    nmt_newt_stack_add(stack, "wpa-enterprise", nmt_8021x_fields_new(s_8021x, FALSE));
 
     /* wep-key */
     subgrid = nmt_editor_grid_new();
@@ -349,6 +363,7 @@ nmt_page_wifi_constructed(GObject *object)
     g_object_bind_property(security, "active-id", stack, "active-id", G_BINDING_SYNC_CREATE);
     nm_editor_bind_wireless_security_method(conn,
                                             s_wsec,
+                                            s_8021x,
                                             security,
                                             "active-id",
                                             G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
@@ -403,4 +418,9 @@ nmt_page_wifi_class_init(NmtPageWifiClass *wifi_class)
 
     object_class->constructed = nmt_page_wifi_constructed;
     object_class->finalize    = nmt_page_wifi_finalize;
+
+    if (!getenv("NM_ALLOW_INSECURE_WEP")) {
+        wifi_security.wep[0].label = NULL;
+        wifi_security.wep[0].id    = NULL;
+    }
 }
diff --git a/src/nmtui/nmt-page-wifi.h b/src/nmtui/nmt-page-wifi.h
index c01fdd1d..d388e6de 100644
--- a/src/nmtui/nmt-page-wifi.h
+++ b/src/nmtui/nmt-page-wifi.h
@@ -9,7 +9,7 @@
 #include "nmt-editor-page-device.h"
 
 #define NMT_TYPE_PAGE_WIFI (nmt_page_wifi_get_type())
-#define NMT_PAGE_WIFI(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_WIFI, NmtPageWifi))
+#define NMT_PAGE_WIFI(obj) (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_WIFI, NmtPageWifi))
 #define NMT_PAGE_WIFI_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_PAGE_WIFI, NmtPageWifiClass))
 #define NMT_IS_PAGE_WIFI(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_PAGE_WIFI))
diff --git a/src/nmtui/nmt-page-wireguard.h b/src/nmtui/nmt-page-wireguard.h
index 8e39139c..6024c1eb 100644
--- a/src/nmtui/nmt-page-wireguard.h
+++ b/src/nmtui/nmt-page-wireguard.h
@@ -10,7 +10,7 @@
 
 #define NMT_TYPE_PAGE_WIREGUARD (nmt_page_wireguard_get_type())
 #define NMT_PAGE_WIREGUARD(obj) \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_WIREGUARD, NmtPageWireGuard))
+    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PAGE_WIREGUARD, NmtPageWireGuard))
 #define NMT_PAGE_WIREGUARD_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_PAGE_WIREGUARD, NmtPageWireGuardClass))
 #define NMT_IS_PAGE_WIREGUARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_PAGE_WIREGUARD))
diff --git a/src/nmtui/nmt-password-dialog.c b/src/nmtui/nmt-password-dialog.c
index 6189997f..75194d7b 100644
--- a/src/nmtui/nmt-password-dialog.c
+++ b/src/nmtui/nmt-password-dialog.c
@@ -71,8 +71,6 @@ nmt_password_dialog_new(const char *request_id,
                         prompt,
                         "secrets",
                         secrets,
-                        "escape-exits",
-                        TRUE,
                         NULL);
 }
 
diff --git a/src/nmtui/nmt-password-dialog.h b/src/nmtui/nmt-password-dialog.h
index 4c60e33d..ec7ae830 100644
--- a/src/nmtui/nmt-password-dialog.h
+++ b/src/nmtui/nmt-password-dialog.h
@@ -10,7 +10,7 @@
 
 #define NMT_TYPE_PASSWORD_DIALOG (nmt_password_dialog_get_type())
 #define NMT_PASSWORD_DIALOG(obj) \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PASSWORD_DIALOG, NmtPasswordDialog))
+    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PASSWORD_DIALOG, NmtPasswordDialog))
 #define NMT_PASSWORD_DIALOG_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_PASSWORD_DIALOG, NmtPasswordDialogClass))
 #define NMT_IS_PASSWORD_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_PASSWORD_DIALOG))
diff --git a/src/nmtui/nmt-password-fields.c b/src/nmtui/nmt-password-fields.c
index 09573c72..9d8ea66b 100644
--- a/src/nmtui/nmt-password-fields.c
+++ b/src/nmtui/nmt-password-fields.c
@@ -25,7 +25,7 @@ typedef struct {
     NmtPasswordFieldsExtras extras;
 
     NmtNewtEntry    *entry;
-    NmtNewtCheckbox *always_ask;
+    NmtNewtPopup    *secret_flags;
     NmtNewtCheckbox *show_password;
 
     char *init_password;
@@ -37,7 +37,7 @@ enum {
     PROP_WIDTH,
     PROP_EXTRAS,
     PROP_PASSWORD,
-    PROP_ALWAYS_ASK,
+    PROP_SECRET_FLAGS,
     PROP_SHOW_PASSWORD,
 
     LAST_PROP
@@ -45,8 +45,9 @@ enum {
 
 /**
  * NmtPasswordFieldsExtras:
- * @NMT_PASSWORD_FIELDS_ALWAYS_ASK: show an "Always ask" checkbox
+ * @NMT_PASSWORD_FIELDS_SHOW_SECRET_FLAGS: show the secret flags popup
  * @NMT_PASSWORD_FIELDS_SHOW_PASSWORD: show a "Show password" checkbox
+ * @NMT_PASSWORD_FIELDS_NOT_EMPTY: return NULL instead of empty string
  *
  * Extra widgets to include in an #NmtPasswordFields
  */
@@ -82,30 +83,64 @@ static const char *
 nmt_password_fields_get_password(NmtPasswordFields *fields)
 {
     NmtPasswordFieldsPrivate *priv = NMT_PASSWORD_FIELDS_GET_PRIVATE(fields);
+    const char               *text;
 
-    return nmt_newt_entry_get_text(priv->entry);
+    text = nmt_newt_entry_get_text(priv->entry);
+    if (priv->extras & NMT_PASSWORD_FIELDS_NOT_EMPTY)
+        return nm_str_not_empty(text);
+
+    return text;
 }
 
 static void
-always_ask_changed(GObject *object, GParamSpec *pspec, gpointer fields)
+show_password_changed(GObject *object, GParamSpec *pspec, gpointer fields)
 {
-    g_object_notify(fields, "always-ask");
+    g_object_notify(fields, "show-password");
 }
 
 static void
-show_password_changed(GObject *object, GParamSpec *pspec, gpointer fields)
+secret_flags_changed(GObject *object, GParamSpec *pspec, gpointer fields)
 {
-    g_object_notify(fields, "show-password");
+    g_object_notify(fields, "secret-flags");
+}
+
+static guint
+secret_flags_from_popup_idx(guint idx)
+{
+    switch (idx) {
+    case 1:
+        return NM_SETTING_SECRET_FLAG_AGENT_OWNED;
+    case 2:
+        return NM_SETTING_SECRET_FLAG_NOT_SAVED;
+    default:
+    case 0:
+        return NM_SETTING_SECRET_FLAG_NONE;
+    }
+}
+
+static guint
+secret_flags_to_popup_idx(guint flags)
+{
+    if (flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED)
+        return 1;
+    if (flags & NM_SETTING_SECRET_FLAG_NOT_SAVED)
+        return 2;
+    return 0;
 }
 
 static void
 nmt_password_fields_init(NmtPasswordFields *fields)
 {
-    NmtPasswordFieldsPrivate *priv = NMT_PASSWORD_FIELDS_GET_PRIVATE(fields);
-
-    priv->entry = NMT_NEWT_ENTRY(nmt_newt_entry_new(-1, 0));
-    priv->always_ask =
-        NMT_NEWT_CHECKBOX(nmt_newt_checkbox_new(_("Ask for this password every time")));
+    NmtPasswordFieldsPrivate *priv      = NMT_PASSWORD_FIELDS_GET_PRIVATE(fields);
+    NmtNewtPopupEntry         entries[] = {
+        {_("Store password for all users"), NULL},
+        {_("Store password only for this user"), NULL},
+        {_("Ask password every time"), NULL},
+        {},
+    };
+
+    priv->entry         = NMT_NEWT_ENTRY(nmt_newt_entry_new(-1, 0));
+    priv->secret_flags  = NMT_NEWT_POPUP(nmt_newt_popup_new(entries));
     priv->show_password = NMT_NEWT_CHECKBOX(nmt_newt_checkbox_new(_("Show password")));
 }
 
@@ -114,20 +149,12 @@ nmt_password_fields_constructed(GObject *object)
 {
     NmtPasswordFieldsPrivate *priv = NMT_PASSWORD_FIELDS_GET_PRIVATE(object);
     NmtNewtGrid              *grid = NMT_NEWT_GRID(object);
+    guint                     row  = 0;
 
-    nmt_newt_grid_add(grid, NMT_NEWT_WIDGET(priv->entry), 0, 0);
-
-    if (priv->extras & NMT_PASSWORD_FIELDS_ALWAYS_ASK) {
-        nmt_newt_grid_add(grid, NMT_NEWT_WIDGET(priv->always_ask), 0, 1);
-        g_signal_connect(priv->always_ask,
-                         "notify::active",
-                         G_CALLBACK(always_ask_changed),
-                         object);
-    } else
-        g_clear_object(&priv->always_ask);
+    nmt_newt_grid_add(grid, NMT_NEWT_WIDGET(priv->entry), 0, row++);
 
     if (priv->extras & NMT_PASSWORD_FIELDS_SHOW_PASSWORD) {
-        nmt_newt_grid_add(grid, NMT_NEWT_WIDGET(priv->show_password), 0, 2);
+        nmt_newt_grid_add(grid, NMT_NEWT_WIDGET(priv->show_password), 0, row++);
         g_signal_connect(priv->show_password,
                          "notify::active",
                          G_CALLBACK(show_password_changed),
@@ -140,6 +167,15 @@ nmt_password_fields_constructed(GObject *object)
     } else
         g_clear_object(&priv->show_password);
 
+    if (priv->extras & NMT_PASSWORD_FIELDS_SHOW_SECRET_FLAGS) {
+        nmt_newt_grid_add(grid, NMT_NEWT_WIDGET(priv->secret_flags), 0, row++);
+        g_signal_connect(priv->secret_flags,
+                         "notify::active-id",
+                         G_CALLBACK(secret_flags_changed),
+                         object);
+    } else
+        g_clear_object(&priv->secret_flags);
+
     g_object_bind_property(priv->entry,
                            "text",
                            object,
@@ -154,9 +190,9 @@ nmt_password_fields_finalize(GObject *object)
 {
     NmtPasswordFieldsPrivate *priv = NMT_PASSWORD_FIELDS_GET_PRIVATE(object);
 
-    if (priv->always_ask) {
-        g_signal_handlers_disconnect_by_func(priv->always_ask,
-                                             G_CALLBACK(always_ask_changed),
+    if (priv->secret_flags) {
+        g_signal_handlers_disconnect_by_func(priv->secret_flags,
+                                             G_CALLBACK(secret_flags_changed),
                                              object);
     }
     if (priv->show_password) {
@@ -188,13 +224,12 @@ nmt_password_fields_set_property(GObject      *object,
     case PROP_PASSWORD:
         nmt_password_fields_set_password(fields, g_value_get_string(value));
         break;
-    case PROP_ALWAYS_ASK:
-        if (priv->always_ask)
-            nmt_newt_checkbox_set_active(priv->always_ask, g_value_get_boolean(value));
+    case PROP_SECRET_FLAGS:
+        nmt_newt_popup_set_active(priv->secret_flags,
+                                  secret_flags_to_popup_idx(g_value_get_uint(value)));
         break;
     case PROP_SHOW_PASSWORD:
-        if (priv->show_password)
-            nmt_newt_checkbox_set_active(priv->show_password, g_value_get_boolean(value));
+        nmt_newt_checkbox_set_active(priv->show_password, g_value_get_boolean(value));
         break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
@@ -218,13 +253,13 @@ nmt_password_fields_get_property(GObject *object, guint prop_id, GValue *value,
     case PROP_PASSWORD:
         g_value_set_string(value, nmt_password_fields_get_password(entry));
         break;
-    case PROP_ALWAYS_ASK:
-        if (priv->always_ask)
-            g_value_set_boolean(value, nmt_newt_checkbox_get_active(priv->always_ask));
+    case PROP_SECRET_FLAGS:
+        g_value_set_uint(
+            value,
+            secret_flags_from_popup_idx(nmt_newt_popup_get_active(priv->secret_flags)));
         break;
     case PROP_SHOW_PASSWORD:
-        if (priv->show_password)
-            g_value_set_boolean(value, nmt_newt_checkbox_get_active(priv->show_password));
+        g_value_set_boolean(value, nmt_newt_checkbox_get_active(priv->show_password));
         break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
@@ -279,18 +314,19 @@ nmt_password_fields_class_init(NmtPasswordFieldsClass *entry_class)
         PROP_PASSWORD,
         g_param_spec_string("password", "", "", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     /**
-     * NmtPasswordFields:always-ask:
+     * NmtPasswordFields:secret-flags:
      *
-     * The current state of the "Always ask" checkbox.
+     * The current state of the "Secret flags" popup.
      */
-    g_object_class_install_property(
-        object_class,
-        PROP_ALWAYS_ASK,
-        g_param_spec_boolean("always-ask",
-                             "",
-                             "",
-                             FALSE,
-                             G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+    g_object_class_install_property(object_class,
+                                    PROP_SECRET_FLAGS,
+                                    g_param_spec_uint("secret-flags",
+                                                      "",
+                                                      "",
+                                                      0,
+                                                      G_MAXUINT,
+                                                      0,
+                                                      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     /**
      * NmtPasswordFields:show-password:
      *
diff --git a/src/nmtui/nmt-password-fields.h b/src/nmtui/nmt-password-fields.h
index 3e3d8145..54f65bd3 100644
--- a/src/nmtui/nmt-password-fields.h
+++ b/src/nmtui/nmt-password-fields.h
@@ -10,7 +10,7 @@
 
 #define NMT_TYPE_PASSWORD_FIELDS (nmt_password_fields_get_type())
 #define NMT_PASSWORD_FIELDS(obj) \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PASSWORD_FIELDS, NmtPasswordFields))
+    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_PASSWORD_FIELDS, NmtPasswordFields))
 #define NMT_PASSWORD_FIELDS_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_PASSWORD_FIELDS, NmtPasswordFieldsClass))
 #define NMT_IS_PASSWORD_FIELDS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_PASSWORD_FIELDS))
@@ -32,8 +32,9 @@ typedef struct {
 GType nmt_password_fields_get_type(void);
 
 typedef enum {
-    NMT_PASSWORD_FIELDS_ALWAYS_ASK    = (1 << 0),
-    NMT_PASSWORD_FIELDS_SHOW_PASSWORD = (1 << 1),
+    NMT_PASSWORD_FIELDS_SHOW_SECRET_FLAGS = (1 << 0),
+    NMT_PASSWORD_FIELDS_SHOW_PASSWORD     = (1 << 1),
+    NMT_PASSWORD_FIELDS_NOT_EMPTY         = (1 << 2), /* Return NULL instead of empty string */
 } NmtPasswordFieldsExtras;
 
 NmtNewtWidget *nmt_password_fields_new(int width, NmtPasswordFieldsExtras extras);
diff --git a/src/nmtui/nmt-route-editor.h b/src/nmtui/nmt-route-editor.h
index 3255324f..922fc171 100644
--- a/src/nmtui/nmt-route-editor.h
+++ b/src/nmtui/nmt-route-editor.h
@@ -10,7 +10,7 @@
 
 #define NMT_TYPE_ROUTE_EDITOR (nmt_route_editor_get_type())
 #define NMT_ROUTE_EDITOR(obj) \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_ROUTE_EDITOR, NmtRouteEditor))
+    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_ROUTE_EDITOR, NmtRouteEditor))
 #define NMT_ROUTE_EDITOR_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_ROUTE_EDITOR, NmtRouteEditorClass))
 #define NMT_IS_ROUTE_EDITOR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_ROUTE_EDITOR))
diff --git a/src/nmtui/nmt-route-entry.h b/src/nmtui/nmt-route-entry.h
index 102cb61c..eda8bcc8 100644
--- a/src/nmtui/nmt-route-entry.h
+++ b/src/nmtui/nmt-route-entry.h
@@ -10,7 +10,7 @@
 
 #define NMT_TYPE_ROUTE_ENTRY (nmt_route_entry_get_type())
 #define NMT_ROUTE_ENTRY(obj) \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_ROUTE_ENTRY, NmtRouteEntry))
+    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_ROUTE_ENTRY, NmtRouteEntry))
 #define NMT_ROUTE_ENTRY_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_ROUTE_ENTRY, NmtRouteEntryClass))
 #define NMT_IS_ROUTE_ENTRY(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_ROUTE_ENTRY))
diff --git a/src/nmtui/nmt-route-table.h b/src/nmtui/nmt-route-table.h
index fb29fd33..6639258b 100644
--- a/src/nmtui/nmt-route-table.h
+++ b/src/nmtui/nmt-route-table.h
@@ -10,7 +10,7 @@
 
 #define NMT_TYPE_ROUTE_TABLE (nmt_route_table_get_type())
 #define NMT_ROUTE_TABLE(obj) \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_ROUTE_TABLE, NmtRouteTable))
+    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_ROUTE_TABLE, NmtRouteTable))
 #define NMT_ROUTE_TABLE_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_ROUTE_TABLE, NmtRouteTableClass))
 #define NMT_IS_ROUTE_TABLE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_ROUTE_TABLE))
diff --git a/src/nmtui/nmt-slave-list.h b/src/nmtui/nmt-slave-list.h
index ab7de7b7..7bb60c59 100644
--- a/src/nmtui/nmt-slave-list.h
+++ b/src/nmtui/nmt-slave-list.h
@@ -10,7 +10,8 @@
 #include "nmtui-edit.h"
 
 #define NMT_TYPE_SLAVE_LIST (nmt_slave_list_get_type())
-#define NMT_SLAVE_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_SLAVE_LIST, NmtSlaveList))
+#define NMT_SLAVE_LIST(obj) \
+    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_SLAVE_LIST, NmtSlaveList))
 #define NMT_SLAVE_LIST_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_SLAVE_LIST, NmtSlaveListClass))
 #define NMT_IS_SLAVE_LIST(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_SLAVE_LIST))
diff --git a/src/nmtui/nmt-widget-list.h b/src/nmtui/nmt-widget-list.h
index f6ed8c4d..3f19b18c 100644
--- a/src/nmtui/nmt-widget-list.h
+++ b/src/nmtui/nmt-widget-list.h
@@ -10,7 +10,7 @@
 
 #define NMT_TYPE_WIDGET_LIST (nmt_widget_list_get_type())
 #define NMT_WIDGET_LIST(obj) \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_WIDGET_LIST, NmtWidgetList))
+    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_WIDGET_LIST, NmtWidgetList))
 #define NMT_WIDGET_LIST_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_WIDGET_LIST, NmtWidgetListClass))
 #define NMT_IS_WIDGET_LIST(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_WIDGET_LIST))
diff --git a/src/nmtui/nmt-wireguard-peer-editor.h b/src/nmtui/nmt-wireguard-peer-editor.h
index ffe76c8c..718919f7 100644
--- a/src/nmtui/nmt-wireguard-peer-editor.h
+++ b/src/nmtui/nmt-wireguard-peer-editor.h
@@ -10,7 +10,7 @@
 
 #define NMT_TYPE_WIREGUARD_PEER_EDITOR (nmt_wireguard_peer_editor_get_type())
 #define NMT_WIREGUARD_PEER_EDITOR(obj) \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_WIREGUARD_PEER_EDITOR, NmtWireguardPeerEditor))
+    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_WIREGUARD_PEER_EDITOR, NmtWireguardPeerEditor))
 #define NMT_WIREGUARD_PEER_EDITOR_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_WIREGUARD_PEER_EDITOR, NmtWireguardPeerEditorClass))
 #define NMT_IS_WIREGUARD_PEER_EDITOR(obj) \
diff --git a/src/nmtui/nmt-wireguard-peer-list.h b/src/nmtui/nmt-wireguard-peer-list.h
index de3faf12..79effd7e 100644
--- a/src/nmtui/nmt-wireguard-peer-list.h
+++ b/src/nmtui/nmt-wireguard-peer-list.h
@@ -11,7 +11,7 @@
 
 #define NMT_TYPE_WIREGUARD_PEER_LIST (nmt_wireguard_peer_list_get_type())
 #define NMT_WIREGUARD_PEER_LIST(obj) \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_WIREGUARD_PEER_LIST, NmtWireguardPeerList))
+    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_WIREGUARD_PEER_LIST, NmtWireguardPeerList))
 #define NMT_WIREGUARD_PEER_LIST_CLASS(klass) \
     (G_TYPE_CHECK_CLASS_CAST((klass), NMT_TYPE_WIREGUARD_PEER_LIST, NmtWireguardPeerListClass))
 #define NMT_IS_WIREGUARD_PEER_LIST(obj) \
diff --git a/src/nmtui/nmtui-connect.c b/src/nmtui/nmtui-connect.c
index fb456653..8c4625ec 100644
--- a/src/nmtui/nmtui-connect.c
+++ b/src/nmtui/nmtui-connect.c
@@ -241,7 +241,7 @@ activate_connection(NMConnection *connection, NMDevice *device, NMObject *specif
     GError                              *error = NULL;
     ActivateConnectionInfo               info  = {};
 
-    form  = g_object_new(NMT_TYPE_NEWT_FORM, "escape-exits", TRUE, NULL);
+    form  = g_object_new(NMT_TYPE_NEWT_FORM, NULL);
     label = nmt_newt_label_new(_("Connecting..."));
     nmt_newt_form_set_content(form, label);
 
@@ -417,14 +417,7 @@ nmt_connect_connection_list(gboolean is_top)
 
     newtGetScreenSize(&screen_width, &screen_height);
 
-    form = g_object_new(NMT_TYPE_NEWT_FORM,
-                        "y",
-                        2,
-                        "height",
-                        screen_height - 4,
-                        "escape-exits",
-                        TRUE,
-                        NULL);
+    form = g_object_new(NMT_TYPE_NEWT_FORM, "y", 2, "height", screen_height - 4, NULL);
 
     grid = nmt_newt_grid_new();
 
diff --git a/src/nmtui/nmtui-edit.c b/src/nmtui/nmtui-edit.c
index ec80a203..4eed22dd 100644
--- a/src/nmtui/nmtui-edit.c
+++ b/src/nmtui/nmtui-edit.c
@@ -91,14 +91,7 @@ nmt_edit_main_connection_list(gboolean is_top)
 
     newtGetScreenSize(&screen_width, &screen_height);
 
-    form = g_object_new(NMT_TYPE_NEWT_FORM,
-                        "y",
-                        2,
-                        "height",
-                        screen_height - 4,
-                        "escape-exits",
-                        TRUE,
-                        NULL);
+    form = g_object_new(NMT_TYPE_NEWT_FORM, "y", 2, "height", screen_height - 4, NULL);
 
     quit = nmt_newt_button_new(is_top ? _("Quit") : _("Back"));
     nmt_newt_widget_set_exit_on_activate(quit, TRUE);
@@ -120,7 +113,7 @@ nmt_edit_main_connection_list(gboolean is_top)
 
 #define NMT_TYPE_ADD_CONNECTION (nmt_add_connection_get_type())
 #define NMT_ADD_CONNECTION(obj) \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_ADD_CONNECTION, NmtAddConnection))
+    (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NMT_TYPE_ADD_CONNECTION, NmtAddConnection))
 #define NMT_IS_ADD_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMT_TYPE_ADD_CONNECTION))
 
 typedef NmtNewtForm      NmtAddConnection;
diff --git a/src/nmtui/nmtui-hostname.c b/src/nmtui/nmtui-hostname.c
index 65af73cc..bdb9753b 100644
--- a/src/nmtui/nmtui-hostname.c
+++ b/src/nmtui/nmtui-hostname.c
@@ -28,7 +28,7 @@ nmtui_hostname_run_dialog(void)
     NmtNewtButtonBox *bbox;
     char             *hostname, *ret = NULL;
 
-    form = g_object_new(NMT_TYPE_NEWT_FORM, "title", _("Set Hostname"), "escape-exits", TRUE, NULL);
+    form = g_object_new(NMT_TYPE_NEWT_FORM, "title", _("Set Hostname"), NULL);
 
     widget = nmt_newt_grid_new();
     nmt_newt_form_set_content(form, widget);
diff --git a/src/nmtui/nmtui.c b/src/nmtui/nmtui.c
index c99d1641..37c26e9d 100644
--- a/src/nmtui/nmtui.c
+++ b/src/nmtui/nmtui.c
@@ -80,12 +80,7 @@ nmtui_main(gboolean is_top, int argc, char **argv)
     NmtNewtButtonBox *bbox;
     int               i;
 
-    form = g_object_new(NMT_TYPE_NEWT_FORM,
-                        "title",
-                        _("NetworkManager TUI"),
-                        "escape-exits",
-                        TRUE,
-                        NULL);
+    form = g_object_new(NMT_TYPE_NEWT_FORM, "title", _("NetworkManager TUI"), NULL);
 
     widget = nmt_newt_grid_new();
     nmt_newt_form_set_content(form, widget);