summaryrefslogtreecommitdiffstats
path: root/panels/network/wireless-security
diff options
context:
space:
mode:
Diffstat (limited to 'panels/network/wireless-security')
-rw-r--r--panels/network/wireless-security/eap-method-fast.c399
-rw-r--r--panels/network/wireless-security/eap-method-fast.h34
-rw-r--r--panels/network/wireless-security/eap-method-fast.ui151
-rw-r--r--panels/network/wireless-security/eap-method-leap.c266
-rw-r--r--panels/network/wireless-security/eap-method-leap.h34
-rw-r--r--panels/network/wireless-security/eap-method-leap.ui63
-rw-r--r--panels/network/wireless-security/eap-method-peap.c400
-rw-r--r--panels/network/wireless-security/eap-method-peap.h34
-rw-r--r--panels/network/wireless-security/eap-method-peap.ui167
-rw-r--r--panels/network/wireless-security/eap-method-simple.c356
-rw-r--r--panels/network/wireless-security/eap-method-simple.h52
-rw-r--r--panels/network/wireless-security/eap-method-simple.ui68
-rw-r--r--panels/network/wireless-security/eap-method-tls.c557
-rw-r--r--panels/network/wireless-security/eap-method-tls.h34
-rw-r--r--panels/network/wireless-security/eap-method-tls.ui139
-rw-r--r--panels/network/wireless-security/eap-method-ttls.c415
-rw-r--r--panels/network/wireless-security/eap-method-ttls.h34
-rw-r--r--panels/network/wireless-security/eap-method-ttls.ui160
-rw-r--r--panels/network/wireless-security/eap-method.c588
-rw-r--r--panels/network/wireless-security/eap-method.h108
-rw-r--r--panels/network/wireless-security/helpers.c60
-rw-r--r--panels/network/wireless-security/helpers.h45
-rw-r--r--panels/network/wireless-security/meson.build73
-rw-r--r--panels/network/wireless-security/wireless-security.c101
-rw-r--r--panels/network/wireless-security/wireless-security.gresource.xml17
-rw-r--r--panels/network/wireless-security/wireless-security.h53
-rw-r--r--panels/network/wireless-security/ws-dynamic-wep.c262
-rw-r--r--panels/network/wireless-security/ws-dynamic-wep.h34
-rw-r--r--panels/network/wireless-security/ws-dynamic-wep.ui89
-rw-r--r--panels/network/wireless-security/ws-file-chooser-button.c268
-rw-r--r--panels/network/wireless-security/ws-file-chooser-button.h44
-rw-r--r--panels/network/wireless-security/ws-leap.c211
-rw-r--r--panels/network/wireless-security/ws-leap.h34
-rw-r--r--panels/network/wireless-security/ws-leap.ui63
-rw-r--r--panels/network/wireless-security/ws-sae.c225
-rw-r--r--panels/network/wireless-security/ws-sae.h33
-rw-r--r--panels/network/wireless-security/ws-sae.ui63
-rw-r--r--panels/network/wireless-security/ws-wep-key.c369
-rw-r--r--panels/network/wireless-security/ws-wep-key.h35
-rw-r--r--panels/network/wireless-security/ws-wep-key.ui141
-rw-r--r--panels/network/wireless-security/ws-wpa-eap.c313
-rw-r--r--panels/network/wireless-security/ws-wpa-eap.h37
-rw-r--r--panels/network/wireless-security/ws-wpa-eap.ui93
-rw-r--r--panels/network/wireless-security/ws-wpa-psk.c237
-rw-r--r--panels/network/wireless-security/ws-wpa-psk.h34
-rw-r--r--panels/network/wireless-security/ws-wpa-psk.ui72
46 files changed, 7065 insertions, 0 deletions
diff --git a/panels/network/wireless-security/eap-method-fast.c b/panels/network/wireless-security/eap-method-fast.c
new file mode 100644
index 0000000..c0f4ad0
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-fast.c
@@ -0,0 +1,399 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* vim: set ft=c ts=4 sts=4 sw=4 noexpandtab smartindent: */
+
+/* EAP-FAST authentication method (RFC4851)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2012 - 2014 Red Hat, Inc.
+ */
+
+#include <glib/gi18n.h>
+
+#include "eap-method.h"
+#include "eap-method-fast.h"
+#include "eap-method-simple.h"
+#include "helpers.h"
+#include "ui-helpers.h"
+#include "ws-file-chooser-button.h"
+
+#define I_NAME_COLUMN 0
+#define I_ID_COLUMN 1
+
+struct _EAPMethodFAST {
+ GtkGrid parent;
+
+ GtkEntry *anon_identity_entry;
+ GtkLabel *anon_identity_label;
+ GtkComboBox *inner_auth_combo;
+ GtkLabel *inner_auth_label;
+ GtkListStore *inner_auth_model;
+ GtkBox *inner_auth_box;
+ WsFileChooserButton *pac_file_button;
+ GtkLabel *pac_file_label;
+ GtkCheckButton *pac_provision_check;
+ GtkComboBox *pac_provision_combo;
+
+ EAPMethodSimple *em_gtc;
+ EAPMethodSimple *em_mschap_v2;
+};
+
+static void eap_method_iface_init (EAPMethodInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (EAPMethodFAST, eap_method_fast, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (eap_method_get_type (), eap_method_iface_init))
+
+static EAPMethod *
+get_inner_method (EAPMethodFAST *self)
+{
+ GtkTreeIter iter;
+ g_autofree gchar *id = NULL;
+
+ if (!gtk_combo_box_get_active_iter (self->inner_auth_combo, &iter))
+ return NULL;
+ gtk_tree_model_get (GTK_TREE_MODEL (self->inner_auth_model), &iter, I_ID_COLUMN, &id, -1);
+
+ if (strcmp (id, "gtc") == 0)
+ return EAP_METHOD (self->em_gtc);
+ if (strcmp (id, "mschapv2") == 0)
+ return EAP_METHOD (self->em_mschap_v2);
+
+ return NULL;
+}
+
+static gboolean
+validate (EAPMethod *parent, GError **error)
+{
+ EAPMethodFAST *self = (EAPMethodFAST *) parent;
+ g_autoptr(GFile) file = NULL;
+ gboolean provisioning;
+ gboolean valid = TRUE;
+
+ provisioning = gtk_check_button_get_active (GTK_CHECK_BUTTON (self->pac_provision_check));
+ file = ws_file_chooser_button_get_file (self->pac_file_button);
+ if (!provisioning && !file) {
+ widget_set_error (GTK_WIDGET (self->pac_file_button));
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("missing EAP-FAST PAC file"));
+ valid = FALSE;
+ } else
+ widget_unset_error (GTK_WIDGET (self->pac_file_button));
+
+ return eap_method_validate (get_inner_method (self), valid ? error : NULL) && valid;
+}
+
+static void
+add_to_size_group (EAPMethod *parent, GtkSizeGroup *group)
+{
+ EAPMethodFAST *self = (EAPMethodFAST *) parent;
+
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->anon_identity_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->pac_file_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->pac_provision_check));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->inner_auth_label));
+
+ eap_method_add_to_size_group (EAP_METHOD (self->em_gtc), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_mschap_v2), group);
+}
+
+static void
+fill_connection (EAPMethod *parent, NMConnection *connection, NMSettingSecretFlags flags)
+{
+ EAPMethodFAST *self = (EAPMethodFAST *) parent;
+ g_autofree gchar *filename = NULL;
+ g_autoptr(GFile) file = NULL;
+ NMSetting8021x *s_8021x;
+ const char *text;
+ gboolean enabled;
+ int pac_provisioning = 0;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ g_assert (s_8021x);
+
+ nm_setting_802_1x_add_eap_method (s_8021x, "fast");
+
+ text = gtk_editable_get_text (GTK_EDITABLE (self->anon_identity_entry));
+ if (text && strlen (text))
+ g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, text, NULL);
+
+ file = ws_file_chooser_button_get_file (self->pac_file_button);
+ filename = file ? g_file_get_path (file) : NULL;
+ g_object_set (s_8021x, NM_SETTING_802_1X_PAC_FILE, filename, NULL);
+
+ enabled = gtk_check_button_get_active (GTK_CHECK_BUTTON (self->pac_provision_check));
+
+ if (!enabled)
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "0", NULL);
+ else {
+ pac_provisioning = gtk_combo_box_get_active (self->pac_provision_combo);
+
+ switch (pac_provisioning) {
+ case 0: /* Anonymous */
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "1", NULL);
+ break;
+ case 1: /* Authenticated */
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "2", NULL);
+ break;
+ case 2: /* Both - anonymous and authenticated */
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "3", NULL);
+ break;
+ default: /* Should not happen */
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "1", NULL);
+ break;
+ }
+ }
+
+ eap_method_fill_connection (get_inner_method (self), connection, flags);
+}
+
+static void
+inner_auth_combo_changed_cb (EAPMethodFAST *self)
+{
+ EAPMethod *inner_method;
+ GtkWidget *child;
+
+ inner_method = get_inner_method (self);
+
+ /* Remove the previous method and migrate username/password across */
+ child = gtk_widget_get_first_child (GTK_WIDGET (self->inner_auth_box));
+ if (child != NULL) {
+ EAPMethod *old_eap = EAP_METHOD (child);
+ eap_method_set_username (inner_method, eap_method_get_username (old_eap));
+ eap_method_set_password (inner_method, eap_method_get_password (old_eap));
+ eap_method_set_show_password (inner_method, eap_method_get_show_password (old_eap));
+ gtk_box_remove (self->inner_auth_box, child);
+ }
+
+ gtk_box_append (self->inner_auth_box, g_object_ref (GTK_WIDGET (inner_method)));
+
+ eap_method_emit_changed (EAP_METHOD (self));
+}
+
+static void
+update_secrets (EAPMethod *parent, NMConnection *connection)
+{
+ EAPMethodFAST *self = (EAPMethodFAST *) parent;
+
+ eap_method_update_secrets (EAP_METHOD (self->em_gtc), connection);
+ eap_method_update_secrets (EAP_METHOD (self->em_mschap_v2), connection);
+}
+
+static GtkWidget *
+get_default_field (EAPMethod *parent)
+{
+ EAPMethodFAST *self = (EAPMethodFAST *) parent;
+ return GTK_WIDGET (self->anon_identity_entry);
+}
+
+static const gchar *
+get_password_flags_name (EAPMethod *parent)
+{
+ return NM_SETTING_802_1X_PASSWORD;
+}
+
+static const gchar *
+get_username (EAPMethod *method)
+{
+ EAPMethodFAST *self = EAP_METHOD_FAST (method);
+ return eap_method_get_username (get_inner_method (self));
+}
+
+static void
+set_username (EAPMethod *method, const gchar *username)
+{
+ EAPMethodFAST *self = EAP_METHOD_FAST (method);
+ return eap_method_set_username (get_inner_method (self), username);
+}
+
+static const gchar *
+get_password (EAPMethod *method)
+{
+ EAPMethodFAST *self = EAP_METHOD_FAST (method);
+ return eap_method_get_password (get_inner_method (self));
+}
+
+static void
+set_password (EAPMethod *method, const gchar *password)
+{
+ EAPMethodFAST *self = EAP_METHOD_FAST (method);
+ return eap_method_set_password (get_inner_method (self), password);
+}
+
+static gboolean
+get_show_password (EAPMethod *method)
+{
+ EAPMethodFAST *self = EAP_METHOD_FAST (method);
+ return eap_method_get_show_password (get_inner_method (self));
+}
+
+static void
+set_show_password (EAPMethod *method, gboolean show_password)
+{
+ EAPMethodFAST *self = EAP_METHOD_FAST (method);
+ return eap_method_set_show_password (get_inner_method (self), show_password);
+}
+
+static void
+pac_toggled_cb (EAPMethodFAST *self)
+{
+ gboolean enabled = FALSE;
+
+ enabled = gtk_check_button_get_active (GTK_CHECK_BUTTON (self->pac_provision_check));
+ gtk_widget_set_sensitive (GTK_WIDGET (self->pac_provision_combo), enabled);
+
+ eap_method_emit_changed (EAP_METHOD (self));
+}
+
+static void
+changed_cb (EAPMethodFAST *self)
+{
+ eap_method_emit_changed (EAP_METHOD (self));
+}
+
+static void
+eap_method_fast_init (EAPMethodFAST *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static void
+eap_method_fast_class_init (EAPMethodFASTClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ g_type_ensure (WS_TYPE_FILE_CHOOSER_BUTTON);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Settings/network/eap-method-fast.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodFAST, anon_identity_entry);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodFAST, anon_identity_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodFAST, inner_auth_combo);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodFAST, inner_auth_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodFAST, inner_auth_model);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodFAST, inner_auth_box);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodFAST, pac_file_button);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodFAST, pac_file_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodFAST, pac_provision_check);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodFAST, pac_provision_combo);
+}
+
+static void
+eap_method_iface_init (EAPMethodInterface *iface)
+{
+ iface->validate = validate;
+ iface->add_to_size_group = add_to_size_group;
+ iface->fill_connection = fill_connection;
+ iface->update_secrets = update_secrets;
+ iface->get_default_field = get_default_field;
+ iface->get_password_flags_name = get_password_flags_name;
+ iface->get_username = get_username;
+ iface->set_username = set_username;
+ iface->get_password = get_password;
+ iface->set_password = set_password;
+ iface->get_show_password = get_show_password;
+ iface->set_show_password = set_show_password;
+}
+
+EAPMethodFAST *
+eap_method_fast_new (NMConnection *connection)
+{
+ EAPMethodFAST *self;
+ GtkFileFilter *filter;
+ NMSetting8021x *s_8021x = NULL;
+ gboolean provisioning_enabled = TRUE;
+ const gchar *phase2_auth = NULL;
+ GtkTreeIter iter;
+
+ self = g_object_new (eap_method_fast_get_type (), NULL);
+
+ if (connection)
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+
+ gtk_combo_box_set_active (self->pac_provision_combo, 0);
+ if (s_8021x) {
+ const char *fast_prov;
+
+ fast_prov = nm_setting_802_1x_get_phase1_fast_provisioning (s_8021x);
+ if (fast_prov) {
+ if (!strcmp (fast_prov, "0"))
+ provisioning_enabled = FALSE;
+ else if (!strcmp (fast_prov, "1"))
+ gtk_combo_box_set_active (self->pac_provision_combo, 0);
+ else if (!strcmp (fast_prov, "2"))
+ gtk_combo_box_set_active (self->pac_provision_combo, 1);
+ else if (!strcmp (fast_prov, "3"))
+ gtk_combo_box_set_active (self->pac_provision_combo, 2);
+ }
+ }
+ gtk_widget_set_sensitive (GTK_WIDGET (self->pac_provision_combo), provisioning_enabled);
+ g_signal_connect_swapped (self->pac_provision_combo, "changed", G_CALLBACK (changed_cb), self);
+
+ gtk_check_button_set_active (self->pac_provision_check, provisioning_enabled);
+ g_signal_connect_swapped (self->pac_provision_check, "toggled", G_CALLBACK (pac_toggled_cb), self);
+
+ if (s_8021x && nm_setting_802_1x_get_anonymous_identity (s_8021x))
+ gtk_editable_set_text (GTK_EDITABLE (self->anon_identity_entry), nm_setting_802_1x_get_anonymous_identity (s_8021x));
+ g_signal_connect_swapped (self->anon_identity_entry, "changed", G_CALLBACK (changed_cb), self);
+
+ g_signal_connect_swapped (self->pac_file_button, "notify::file", G_CALLBACK (changed_cb), self);
+
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_add_pattern (filter, "*.pac");
+ gtk_file_filter_set_name (filter, _("PAC files (*.pac)"));
+ gtk_file_chooser_add_filter (ws_file_chooser_button_get_filechooser (self->pac_file_button), filter);
+ filter = gtk_file_filter_new ();
+ gtk_file_filter_add_pattern (filter, "*");
+ gtk_file_filter_set_name (filter, _("All files"));
+ gtk_file_chooser_add_filter (ws_file_chooser_button_get_filechooser (self->pac_file_button), filter);
+
+ if (connection && s_8021x) {
+ const char *filename = nm_setting_802_1x_get_pac_file (s_8021x);
+ if (filename) {
+ g_autoptr(GFile) file = g_file_new_for_path (filename);
+ ws_file_chooser_button_set_file (self->pac_file_button, file);
+ }
+ }
+
+ self->em_gtc = eap_method_simple_new (connection, "gtc", TRUE, FALSE);
+ gtk_widget_show (GTK_WIDGET (self->em_gtc));
+ g_signal_connect_object (self->em_gtc, "changed", G_CALLBACK (eap_method_emit_changed), self, G_CONNECT_SWAPPED);
+
+ self->em_mschap_v2 = eap_method_simple_new (connection, "mschapv2", TRUE, FALSE);
+ gtk_widget_show (GTK_WIDGET (self->em_mschap_v2));
+ g_signal_connect_object (self->em_mschap_v2, "changed", G_CALLBACK (eap_method_emit_changed), self, G_CONNECT_SWAPPED);
+
+ if (s_8021x) {
+ if (nm_setting_802_1x_get_phase2_auth (s_8021x))
+ phase2_auth = nm_setting_802_1x_get_phase2_auth (s_8021x);
+ else if (nm_setting_802_1x_get_phase2_autheap (s_8021x))
+ phase2_auth = nm_setting_802_1x_get_phase2_autheap (s_8021x);
+ }
+ if (phase2_auth == NULL)
+ phase2_auth = "gtc";
+
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->inner_auth_model), &iter)) {
+ do {
+ g_autofree gchar *id = NULL;
+ gtk_tree_model_get (GTK_TREE_MODEL (self->inner_auth_model), &iter, I_ID_COLUMN, &id, -1);
+ if (strcmp (id, phase2_auth) == 0)
+ gtk_combo_box_set_active_iter (self->inner_auth_combo, &iter);
+ } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->inner_auth_model), &iter));
+ }
+
+ g_signal_connect_swapped (self->inner_auth_combo, "changed", G_CALLBACK (inner_auth_combo_changed_cb), self);
+ inner_auth_combo_changed_cb (self);
+
+ return self;
+}
+
diff --git a/panels/network/wireless-security/eap-method-fast.h b/panels/network/wireless-security/eap-method-fast.h
new file mode 100644
index 0000000..5528ab1
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-fast.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* vim: set ft=c ts=4 sts=4 sw=4 noexpandtab smartindent: */
+
+/* EAP-FAST authentication method (RFC4851)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2012 Red Hat, Inc.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (EAPMethodFAST, eap_method_fast, EAP, METHOD_FAST, GtkGrid)
+
+EAPMethodFAST *eap_method_fast_new (NMConnection *connection);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/eap-method-fast.ui b/panels/network/wireless-security/eap-method-fast.ui
new file mode 100644
index 0000000..ad63b18
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-fast.ui
@@ -0,0 +1,151 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.4"/>
+ <object class="GtkListStore" id="inner_auth_model">
+ <columns>
+ <!-- column-name label -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">GTC</col>
+ <col id="1">gtc</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">MSCHAPv2</col>
+ <col id="1">mschapv2</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="pac_provision_model">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">Anonymous</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Authenticated</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Both</col>
+ </row>
+ </data>
+ </object>
+ <template class="EAPMethodFAST" parent="GtkGrid">
+ <property name="valign">start</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="anon_identity_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Anony_mous identity</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">anon_identity_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="anon_identity_entry">
+ <property name="hexpand">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="pac_file_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">PAC _file</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">pac_file_button</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="WsFileChooserButton" id="pac_file_button">
+ <property name="hexpand">True</property>
+ <property name="title" translatable="yes">Choose a PAC file</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="inner_auth_box">
+ <property name="orientation">vertical</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="column-span">2</property>
+ <property name="row">4</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="inner_auth_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Inner authentication</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">inner_auth_combo</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="inner_auth_combo">
+ <property name="hexpand">True</property>
+ <property name="model">inner_auth_model</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">3</property>
+ </layout>
+ <child>
+ <object class="GtkCellRendererText"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="pac_provision_check">
+ <property name="label" translatable="yes">Allow automatic PAC pro_visioning</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="pac_provision_combo">
+ <property name="hexpand">True</property>
+ <property name="model">pac_provision_model</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ <child>
+ <object class="GtkCellRendererText"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/wireless-security/eap-method-leap.c b/panels/network/wireless-security/eap-method-leap.c
new file mode 100644
index 0000000..95e7a8e
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-leap.c
@@ -0,0 +1,266 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#include <glib/gi18n.h>
+
+#include "eap-method.h"
+#include "eap-method-leap.h"
+#include "helpers.h"
+#include "nma-ui-utils.h"
+#include "ui-helpers.h"
+
+struct _EAPMethodLEAP {
+ GtkGrid parent;
+
+ GtkEntry *password_entry;
+ GtkLabel *password_label;
+ GtkCheckButton *show_password_check;
+ GtkEntry *username_entry;
+ GtkLabel *username_label;
+};
+
+static void eap_method_iface_init (EAPMethodInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (EAPMethodLEAP, eap_method_leap, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (eap_method_get_type (), eap_method_iface_init))
+
+static void
+show_toggled_cb (EAPMethodLEAP *self)
+{
+ gboolean visible;
+ visible = gtk_check_button_get_active (GTK_CHECK_BUTTON (self->show_password_check));
+ gtk_entry_set_visibility (self->password_entry, visible);
+}
+
+static gboolean
+validate (EAPMethod *parent, GError **error)
+{
+ EAPMethodLEAP *self = (EAPMethodLEAP *)parent;
+ NMSettingSecretFlags secret_flags;
+ const char *text;
+ gboolean ret = TRUE;
+
+ text = gtk_editable_get_text (GTK_EDITABLE (self->username_entry));
+ if (!text || !strlen (text)) {
+ widget_set_error (GTK_WIDGET (self->username_entry));
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("missing EAP-LEAP username"));
+ ret = FALSE;
+ } else
+ widget_unset_error (GTK_WIDGET (self->username_entry));
+
+ secret_flags = nma_utils_menu_to_secret_flags (GTK_WIDGET (self->password_entry));
+ if (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED) {
+ widget_unset_error (GTK_WIDGET (self->password_entry));
+ return TRUE;
+ }
+
+ text = gtk_editable_get_text (GTK_EDITABLE (self->password_entry));
+ if (!text || !strlen (text)) {
+ widget_set_error (GTK_WIDGET (self->password_entry));
+ if (ret) {
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("missing EAP-LEAP password"));
+ ret = FALSE;
+ }
+ } else
+ widget_unset_error (GTK_WIDGET (self->password_entry));
+
+ return ret;
+}
+
+static void
+add_to_size_group (EAPMethod *parent, GtkSizeGroup *group)
+{
+ EAPMethodLEAP *self = (EAPMethodLEAP *) parent;
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->username_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->password_label));
+}
+
+static void
+fill_connection (EAPMethod *parent, NMConnection *connection, NMSettingSecretFlags flags)
+{
+ EAPMethodLEAP *self = (EAPMethodLEAP *) parent;
+ NMSetting8021x *s_8021x;
+ NMSettingSecretFlags secret_flags;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ g_assert (s_8021x);
+
+ nm_setting_802_1x_add_eap_method (s_8021x, "leap");
+
+ g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, gtk_editable_get_text (GTK_EDITABLE (self->username_entry)), NULL);
+ g_object_set (s_8021x, NM_SETTING_802_1X_PASSWORD, gtk_editable_get_text (GTK_EDITABLE (self->password_entry)), NULL);
+
+ /* Save 802.1X password flags to the connection */
+ secret_flags = nma_utils_menu_to_secret_flags (GTK_WIDGET (self->password_entry));
+ nm_setting_set_secret_flags (NM_SETTING (s_8021x), NM_SETTING_802_1X_PASSWORD,
+ secret_flags, NULL);
+
+ /* Update secret flags and popup when editing the connection */
+ nma_utils_update_password_storage (GTK_WIDGET (self->password_entry), secret_flags,
+ NM_SETTING (s_8021x), NM_SETTING_802_1X_PASSWORD);
+}
+
+static void
+update_secrets (EAPMethod *parent, NMConnection *connection)
+{
+ EAPMethodLEAP *self = (EAPMethodLEAP *) parent;
+ helper_fill_secret_entry (connection,
+ self->password_entry,
+ NM_TYPE_SETTING_802_1X,
+ (HelperSecretFunc) nm_setting_802_1x_get_password);
+}
+
+static GtkWidget *
+get_default_field (EAPMethod *parent)
+{
+ EAPMethodLEAP *self = (EAPMethodLEAP *) parent;
+ return GTK_WIDGET (self->username_entry);
+}
+
+static const gchar *
+get_password_flags_name (EAPMethod *parent)
+{
+ return NM_SETTING_802_1X_PASSWORD;
+}
+
+static const gchar *
+get_username (EAPMethod *method)
+{
+ EAPMethodLEAP *self = EAP_METHOD_LEAP (method);
+ return gtk_editable_get_text (GTK_EDITABLE (self->username_entry));
+}
+
+static void
+set_username (EAPMethod *method, const gchar *username)
+{
+ EAPMethodLEAP *self = EAP_METHOD_LEAP (method);
+ gtk_editable_set_text (GTK_EDITABLE (self->username_entry), username);
+}
+
+static const gchar *
+get_password (EAPMethod *method)
+{
+ EAPMethodLEAP *self = EAP_METHOD_LEAP (method);
+ return gtk_editable_get_text (GTK_EDITABLE (self->password_entry));
+}
+
+static void
+set_password (EAPMethod *method, const gchar *password)
+{
+ EAPMethodLEAP *self = EAP_METHOD_LEAP (method);
+ gtk_editable_set_text (GTK_EDITABLE (self->password_entry), password);
+}
+
+static gboolean
+get_show_password (EAPMethod *method)
+{
+ EAPMethodLEAP *self = EAP_METHOD_LEAP (method);
+ return gtk_check_button_get_active (GTK_CHECK_BUTTON (self->show_password_check));
+}
+
+static void
+set_show_password (EAPMethod *method, gboolean show_password)
+{
+ EAPMethodLEAP *self = EAP_METHOD_LEAP (method);
+ gtk_check_button_set_active (self->show_password_check, show_password);
+}
+
+static void
+eap_method_leap_dispose (GObject *object)
+{
+ EAPMethodLEAP *self = EAP_METHOD_LEAP (object);
+
+ g_signal_handlers_disconnect_by_data (self, self);
+ g_signal_handlers_disconnect_by_data (self->show_password_check, self);
+
+ G_OBJECT_CLASS (eap_method_leap_parent_class)->dispose (object);
+}
+
+static void
+changed_cb (EAPMethodLEAP *self)
+{
+ eap_method_emit_changed (EAP_METHOD (self));
+}
+
+static void
+eap_method_leap_init (EAPMethodLEAP *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static void
+eap_method_leap_class_init (EAPMethodLEAPClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = eap_method_leap_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Settings/network/eap-method-leap.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodLEAP, password_entry);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodLEAP, password_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodLEAP, show_password_check);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodLEAP, username_entry);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodLEAP, username_label);
+}
+
+static void
+eap_method_iface_init (EAPMethodInterface *iface)
+{
+ iface->validate = validate;
+ iface->add_to_size_group = add_to_size_group;
+ iface->fill_connection = fill_connection;
+ iface->update_secrets = update_secrets;
+ iface->get_default_field = get_default_field;
+ iface->get_password_flags_name = get_password_flags_name;
+ iface->get_username = get_username;
+ iface->set_username = set_username;
+ iface->get_password = get_password;
+ iface->set_password = set_password;
+ iface->get_show_password = get_show_password;
+ iface->set_show_password = set_show_password;
+}
+
+EAPMethodLEAP *
+eap_method_leap_new (NMConnection *connection)
+{
+ EAPMethodLEAP *self;
+ NMSetting8021x *s_8021x = NULL;
+
+ self = g_object_new (eap_method_leap_get_type (), NULL);
+
+ g_signal_connect_swapped (self->username_entry, "changed", G_CALLBACK (changed_cb), self);
+
+ g_signal_connect_swapped (self->password_entry, "changed", G_CALLBACK (changed_cb), self);
+
+ /* Create password-storage popup menu for password entry under entry's secondary icon */
+ if (connection)
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ nma_utils_setup_password_storage (GTK_WIDGET (self->password_entry), 0, (NMSetting *) s_8021x, NM_SETTING_802_1X_PASSWORD,
+ FALSE, FALSE);
+
+ g_signal_connect_swapped (self->show_password_check, "toggled", G_CALLBACK (show_toggled_cb), self);
+
+ return self;
+}
+
diff --git a/panels/network/wireless-security/eap-method-leap.h b/panels/network/wireless-security/eap-method-leap.h
new file mode 100644
index 0000000..18248a6
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-leap.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (EAPMethodLEAP, eap_method_leap, EAP, METHOD_LEAP, GtkGrid)
+
+EAPMethodLEAP *eap_method_leap_new (NMConnection *connection);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/eap-method-leap.ui b/panels/network/wireless-security/eap-method-leap.ui
new file mode 100644
index 0000000..3f945bd
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-leap.ui
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.4"/>
+ <template class="EAPMethodLEAP" parent="GtkGrid">
+ <property name="valign">start</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="username_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Username</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">username_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="password_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Password</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">password_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="password_entry">
+ <property name="hexpand">True</property>
+ <property name="visibility">False</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="show_password_check">
+ <property name="label" translatable="yes">Sho_w password</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="username_entry">
+ <property name="hexpand">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/wireless-security/eap-method-peap.c b/panels/network/wireless-security/eap-method-peap.c
new file mode 100644
index 0000000..17eee12
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-peap.c
@@ -0,0 +1,400 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#include <glib/gi18n.h>
+
+#include "eap-method.h"
+#include "eap-method-peap.h"
+#include "eap-method-simple.h"
+#include "helpers.h"
+#include "ui-helpers.h"
+#include "ws-file-chooser-button.h"
+
+#define I_NAME_COLUMN 0
+#define I_ID_COLUMN 1
+
+struct _EAPMethodPEAP {
+ GtkGrid parent;
+
+ GtkEntry *anon_identity_entry;
+ GtkLabel *anon_identity_label;
+ WsFileChooserButton *ca_cert_button;
+ GtkLabel *ca_cert_label;
+ GtkCheckButton *ca_cert_not_required_check;
+ GtkBox *inner_auth_box;
+ GtkComboBox *inner_auth_combo;
+ GtkLabel *inner_auth_label;
+ GtkListStore *inner_auth_model;
+ GtkComboBox *version_combo;
+ GtkLabel *version_label;
+
+ EAPMethodSimple *em_gtc;
+ EAPMethodSimple *em_md5;
+ EAPMethodSimple *em_mschap_v2;
+};
+
+static void eap_method_iface_init (EAPMethodInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (EAPMethodPEAP, eap_method_peap, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (eap_method_get_type (), eap_method_iface_init))
+
+static EAPMethod *
+get_inner_method (EAPMethodPEAP *self)
+{
+ GtkTreeIter iter;
+ g_autofree gchar *id = NULL;
+
+ if (!gtk_combo_box_get_active_iter (self->inner_auth_combo, &iter))
+ return NULL;
+ gtk_tree_model_get (GTK_TREE_MODEL (self->inner_auth_model), &iter, I_ID_COLUMN, &id, -1);
+
+ if (strcmp (id, "gtc") == 0)
+ return EAP_METHOD (self->em_gtc);
+ if (strcmp (id, "md5") == 0)
+ return EAP_METHOD (self->em_md5);
+ if (strcmp (id, "mschapv2") == 0)
+ return EAP_METHOD (self->em_mschap_v2);
+
+ return NULL;
+}
+
+static gboolean
+validate (EAPMethod *method, GError **error)
+{
+ EAPMethodPEAP *self = EAP_METHOD_PEAP (method);
+ g_autoptr(GError) local_error = NULL;
+
+ if (!eap_method_validate_filepicker (ws_file_chooser_button_get_filechooser (self->ca_cert_button),
+ TYPE_CA_CERT, NULL, NULL, &local_error)) {
+ g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid EAP-PEAP CA certificate: %s"), local_error->message);
+ return FALSE;
+ }
+
+ if (!gtk_check_button_get_active (GTK_CHECK_BUTTON (self->ca_cert_not_required_check))) {
+ g_autoptr(GFile) file = NULL;
+
+ file = ws_file_chooser_button_get_file (self->ca_cert_button);
+ if (file == NULL) {
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid EAP-PEAP CA certificate: no certificate specified"));
+ return FALSE;
+ }
+ }
+
+ return eap_method_validate (get_inner_method (self), error);
+}
+
+static void
+ca_cert_not_required_toggled (EAPMethodPEAP *self)
+{
+ eap_method_ca_cert_not_required_toggled (self->ca_cert_not_required_check,
+ ws_file_chooser_button_get_filechooser (self->ca_cert_button));
+ eap_method_emit_changed (EAP_METHOD (self));
+}
+
+static void
+add_to_size_group (EAPMethod *method, GtkSizeGroup *group)
+{
+ EAPMethodPEAP *self = EAP_METHOD_PEAP (method);
+
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->ca_cert_not_required_check));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->anon_identity_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->ca_cert_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->version_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->inner_auth_label));
+
+ eap_method_add_to_size_group (EAP_METHOD (self->em_gtc), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_md5), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_mschap_v2), group);
+}
+
+static void
+fill_connection (EAPMethod *method, NMConnection *connection, NMSettingSecretFlags flags)
+{
+ EAPMethodPEAP *self = EAP_METHOD_PEAP (method);
+ NMSetting8021x *s_8021x;
+ NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ const char *text;
+ g_autofree gchar *filename = NULL;
+ g_autoptr(GFile) file = NULL;
+ int peapver_active = 0;
+ g_autoptr(GError) error = NULL;
+ gboolean ca_cert_error = FALSE;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ g_assert (s_8021x);
+
+ nm_setting_802_1x_add_eap_method (s_8021x, "peap");
+
+ text = gtk_editable_get_text (GTK_EDITABLE (self->anon_identity_entry));
+ if (text && strlen (text))
+ g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, text, NULL);
+
+ file = ws_file_chooser_button_get_file (self->ca_cert_button);
+ filename = file ? g_file_get_path (file) : NULL;
+ if (!nm_setting_802_1x_set_ca_cert (s_8021x, filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
+ g_warning ("Couldn't read CA certificate '%s': %s", filename, error ? error->message : "(unknown)");
+ ca_cert_error = TRUE;
+ }
+ eap_method_ca_cert_ignore_set (method, connection, filename, ca_cert_error);
+
+ peapver_active = gtk_combo_box_get_active (self->version_combo);
+ switch (peapver_active) {
+ case 1: /* PEAP v0 */
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_PEAPVER, "0", NULL);
+ break;
+ case 2: /* PEAP v1 */
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_PEAPVER, "1", NULL);
+ break;
+ default: /* Automatic */
+ g_object_set (G_OBJECT (s_8021x), NM_SETTING_802_1X_PHASE1_PEAPVER, NULL, NULL);
+ break;
+ }
+
+ eap_method_fill_connection (get_inner_method (self), connection, flags);
+}
+
+static void
+inner_auth_combo_changed_cb (EAPMethodPEAP *self)
+{
+ EAPMethod *inner_method;
+ GtkWidget *child;
+
+ inner_method = get_inner_method (self);
+
+ /* Remove the previous method and migrate username/password across */
+ child = gtk_widget_get_first_child (GTK_WIDGET (self->inner_auth_box));
+ if (child != NULL) {
+ EAPMethod *old_eap = EAP_METHOD (child);
+ eap_method_set_username (inner_method, eap_method_get_username (old_eap));
+ eap_method_set_password (inner_method, eap_method_get_password (old_eap));
+ eap_method_set_show_password (inner_method, eap_method_get_show_password (old_eap));
+ gtk_box_remove (self->inner_auth_box, GTK_WIDGET (old_eap));
+ }
+
+ gtk_box_append (self->inner_auth_box, g_object_ref (GTK_WIDGET (inner_method)));
+
+ eap_method_emit_changed (EAP_METHOD (self));
+}
+
+static void
+update_secrets (EAPMethod *method, NMConnection *connection)
+{
+ EAPMethodPEAP *self = EAP_METHOD_PEAP (method);
+
+ eap_method_update_secrets (EAP_METHOD (self->em_gtc), connection);
+ eap_method_update_secrets (EAP_METHOD (self->em_md5), connection);
+ eap_method_update_secrets (EAP_METHOD (self->em_mschap_v2), connection);
+}
+
+static GtkWidget *
+get_default_field (EAPMethod *method)
+{
+ EAPMethodPEAP *self = EAP_METHOD_PEAP (method);
+ return GTK_WIDGET (self->anon_identity_entry);
+}
+
+static const gchar *
+get_password_flags_name (EAPMethod *method)
+{
+ return NM_SETTING_802_1X_PASSWORD;
+}
+
+static const gchar *
+get_username (EAPMethod *method)
+{
+ EAPMethodPEAP *self = EAP_METHOD_PEAP (method);
+ return eap_method_get_username (get_inner_method (self));
+}
+
+static void
+set_username (EAPMethod *method, const gchar *username)
+{
+ EAPMethodPEAP *self = EAP_METHOD_PEAP (method);
+ return eap_method_set_username (get_inner_method (self), username);
+}
+
+static const gchar *
+get_password (EAPMethod *method)
+{
+ EAPMethodPEAP *self = EAP_METHOD_PEAP (method);
+ return eap_method_get_password (get_inner_method (self));
+}
+
+static void
+set_password (EAPMethod *method, const gchar *password)
+{
+ EAPMethodPEAP *self = EAP_METHOD_PEAP (method);
+ return eap_method_set_password (get_inner_method (self), password);
+}
+
+static gboolean
+get_show_password (EAPMethod *method)
+{
+ EAPMethodPEAP *self = EAP_METHOD_PEAP (method);
+ return eap_method_get_show_password (get_inner_method (self));
+}
+
+static void
+set_show_password (EAPMethod *method, gboolean show_password)
+{
+ EAPMethodPEAP *self = EAP_METHOD_PEAP (method);
+ return eap_method_set_show_password (get_inner_method (self), show_password);
+}
+
+static void
+changed_cb (EAPMethodPEAP *self)
+{
+ eap_method_emit_changed (EAP_METHOD (self));
+}
+
+static void
+eap_method_peap_init (EAPMethodPEAP *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static void
+eap_method_peap_class_init (EAPMethodPEAPClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Settings/network/eap-method-peap.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodPEAP, anon_identity_entry);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodPEAP, anon_identity_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodPEAP, ca_cert_button);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodPEAP, ca_cert_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodPEAP, ca_cert_not_required_check);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodPEAP, inner_auth_box);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodPEAP, inner_auth_combo);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodPEAP, inner_auth_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodPEAP, inner_auth_model);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodPEAP, version_combo);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodPEAP, version_label);
+}
+
+static void
+eap_method_iface_init (EAPMethodInterface *iface)
+{
+ iface->validate = validate;
+ iface->add_to_size_group = add_to_size_group;
+ iface->fill_connection = fill_connection;
+ iface->update_secrets = update_secrets;
+ iface->get_default_field = get_default_field;
+ iface->get_password_flags_name = get_password_flags_name;
+ iface->get_username = get_username;
+ iface->set_username = set_username;
+ iface->get_password = get_password;
+ iface->set_password = set_password;
+ iface->get_show_password = get_show_password;
+ iface->set_show_password = set_show_password;
+}
+
+EAPMethodPEAP *
+eap_method_peap_new (NMConnection *connection)
+{
+ EAPMethodPEAP *self;
+ GtkFileFilter *filter;
+ NMSetting8021x *s_8021x = NULL;
+ const char *filename;
+ const gchar *phase2_auth = NULL;
+ GtkTreeIter iter;
+
+ self = g_object_new (eap_method_peap_get_type (), NULL);
+
+ if (connection)
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+
+ g_signal_connect_swapped (self->ca_cert_not_required_check, "toggled", G_CALLBACK (ca_cert_not_required_toggled), self);
+
+ g_signal_connect_swapped (self->ca_cert_button, "notify::file", G_CALLBACK (changed_cb), self);
+ filter = eap_method_default_file_chooser_filter_new (FALSE);
+ gtk_file_chooser_add_filter (ws_file_chooser_button_get_filechooser (self->ca_cert_button),
+ filter);
+ if (connection && s_8021x) {
+ filename = NULL;
+ if (nm_setting_802_1x_get_ca_cert_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH) {
+ filename = nm_setting_802_1x_get_ca_cert_path (s_8021x);
+ if (filename) {
+ g_autoptr(GFile) file = g_file_new_for_path (filename);
+ ws_file_chooser_button_set_file (self->ca_cert_button, file);
+ }
+ }
+ gtk_check_button_set_active (self->ca_cert_not_required_check,
+ !filename && eap_method_ca_cert_ignore_get (EAP_METHOD (self), connection));
+ }
+
+ self->em_mschap_v2 = eap_method_simple_new (connection, "mschapv2", TRUE, FALSE);
+ gtk_widget_show (GTK_WIDGET (self->em_mschap_v2));
+ g_signal_connect_object (self->em_mschap_v2, "changed", G_CALLBACK (eap_method_emit_changed), self, G_CONNECT_SWAPPED);
+
+ self->em_md5 = eap_method_simple_new (connection, "md5", TRUE, FALSE);
+ gtk_widget_show (GTK_WIDGET (self->em_md5));
+ g_signal_connect_object (self->em_md5, "changed", G_CALLBACK (eap_method_emit_changed), self, G_CONNECT_SWAPPED);
+
+ self->em_gtc = eap_method_simple_new (connection, "gtc", TRUE, FALSE);
+ gtk_widget_show (GTK_WIDGET (self->em_gtc));
+ g_signal_connect_object (self->em_gtc, "changed", G_CALLBACK (eap_method_emit_changed), self, G_CONNECT_SWAPPED);
+
+ if (s_8021x) {
+ if (nm_setting_802_1x_get_phase2_auth (s_8021x))
+ phase2_auth = nm_setting_802_1x_get_phase2_auth (s_8021x);
+ else if (nm_setting_802_1x_get_phase2_autheap (s_8021x))
+ phase2_auth = nm_setting_802_1x_get_phase2_autheap (s_8021x);
+ }
+ if (phase2_auth == NULL)
+ phase2_auth = "mschapv2";
+
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->inner_auth_model), &iter)) {
+ do {
+ g_autofree gchar *id = NULL;
+ gtk_tree_model_get (GTK_TREE_MODEL (self->inner_auth_model), &iter, I_ID_COLUMN, &id, -1);
+ if (strcmp (id, phase2_auth) == 0)
+ gtk_combo_box_set_active_iter (self->inner_auth_combo, &iter);
+ } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->inner_auth_model), &iter));
+ }
+
+ g_signal_connect_swapped (self->inner_auth_combo, "changed", G_CALLBACK (inner_auth_combo_changed_cb), self);
+ inner_auth_combo_changed_cb (self);
+
+ gtk_combo_box_set_active (self->version_combo, 0);
+ if (s_8021x) {
+ const char *peapver;
+
+ peapver = nm_setting_802_1x_get_phase1_peapver (s_8021x);
+ if (peapver) {
+ /* Index 0 is "Automatic" */
+ if (!strcmp (peapver, "0"))
+ gtk_combo_box_set_active (self->version_combo, 1);
+ else if (!strcmp (peapver, "1"))
+ gtk_combo_box_set_active (self->version_combo, 2);
+ }
+ }
+ g_signal_connect_swapped (self->version_combo, "changed", G_CALLBACK (changed_cb), self);
+
+ if (s_8021x && nm_setting_802_1x_get_anonymous_identity (s_8021x))
+ gtk_editable_set_text (GTK_EDITABLE (self->anon_identity_entry), nm_setting_802_1x_get_anonymous_identity (s_8021x));
+ g_signal_connect_swapped (self->anon_identity_entry, "changed", G_CALLBACK (changed_cb), self);
+
+ return self;
+}
+
diff --git a/panels/network/wireless-security/eap-method-peap.h b/panels/network/wireless-security/eap-method-peap.h
new file mode 100644
index 0000000..53b2f30
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-peap.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (EAPMethodPEAP, eap_method_peap, EAP, METHOD_PEAP, GtkGrid)
+
+EAPMethodPEAP *eap_method_peap_new (NMConnection *connection);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/eap-method-peap.ui b/panels/network/wireless-security/eap-method-peap.ui
new file mode 100644
index 0000000..ac04783
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-peap.ui
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.4"/>
+ <object class="GtkListStore" id="inner_auth_model">
+ <columns>
+ <!-- column-name label -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">MSCHAPv2</col>
+ <col id="1">mschapv2</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">MD5</col>
+ <col id="1">md5</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">GTC</col>
+ <col id="1">gtc</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="version_model">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">Automatic</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Version 0</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Version 1</col>
+ </row>
+ </data>
+ </object>
+ <template class="EAPMethodPEAP" parent="GtkGrid">
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="anon_identity_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Anony_mous identity</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">anon_identity_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="anon_identity_entry">
+ <property name="hexpand">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="ca_cert_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">C_A certificate</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">ca_cert_button</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="WsFileChooserButton" id="ca_cert_button">
+ <property name="hexpand">True</property>
+ <property name="title" translatable="yes">Choose a Certificate Authority certificate</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="ca_cert_not_required_check">
+ <property name="label" translatable="yes">No CA certificate is _required</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="version_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">PEAP _version</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">version_combo</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="version_combo">
+ <property name="hexpand">True</property>
+ <property name="model">version_model</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">3</property>
+ </layout>
+ <child>
+ <object class="GtkCellRendererText"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="inner_auth_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Inner authentication</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">inner_auth_combo</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">4</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="inner_auth_combo">
+ <property name="hexpand">True</property>
+ <property name="model">inner_auth_model</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">4</property>
+ </layout>
+ <child>
+ <object class="GtkCellRendererText"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="inner_auth_box">
+ <property name="orientation">vertical</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">5</property>
+ <property name="column-span">2</property>
+ </layout>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/wireless-security/eap-method-simple.c b/panels/network/wireless-security/eap-method-simple.c
new file mode 100644
index 0000000..7bb29ec
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-simple.c
@@ -0,0 +1,356 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#include <glib/gi18n.h>
+
+#include "eap-method.h"
+#include "eap-method-simple.h"
+#include "helpers.h"
+#include "nma-ui-utils.h"
+#include "ui-helpers.h"
+
+struct _EAPMethodSimple {
+ GtkGrid parent;
+
+ GtkEntry *password_entry;
+ GtkLabel *password_label;
+ GtkToggleButton *show_password_check;
+ GtkEntry *username_entry;
+ GtkLabel *username_label;
+
+ gchar *name;
+ gboolean phase2;
+ gboolean autheap_allowed;
+
+ guint idle_func_id;
+};
+
+static void eap_method_iface_init (EAPMethodInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (EAPMethodSimple, eap_method_simple, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (eap_method_get_type (), eap_method_iface_init))
+
+static void
+show_toggled_cb (EAPMethodSimple *self)
+{
+ gboolean visible;
+
+ visible = gtk_check_button_get_active (GTK_CHECK_BUTTON (self->show_password_check));
+ gtk_entry_set_visibility (self->password_entry, visible);
+}
+
+static gboolean
+always_ask_selected (GtkEntry *passwd_entry)
+{
+ return !!( nma_utils_menu_to_secret_flags (GTK_WIDGET (passwd_entry))
+ & NM_SETTING_SECRET_FLAG_NOT_SAVED);
+}
+
+static gboolean
+validate (EAPMethod *method, GError **error)
+{
+ EAPMethodSimple *self = EAP_METHOD_SIMPLE (method);
+ const char *text;
+ gboolean ret = TRUE;
+
+ text = gtk_editable_get_text (GTK_EDITABLE (self->username_entry));
+ if (!text || !strlen (text)) {
+ widget_set_error (GTK_WIDGET (self->username_entry));
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("missing EAP username"));
+ ret = FALSE;
+ } else
+ widget_unset_error (GTK_WIDGET (self->username_entry));
+
+ /* Check if the password should always be requested */
+ if (always_ask_selected (self->password_entry))
+ widget_unset_error (GTK_WIDGET (self->password_entry));
+ else {
+ text = gtk_editable_get_text (GTK_EDITABLE (self->password_entry));
+ if (!text || !strlen (text)) {
+ widget_set_error (GTK_WIDGET (self->password_entry));
+ if (ret) {
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("missing EAP password"));
+ ret = FALSE;
+ }
+ } else
+ widget_unset_error (GTK_WIDGET (self->password_entry));
+ }
+
+ return ret;
+}
+
+static void
+add_to_size_group (EAPMethod *method, GtkSizeGroup *group)
+{
+ EAPMethodSimple *self = EAP_METHOD_SIMPLE (method);
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->username_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->password_label));
+}
+
+static void
+fill_connection (EAPMethod *method, NMConnection *connection, NMSettingSecretFlags prev_flags)
+{
+ EAPMethodSimple *self = EAP_METHOD_SIMPLE (method);
+ NMSetting8021x *s_8021x;
+ gboolean not_saved = FALSE;
+ NMSettingSecretFlags flags;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ g_assert (s_8021x);
+
+ /* If this is the main EAP method, clear any existing methods because the
+ * user-selected on will replace it.
+ */
+ if (eap_method_get_phase2 (method) == FALSE)
+ nm_setting_802_1x_clear_eap_methods (s_8021x);
+
+ if (eap_method_get_phase2 (method)) {
+ /* If the outer EAP method (TLS, TTLS, PEAP, etc) allows inner/phase2
+ * EAP methods (which only TTLS allows) *and* the inner/phase2 method
+ * supports being an inner EAP method, then set PHASE2_AUTHEAP.
+ * Otherwise the inner/phase2 method goes into PHASE2_AUTH.
+ */
+ if (self->autheap_allowed) {
+ g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTHEAP, self->name, NULL);
+ g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, NULL, NULL);
+ } else {
+ g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, self->name, NULL);
+ g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTHEAP, NULL, NULL);
+ }
+ } else
+ nm_setting_802_1x_add_eap_method (s_8021x, self->name);
+
+ g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, gtk_editable_get_text (GTK_EDITABLE (self->username_entry)), NULL);
+
+ /* Save the password always ask setting */
+ not_saved = always_ask_selected (self->password_entry);
+ flags = nma_utils_menu_to_secret_flags (GTK_WIDGET (self->password_entry));
+ nm_setting_set_secret_flags (NM_SETTING (s_8021x), NM_SETTING_802_1X_PASSWORD, flags, NULL);
+
+ /* Fill the connection's password if we're in the applet so that it'll get
+ * back to NM. From the editor though, since the connection isn't going
+ * back to NM in response to a GetSecrets() call, we don't save it if the
+ * user checked "Always Ask".
+ */
+ if (not_saved == FALSE)
+ g_object_set (s_8021x, NM_SETTING_802_1X_PASSWORD, gtk_editable_get_text (GTK_EDITABLE (self->password_entry)), NULL);
+
+ /* Update secret flags and popup when editing the connection */
+ nma_utils_update_password_storage (GTK_WIDGET (self->password_entry), flags,
+ NM_SETTING (s_8021x), NM_SETTING_802_1X_PASSWORD);
+}
+
+static void
+update_secrets (EAPMethod *method, NMConnection *connection)
+{
+ EAPMethodSimple *self = EAP_METHOD_SIMPLE (method);
+ helper_fill_secret_entry (connection,
+ self->password_entry,
+ NM_TYPE_SETTING_802_1X,
+ (HelperSecretFunc) nm_setting_802_1x_get_password);
+}
+
+static GtkWidget *
+get_default_field (EAPMethod *method)
+{
+ EAPMethodSimple *self = EAP_METHOD_SIMPLE (method);
+ return GTK_WIDGET (self->username_entry);
+}
+
+static const gchar *
+get_password_flags_name (EAPMethod *method)
+{
+ return NM_SETTING_802_1X_PASSWORD;
+}
+
+static const gboolean
+get_phase2 (EAPMethod *method)
+{
+ EAPMethodSimple *self = EAP_METHOD_SIMPLE (method);
+ return self->phase2;
+}
+
+static const gchar *
+get_username (EAPMethod *method)
+{
+ EAPMethodSimple *self = EAP_METHOD_SIMPLE (method);
+ return gtk_editable_get_text (GTK_EDITABLE (self->username_entry));
+}
+
+static void
+set_username (EAPMethod *method, const gchar *username)
+{
+ EAPMethodSimple *self = EAP_METHOD_SIMPLE (method);
+ if (username)
+ gtk_editable_set_text (GTK_EDITABLE (self->username_entry), username);
+}
+
+static const gchar *
+get_password (EAPMethod *method)
+{
+ EAPMethodSimple *self = EAP_METHOD_SIMPLE (method);
+ return gtk_editable_get_text (GTK_EDITABLE (self->password_entry));
+}
+
+static void
+set_password (EAPMethod *method, const gchar *password)
+{
+ EAPMethodSimple *self = EAP_METHOD_SIMPLE (method);
+ if (password)
+ gtk_editable_set_text (GTK_EDITABLE (self->password_entry), password);
+}
+
+static gboolean
+get_show_password (EAPMethod *method)
+{
+ EAPMethodSimple *self = EAP_METHOD_SIMPLE (method);
+ return gtk_check_button_get_active (GTK_CHECK_BUTTON (self->show_password_check));
+}
+
+static void
+set_show_password (EAPMethod *method, gboolean show_password)
+{
+ EAPMethodSimple *self = EAP_METHOD_SIMPLE (method);
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->show_password_check), show_password);
+}
+
+static gboolean
+stuff_changed (EAPMethodSimple *self)
+{
+ eap_method_emit_changed (EAP_METHOD (self));
+ self->idle_func_id = 0;
+ return FALSE;
+}
+
+static void
+password_storage_changed (EAPMethodSimple *self)
+{
+ gboolean always_ask;
+
+ always_ask = always_ask_selected (self->password_entry);
+
+ if (always_ask) {
+ /* we always clear this button and do not restore it
+ * (because we want to hide the password). */
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->show_password_check), FALSE);
+ }
+
+ gtk_widget_set_sensitive (GTK_WIDGET (self->show_password_check), !always_ask);
+
+ if (!self->idle_func_id)
+ self->idle_func_id = g_idle_add ((GSourceFunc) stuff_changed, self);
+}
+
+static void
+eap_method_simple_dispose (GObject *object)
+{
+ EAPMethodSimple *self = EAP_METHOD_SIMPLE (object);
+
+ g_clear_pointer (&self->name, g_free);
+
+ g_signal_handlers_disconnect_by_data (self, self);
+ g_signal_handlers_disconnect_by_data (self->password_entry, self);
+ g_signal_handlers_disconnect_by_data (self->show_password_check, self);
+
+ if (self->idle_func_id != 0) {
+ g_source_remove (self->idle_func_id);
+ self->idle_func_id = 0;
+ }
+
+ G_OBJECT_CLASS (eap_method_simple_parent_class)->dispose (object);
+}
+
+static void
+changed_cb (EAPMethodSimple *self)
+{
+ eap_method_emit_changed (EAP_METHOD (self));
+}
+
+static void
+eap_method_simple_init (EAPMethodSimple *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static void
+eap_method_simple_class_init (EAPMethodSimpleClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = eap_method_simple_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Settings/network/eap-method-simple.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodSimple, password_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodSimple, username_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodSimple, password_entry);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodSimple, show_password_check);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodSimple, username_entry);
+}
+
+static void
+eap_method_iface_init (EAPMethodInterface *iface)
+{
+ iface->validate = validate;
+ iface->add_to_size_group = add_to_size_group;
+ iface->fill_connection = fill_connection;
+ iface->update_secrets = update_secrets;
+ iface->get_default_field = get_default_field;
+ iface->get_password_flags_name = get_password_flags_name;
+ iface->get_phase2 = get_phase2;
+ iface->get_username = get_username;
+ iface->set_username = set_username;
+ iface->get_password = get_password;
+ iface->set_password = set_password;
+ iface->get_show_password = get_show_password;
+ iface->set_show_password = set_show_password;
+}
+
+EAPMethodSimple *
+eap_method_simple_new (NMConnection *connection, const gchar *name, gboolean phase2, gboolean autheap_allowed)
+{
+ EAPMethodSimple *self;
+ NMSetting8021x *s_8021x = NULL;
+
+ self = g_object_new (eap_method_simple_get_type (), NULL);
+ self->name = g_strdup (name);
+ self->phase2 = phase2;
+ self->autheap_allowed = autheap_allowed;
+
+ g_signal_connect_swapped (self->username_entry, "changed", G_CALLBACK (changed_cb), self);
+
+ g_signal_connect_swapped (self->password_entry, "changed", G_CALLBACK (changed_cb), self);
+
+ /* Create password-storage popup menu for password entry under entry's secondary icon */
+ if (connection)
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ nma_utils_setup_password_storage (GTK_WIDGET (self->password_entry), 0, (NMSetting *) s_8021x, NM_SETTING_802_1X_PASSWORD,
+ FALSE, FALSE);
+
+ g_signal_connect_swapped (self->password_entry, "notify::secondary-icon-name", G_CALLBACK (password_storage_changed), self);
+
+ g_signal_connect_swapped (self->show_password_check, "toggled", G_CALLBACK (show_toggled_cb), self);
+
+ return self;
+}
+
diff --git a/panels/network/wireless-security/eap-method-simple.h b/panels/network/wireless-security/eap-method-simple.h
new file mode 100644
index 0000000..8645fb1
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-simple.h
@@ -0,0 +1,52 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (EAPMethodSimple, eap_method_simple, EAP, METHOD_SIMPLE, GtkGrid)
+
+typedef enum {
+ /* NOTE: when updating this table, also update eap_methods[] */
+ EAP_METHOD_SIMPLE_TYPE_PAP = 0,
+ EAP_METHOD_SIMPLE_TYPE_MSCHAP,
+ EAP_METHOD_SIMPLE_TYPE_MSCHAP_V2,
+ EAP_METHOD_SIMPLE_TYPE_PLAIN_MSCHAP_V2,
+ EAP_METHOD_SIMPLE_TYPE_MD5,
+ EAP_METHOD_SIMPLE_TYPE_PWD,
+ EAP_METHOD_SIMPLE_TYPE_CHAP,
+ EAP_METHOD_SIMPLE_TYPE_GTC,
+
+ /* Boundary value, do not use */
+ EAP_METHOD_SIMPLE_TYPE_LAST
+} EAPMethodSimpleType;
+
+EAPMethodSimple *eap_method_simple_new (NMConnection *connection,
+ const gchar *name,
+ gboolean phase2,
+ gboolean autheap_allowed);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/eap-method-simple.ui b/panels/network/wireless-security/eap-method-simple.ui
new file mode 100644
index 0000000..e5c37c9
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-simple.ui
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.4"/>
+ <template class="EAPMethodSimple" parent="GtkGrid">
+ <property name="valign">start</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="username_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Username</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">username_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="password_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Password</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">password_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="password_entry">
+ <property name="hexpand">True</property>
+ <property name="visibility">False</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="username_entry">
+ <property name="hexpand">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="hexpand">True</property>
+ <property name="orientation">vertical</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ <child>
+ <object class="GtkCheckButton" id="show_password_check">
+ <property name="label" translatable="yes">Sho_w password</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/wireless-security/eap-method-tls.c b/panels/network/wireless-security/eap-method-tls.c
new file mode 100644
index 0000000..5038915
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-tls.c
@@ -0,0 +1,557 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#include <glib/gi18n.h>
+
+#include "eap-method.h"
+#include "eap-method-tls.h"
+#include "helpers.h"
+#include "nma-ui-utils.h"
+#include "ui-helpers.h"
+#include "ws-file-chooser-button.h"
+
+struct _EAPMethodTLS {
+ GtkGrid parent;
+
+ WsFileChooserButton *ca_cert_button;
+ GtkLabel *ca_cert_label;
+ GtkCheckButton *ca_cert_not_required_check;
+ GtkEntry *identity_entry;
+ GtkLabel *identity_label;
+ WsFileChooserButton *private_key_button;
+ GtkLabel *private_key_label;
+ GtkEntry *private_key_password_entry;
+ GtkLabel *private_key_password_label;
+ GtkCheckButton *show_password_check;
+ WsFileChooserButton *user_cert_button;
+ GtkLabel *user_cert_label;
+
+ gchar *username;
+ gchar *password;
+ gboolean show_password;
+};
+
+static void eap_method_iface_init (EAPMethodInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (EAPMethodTLS, eap_method_tls, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (eap_method_get_type (), eap_method_iface_init))
+
+static void
+eap_method_tls_dispose (GObject *object)
+{
+ EAPMethodTLS *self = EAP_METHOD_TLS (object);
+
+ g_clear_pointer (&self->username, g_free);
+ g_clear_pointer (&self->password, g_free);
+
+ G_OBJECT_CLASS (eap_method_tls_parent_class)->dispose (object);
+}
+
+static void
+show_toggled_cb (EAPMethodTLS *self)
+{
+ gboolean visible;
+
+ visible = gtk_check_button_get_active (GTK_CHECK_BUTTON (self->show_password_check));
+ gtk_entry_set_visibility (self->private_key_password_entry, visible);
+}
+
+static gboolean
+validate (EAPMethod *method, GError **error)
+{
+ EAPMethodTLS *self = EAP_METHOD_TLS (method);
+ NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ NMSettingSecretFlags secret_flags;
+ const char *password, *identity;
+ g_autoptr(GError) ca_cert_error = NULL;
+ g_autoptr(GError) private_key_error = NULL;
+ g_autoptr(GError) user_cert_error = NULL;
+ gboolean ret = TRUE;
+
+ identity = gtk_editable_get_text (GTK_EDITABLE (self->identity_entry));
+ if (!identity || !strlen (identity)) {
+ widget_set_error (GTK_WIDGET (self->identity_entry));
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("missing EAP-TLS identity"));
+ ret = FALSE;
+ } else {
+ widget_unset_error (GTK_WIDGET (self->identity_entry));
+ }
+
+ if (!eap_method_validate_filepicker (ws_file_chooser_button_get_filechooser (self->ca_cert_button),
+ TYPE_CA_CERT, NULL, NULL, &ca_cert_error)) {
+ widget_set_error (GTK_WIDGET (self->ca_cert_button));
+ if (ret) {
+ g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid EAP-TLS CA certificate: %s"), ca_cert_error->message);
+ ret = FALSE;
+ }
+ } else if (!gtk_check_button_get_active (GTK_CHECK_BUTTON (self->ca_cert_not_required_check))) {
+ g_autoptr(GFile) file = NULL;
+
+ file = ws_file_chooser_button_get_file (self->ca_cert_button);
+ if (file == NULL) {
+ widget_set_error (GTK_WIDGET (self->ca_cert_button));
+ if (ret) {
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid EAP-TLS CA certificate: no certificate specified"));
+ ret = FALSE;
+ }
+ }
+ }
+
+ password = gtk_editable_get_text (GTK_EDITABLE (self->private_key_password_entry));
+ secret_flags = nma_utils_menu_to_secret_flags (GTK_WIDGET (self->private_key_password_entry));
+ if (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED)
+ password = NULL;
+
+ if (!eap_method_validate_filepicker (ws_file_chooser_button_get_filechooser (self->private_key_button),
+ TYPE_PRIVATE_KEY,
+ password,
+ &format,
+ &private_key_error)) {
+ if (ret) {
+ g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid EAP-TLS private-key: %s"), private_key_error->message);
+ ret = FALSE;
+ }
+ widget_set_error (GTK_WIDGET (self->private_key_button));
+ }
+
+ if (format != NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
+ if (!eap_method_validate_filepicker (ws_file_chooser_button_get_filechooser (self->user_cert_button),
+ TYPE_CLIENT_CERT, NULL, NULL, &user_cert_error)) {
+ if (ret) {
+ g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid EAP-TLS user-certificate: %s"), user_cert_error->message);
+ ret = FALSE;
+ }
+ widget_set_error (GTK_WIDGET (self->user_cert_button));
+ }
+ }
+
+ return ret;
+}
+
+static void
+ca_cert_not_required_toggled (EAPMethodTLS *self)
+{
+ eap_method_ca_cert_not_required_toggled (self->ca_cert_not_required_check,
+ ws_file_chooser_button_get_filechooser (self->ca_cert_button));
+ eap_method_emit_changed (EAP_METHOD (self));
+}
+
+static void
+add_to_size_group (EAPMethod *method, GtkSizeGroup *group)
+{
+ EAPMethodTLS *self = EAP_METHOD_TLS (method);
+
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->ca_cert_not_required_check));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->identity_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->user_cert_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->ca_cert_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->private_key_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->private_key_password_label));
+}
+
+static void
+fill_connection (EAPMethod *method, NMConnection *connection, NMSettingSecretFlags flags)
+{
+ EAPMethodTLS *self = EAP_METHOD_TLS (method);
+ NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ NMSetting8021x *s_8021x;
+ NMSettingSecretFlags secret_flags;
+ g_autofree gchar *ca_filename = NULL;
+ g_autoptr(GFile) ca_file = NULL;
+ g_autofree gchar *pk_filename = NULL;
+ g_autoptr(GFile) pk_file = NULL;
+ const char *password = NULL;
+ gboolean ca_cert_error = FALSE;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GError) error2 = NULL;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ g_assert (s_8021x);
+
+ nm_setting_802_1x_add_eap_method (s_8021x, "tls");
+
+ g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, gtk_editable_get_text (GTK_EDITABLE (self->identity_entry)), NULL);
+
+ /* TLS private key */
+ password = gtk_editable_get_text (GTK_EDITABLE (self->private_key_password_entry));
+ secret_flags = nma_utils_menu_to_secret_flags (GTK_WIDGET (self->private_key_password_entry));
+ if (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED)
+ password = NULL;
+
+ pk_file = ws_file_chooser_button_get_file (self->private_key_button);
+ g_assert (pk_file);
+ pk_filename = g_file_get_path (pk_file);
+
+ if (!nm_setting_802_1x_set_private_key (s_8021x, pk_filename, password, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error))
+ g_warning ("Couldn't read private key '%s': %s", pk_filename, error ? error->message : "(unknown)");
+
+ /* Save 802.1X password flags to the connection */
+ nm_setting_set_secret_flags (NM_SETTING (s_8021x), NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD,
+ secret_flags, NULL);
+
+ /* Update secret flags and popup when editing the connection */
+ nma_utils_update_password_storage (GTK_WIDGET (self->private_key_password_entry), secret_flags,
+ NM_SETTING (s_8021x), NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD);
+
+ /* TLS client certificate */
+ if (format != NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
+ g_autofree gchar *cc_filename = NULL;
+ g_autoptr(GFile) cc_file = NULL;
+ g_autoptr(GError) error = NULL;
+
+ /* If the key is pkcs#12 nm_setting_802_1x_set_private_key() already
+ * set the client certificate for us.
+ */
+ cc_file = ws_file_chooser_button_get_file (self->private_key_button);
+ g_assert (cc_file);
+ cc_filename = g_file_get_path (cc_file);
+
+ format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ if (!nm_setting_802_1x_set_client_cert (s_8021x, cc_filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error))
+ g_warning ("Couldn't read client certificate '%s': %s", cc_filename, error ? error->message : "(unknown)");
+ }
+
+ /* TLS CA certificate */
+ ca_file = ws_file_chooser_button_get_file (self->private_key_button);
+ ca_filename = ca_file ? g_file_get_path (ca_file) : NULL;
+
+ format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ if (!nm_setting_802_1x_set_ca_cert (s_8021x, ca_filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error2)) {
+ g_warning ("Couldn't read CA certificate '%s': %s", ca_filename, error2 ? error2->message : "(unknown)");
+ ca_cert_error = TRUE;
+ }
+ eap_method_ca_cert_ignore_set (method, connection, ca_filename, ca_cert_error);
+}
+
+static void
+private_key_picker_helper (EAPMethodTLS *self, const char *filename, gboolean changed)
+{
+ g_autoptr(NMSetting8021x) setting = NULL;
+ NMSetting8021xCKFormat cert_format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ const char *password;
+
+ password = gtk_editable_get_text (GTK_EDITABLE (self->private_key_password_entry));
+
+ setting = (NMSetting8021x *) nm_setting_802_1x_new ();
+ nm_setting_802_1x_set_private_key (setting, filename, password, NM_SETTING_802_1X_CK_SCHEME_PATH, &cert_format, NULL);
+
+ /* With PKCS#12, the client cert must be the same as the private key */
+ if (cert_format == NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
+ ws_file_chooser_button_set_file (self->user_cert_button, NULL);
+ gtk_widget_set_sensitive (GTK_WIDGET (self->user_cert_button), FALSE);
+ } else if (changed)
+ gtk_widget_set_sensitive (GTK_WIDGET (self->user_cert_button), TRUE);
+
+ /* Warn the user if the private key is unencrypted */
+ if (!eap_method_is_encrypted_private_key (filename)) {
+ GtkWidget *dialog;
+ GtkNative *native;
+ GtkWindow *parent_window = NULL;
+
+ native = gtk_widget_get_native (GTK_WIDGET (self));
+ if (GTK_IS_WINDOW (native))
+ parent_window = GTK_WINDOW (native);
+
+ dialog = gtk_message_dialog_new (parent_window,
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_OK,
+ "%s",
+ _("Unencrypted private keys are insecure"));
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ "%s",
+ _("The selected private key does not appear to be protected by a password. This could allow your security credentials to be compromised. Please select a password-protected private key.\n\n(You can password-protect your private key with openssl)"));
+ gtk_window_present (GTK_WINDOW (dialog));
+ }
+}
+
+static void
+private_key_picker_file_set_cb (WsFileChooserButton *chooser, gpointer user_data)
+{
+ EAPMethodTLS *self = user_data;
+ g_autoptr(GFile) file = NULL;
+ g_autofree gchar *filename = NULL;
+
+ file = ws_file_chooser_button_get_file (chooser);
+ filename = file ? g_file_get_path (file) : NULL;
+ if (filename)
+ private_key_picker_helper (self, filename, TRUE);
+}
+
+static void reset_filter (GtkWidget *widget, GParamSpec *spec, gpointer user_data)
+{
+ if (!gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (widget))) {
+ g_signal_handlers_block_by_func (widget, reset_filter, user_data);
+ gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (widget), GTK_FILE_FILTER (user_data));
+ g_signal_handlers_unblock_by_func (widget, reset_filter, user_data);
+ }
+}
+
+typedef const char * (*PathFunc) (NMSetting8021x *setting);
+typedef NMSetting8021xCKScheme (*SchemeFunc) (NMSetting8021x *setting);
+
+static void
+changed_cb (EAPMethodTLS *self)
+{
+ eap_method_emit_changed (EAP_METHOD (self));
+}
+
+static void
+setup_filepicker (EAPMethodTLS *self,
+ WsFileChooserButton *button,
+ const char *title,
+ NMSetting8021x *s_8021x,
+ SchemeFunc scheme_func,
+ PathFunc path_func,
+ gboolean privkey,
+ gboolean client_cert)
+{
+ GtkFileFilter *filter;
+ const char *filename = NULL;
+
+ if (s_8021x && path_func && scheme_func) {
+ if (scheme_func (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH) {
+ filename = path_func (s_8021x);
+ if (filename) {
+ g_autoptr(GFile) file = g_file_new_for_path (filename);
+ ws_file_chooser_button_set_file (button, file);
+ }
+ }
+ }
+
+ /* Connect a special handler for private keys to intercept PKCS#12 key types
+ * and desensitize the user cert button.
+ */
+ if (privkey) {
+ g_signal_connect (button, "notify::file",
+ G_CALLBACK (private_key_picker_file_set_cb),
+ self);
+ if (filename)
+ private_key_picker_helper (self, filename, FALSE);
+ }
+
+ g_signal_connect_swapped (button, "notify::file", G_CALLBACK (changed_cb), self);
+
+ filter = eap_method_default_file_chooser_filter_new (privkey);
+ gtk_file_chooser_add_filter (ws_file_chooser_button_get_filechooser (button), filter);
+
+ /* For some reason, GTK+ calls set_current_filter (..., NULL) from
+ * gtkfilechooserdefault.c::show_and_select_files_finished_loading() on our
+ * dialog; so force-reset the filter to what we want it to be whenever
+ * it gets cleared.
+ */
+ if (client_cert)
+ g_signal_connect (button, "notify::filter", (GCallback) reset_filter, filter);
+}
+
+static void
+update_secrets (EAPMethod *method, NMConnection *connection)
+{
+ EAPMethodTLS *self = EAP_METHOD_TLS (method);
+ NMSetting8021x *s_8021x;
+ const char *filename;
+
+ helper_fill_secret_entry (connection,
+ self->private_key_password_entry,
+ NM_TYPE_SETTING_802_1X,
+ (HelperSecretFunc) nm_setting_802_1x_get_private_key_password);
+
+ /* Set the private key filepicker button path if we have a private key */
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ if (s_8021x && (nm_setting_802_1x_get_private_key_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH)) {
+ filename = nm_setting_802_1x_get_private_key_path (s_8021x);
+ if (filename) {
+ g_autoptr(GFile) file = g_file_new_for_path (filename);
+ ws_file_chooser_button_set_file (self->private_key_button, file);
+ }
+ }
+}
+
+static GtkWidget *
+get_default_field (EAPMethod *method)
+{
+ EAPMethodTLS *self = EAP_METHOD_TLS (method);
+ return GTK_WIDGET (self->identity_entry);
+}
+
+static const gchar *
+get_password_flags_name (EAPMethod *method)
+{
+ return NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD;
+}
+
+static const gchar *
+get_username (EAPMethod *method)
+{
+ EAPMethodTLS *self = EAP_METHOD_TLS (method);
+ return self->username;
+}
+
+static void
+set_username (EAPMethod *method, const gchar *username)
+{
+ EAPMethodTLS *self = EAP_METHOD_TLS (method);
+ g_free (self->username);
+ self->username = g_strdup (username);
+}
+
+static const gchar *
+get_password (EAPMethod *method)
+{
+ EAPMethodTLS *self = EAP_METHOD_TLS (method);
+ return self->password;
+}
+
+static void
+set_password (EAPMethod *method, const gchar *password)
+{
+ EAPMethodTLS *self = EAP_METHOD_TLS (method);
+ g_free (self->password);
+ self->password = g_strdup (password);
+}
+
+static const gboolean
+get_show_password (EAPMethod *method)
+{
+ EAPMethodTLS *self = EAP_METHOD_TLS (method);
+ return self->show_password;
+}
+
+static void
+set_show_password (EAPMethod *method, gboolean show_password)
+{
+ EAPMethodTLS *self = EAP_METHOD_TLS (method);
+ self->show_password = show_password;
+}
+
+static void
+eap_method_tls_init (EAPMethodTLS *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+ self->username = g_strdup ("");
+ self->password = g_strdup ("");
+}
+
+static void
+eap_method_tls_class_init (EAPMethodTLSClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = eap_method_tls_dispose;
+
+ g_type_ensure (WS_TYPE_FILE_CHOOSER_BUTTON);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Settings/network/eap-method-tls.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTLS, ca_cert_button);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTLS, ca_cert_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTLS, ca_cert_not_required_check);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTLS, identity_entry);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTLS, identity_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTLS, private_key_button);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTLS, private_key_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTLS, private_key_password_entry);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTLS, private_key_password_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTLS, show_password_check);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTLS, user_cert_button);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTLS, user_cert_label);
+}
+
+static void
+eap_method_iface_init (EAPMethodInterface *iface)
+{
+ iface->validate = validate;
+ iface->add_to_size_group = add_to_size_group;
+ iface->fill_connection = fill_connection;
+ iface->update_secrets = update_secrets;
+ iface->get_default_field = get_default_field;
+ iface->get_password_flags_name = get_password_flags_name;
+ iface->get_username = get_username;
+ iface->set_username = set_username;
+ iface->get_password = get_password;
+ iface->set_password = set_password;
+ iface->get_show_password = get_show_password;
+ iface->set_show_password = set_show_password;
+}
+
+EAPMethodTLS *
+eap_method_tls_new (NMConnection *connection)
+{
+ EAPMethodTLS *self;
+ NMSetting8021x *s_8021x = NULL;
+ gboolean ca_not_required = FALSE;
+
+ self = g_object_new (eap_method_tls_get_type (), NULL);
+
+ if (connection)
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+
+ g_signal_connect_swapped (self->ca_cert_not_required_check, "toggled", G_CALLBACK (ca_cert_not_required_toggled), self);
+
+ g_signal_connect_swapped (self->identity_entry, "changed", G_CALLBACK (changed_cb), self);
+ if (s_8021x && nm_setting_802_1x_get_identity (s_8021x))
+ gtk_editable_set_text (GTK_EDITABLE (self->identity_entry), nm_setting_802_1x_get_identity (s_8021x));
+
+ setup_filepicker (self,
+ self->user_cert_button,
+ _("Choose your personal certificate"),
+ s_8021x,
+ nm_setting_802_1x_get_client_cert_scheme,
+ nm_setting_802_1x_get_client_cert_path,
+ FALSE, TRUE);
+ setup_filepicker (self,
+ self->ca_cert_button,
+ _("Choose a Certificate Authority certificate"),
+ s_8021x,
+ nm_setting_802_1x_get_ca_cert_scheme,
+ nm_setting_802_1x_get_ca_cert_path,
+ FALSE, FALSE);
+ setup_filepicker (self,
+ self->private_key_button,
+ _("Choose your private key"),
+ s_8021x,
+ nm_setting_802_1x_get_private_key_scheme,
+ nm_setting_802_1x_get_private_key_path,
+ TRUE, FALSE);
+
+ if (connection && eap_method_ca_cert_ignore_get (EAP_METHOD (self), connection)) {
+ g_autoptr(GFile) file = ws_file_chooser_button_get_file (self->ca_cert_button);
+ ca_not_required = !file;
+ }
+ gtk_check_button_set_active (self->ca_cert_not_required_check, ca_not_required);
+
+ /* Fill secrets, if any */
+ if (connection)
+ update_secrets (EAP_METHOD (self), connection);
+
+ g_signal_connect_swapped (self->private_key_password_entry, "changed", G_CALLBACK (changed_cb), self);
+
+ /* Create password-storage popup menu for password entry under entry's secondary icon */
+ nma_utils_setup_password_storage (GTK_WIDGET (self->private_key_password_entry), 0, (NMSetting *) s_8021x, NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD,
+ FALSE, FALSE);
+
+ g_signal_connect_swapped (self->show_password_check, "toggled", G_CALLBACK (show_toggled_cb), self);
+
+ return self;
+}
+
diff --git a/panels/network/wireless-security/eap-method-tls.h b/panels/network/wireless-security/eap-method-tls.h
new file mode 100644
index 0000000..27f3843
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-tls.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (EAPMethodTLS, eap_method_tls, EAP, METHOD_TLS, GtkGrid)
+
+EAPMethodTLS *eap_method_tls_new (NMConnection *connection);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/eap-method-tls.ui b/panels/network/wireless-security/eap-method-tls.ui
new file mode 100644
index 0000000..69c2610
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-tls.ui
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.4"/>
+ <template class="EAPMethodTLS" parent="GtkGrid">
+ <property name="valign">start</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="identity_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">I_dentity</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">identity_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="identity_entry">
+ <property name="hexpand">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="user_cert_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_User certificate</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">user_cert_button</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="WsFileChooserButton" id="user_cert_button">
+ <property name="hexpand">True</property>
+ <property name="title" translatable="yes">Choose a Certificate Authority certificate</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="ca_cert_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">C_A certificate</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">ca_cert_button</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="WsFileChooserButton" id="ca_cert_button">
+ <property name="hexpand">True</property>
+ <property name="title" translatable="yes">Choose a Certificate Authority certificate</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="ca_cert_not_required_check">
+ <property name="label" translatable="yes">No CA certificate is _required</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="private_key_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Private _key</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">private_key_button</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">4</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="WsFileChooserButton" id="private_key_button">
+ <property name="hexpand">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">4</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="private_key_password_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Private key password</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">private_key_password_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">5</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="private_key_password_entry">
+ <property name="hexpand">True</property>
+ <property name="visibility">False</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">5</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="show_password_check">
+ <property name="label" translatable="yes">Sho_w password</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">6</property>
+ </layout>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/wireless-security/eap-method-ttls.c b/panels/network/wireless-security/eap-method-ttls.c
new file mode 100644
index 0000000..b41a57f
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-ttls.c
@@ -0,0 +1,415 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#include <glib/gi18n.h>
+
+#include "eap-method.h"
+#include "eap-method-simple.h"
+#include "eap-method-ttls.h"
+#include "helpers.h"
+#include "ws-file-chooser-button.h"
+
+#define I_NAME_COLUMN 0
+#define I_ID_COLUMN 1
+
+struct _EAPMethodTTLS {
+ GtkGrid parent;
+
+ GtkEntry *anon_identity_entry;
+ GtkLabel *anon_identity_label;
+ WsFileChooserButton *ca_cert_button;
+ GtkLabel *ca_cert_label;
+ GtkCheckButton *ca_cert_not_required_check;
+ GtkEntry *domain_match_entry;
+ GtkLabel *domain_match_label;
+ GtkComboBox *inner_auth_combo;
+ GtkLabel *inner_auth_label;
+ GtkListStore *inner_auth_model;
+ GtkBox *inner_auth_box;
+
+ EAPMethodSimple *em_chap;
+ EAPMethodSimple *em_gtc;
+ EAPMethodSimple *em_md5;
+ EAPMethodSimple *em_mschap;
+ EAPMethodSimple *em_mschap_v2;
+ EAPMethodSimple *em_pap;
+ EAPMethodSimple *em_plain_mschap_v2;
+};
+
+static void eap_method_iface_init (EAPMethodInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (EAPMethodTTLS, eap_method_ttls, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (eap_method_get_type (), eap_method_iface_init))
+
+static EAPMethod *
+get_inner_method (EAPMethodTTLS *self)
+{
+ GtkTreeIter iter;
+ g_autofree gchar *id = NULL;
+
+ if (!gtk_combo_box_get_active_iter (self->inner_auth_combo, &iter))
+ return NULL;
+ gtk_tree_model_get (GTK_TREE_MODEL (self->inner_auth_model), &iter, I_ID_COLUMN, &id, -1);
+
+ if (strcmp (id, "chap") == 0)
+ return EAP_METHOD (self->em_chap);
+ if (strcmp (id, "gtc") == 0)
+ return EAP_METHOD (self->em_gtc);
+ if (strcmp (id, "md5") == 0)
+ return EAP_METHOD (self->em_md5);
+ if (strcmp (id, "mschap") == 0)
+ return EAP_METHOD (self->em_mschap);
+ if (strcmp (id, "mschapv2") == 0)
+ return EAP_METHOD (self->em_mschap_v2);
+ if (strcmp (id, "pap") == 0)
+ return EAP_METHOD (self->em_pap);
+ if (strcmp (id, "plain_mschapv2") == 0)
+ return EAP_METHOD (self->em_plain_mschap_v2);
+
+ return NULL;
+}
+
+static gboolean
+validate (EAPMethod *method, GError **error)
+{
+ EAPMethodTTLS *self = EAP_METHOD_TTLS (method);
+ g_autoptr(GError) local_error = NULL;
+
+ if (!eap_method_validate_filepicker (ws_file_chooser_button_get_filechooser (self->ca_cert_button),
+ TYPE_CA_CERT, NULL, NULL, &local_error)) {
+ g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid EAP-TTLS CA certificate: %s"), local_error->message);
+ return FALSE;
+ }
+ if (!gtk_check_button_get_active (GTK_CHECK_BUTTON (self->ca_cert_not_required_check))) {
+ g_autoptr(GFile) file = NULL;
+
+ file = ws_file_chooser_button_get_file (self->ca_cert_button);
+ if (file == NULL) {
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid EAP-TTLS CA certificate: no certificate specified"));
+ return FALSE;
+ }
+ }
+
+ return eap_method_validate (get_inner_method (self), error);
+}
+
+static void
+ca_cert_not_required_toggled (EAPMethodTTLS *self)
+{
+ eap_method_ca_cert_not_required_toggled (self->ca_cert_not_required_check,
+ ws_file_chooser_button_get_filechooser (self->ca_cert_button));
+ eap_method_emit_changed (EAP_METHOD (self));
+}
+
+static void
+add_to_size_group (EAPMethod *method, GtkSizeGroup *group)
+{
+ EAPMethodTTLS *self = EAP_METHOD_TTLS (method);
+
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->ca_cert_not_required_check));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->anon_identity_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->domain_match_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->ca_cert_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->inner_auth_label));
+
+ eap_method_add_to_size_group (EAP_METHOD (self->em_chap), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_gtc), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_md5), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_mschap), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_mschap_v2), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_pap), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_plain_mschap_v2), group);
+}
+
+static void
+fill_connection (EAPMethod *method, NMConnection *connection, NMSettingSecretFlags flags)
+{
+ EAPMethodTTLS *self = EAP_METHOD_TTLS (method);
+ NMSetting8021x *s_8021x;
+ NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ const char *text;
+ g_autofree gchar *filename = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GFile) file = NULL;
+ gboolean ca_cert_error = FALSE;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ g_assert (s_8021x);
+
+ nm_setting_802_1x_add_eap_method (s_8021x, "ttls");
+
+ text = gtk_editable_get_text (GTK_EDITABLE (self->anon_identity_entry));
+ if (text && strlen (text))
+ g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, text, NULL);
+
+ text = gtk_editable_get_text (GTK_EDITABLE (self->domain_match_entry));
+ if (text && strlen (text))
+ g_object_set (s_8021x, NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH, text, NULL);
+
+ file = ws_file_chooser_button_get_file (self->ca_cert_button);
+ filename = file ? g_file_get_path (file) : NULL;
+ if (!nm_setting_802_1x_set_ca_cert (s_8021x, filename, NM_SETTING_802_1X_CK_SCHEME_PATH, &format, &error)) {
+ g_warning ("Couldn't read CA certificate '%s': %s", filename, error ? error->message : "(unknown)");
+ ca_cert_error = TRUE;
+ }
+ eap_method_ca_cert_ignore_set (method, connection, filename, ca_cert_error);
+
+ eap_method_fill_connection (get_inner_method (self), connection, flags);
+}
+
+static void
+inner_auth_combo_changed_cb (EAPMethodTTLS *self)
+{
+ EAPMethod *inner_method;
+ GtkWidget *child;
+
+ inner_method = get_inner_method (self);
+
+ /* Remove the previous method and migrate username/password across */
+ child = gtk_widget_get_first_child (GTK_WIDGET (self->inner_auth_box));
+ if (child != NULL) {
+ EAPMethod *old_eap = EAP_METHOD (child);
+ eap_method_set_username (inner_method, eap_method_get_username (old_eap));
+ eap_method_set_password (inner_method, eap_method_get_password (old_eap));
+ eap_method_set_show_password (inner_method, eap_method_get_show_password (old_eap));
+ gtk_box_remove (self->inner_auth_box, child);
+ }
+
+ gtk_box_append (self->inner_auth_box, g_object_ref (GTK_WIDGET (inner_method)));
+
+ eap_method_emit_changed (EAP_METHOD (self));
+}
+
+static void
+update_secrets (EAPMethod *method, NMConnection *connection)
+{
+ EAPMethodTTLS *self = EAP_METHOD_TTLS (method);
+
+ eap_method_update_secrets (EAP_METHOD (self->em_chap), connection);
+ eap_method_update_secrets (EAP_METHOD (self->em_gtc), connection);
+ eap_method_update_secrets (EAP_METHOD (self->em_md5), connection);
+ eap_method_update_secrets (EAP_METHOD (self->em_mschap), connection);
+ eap_method_update_secrets (EAP_METHOD (self->em_mschap_v2), connection);
+ eap_method_update_secrets (EAP_METHOD (self->em_pap), connection);
+ eap_method_update_secrets (EAP_METHOD (self->em_plain_mschap_v2), connection);
+}
+
+static GtkWidget *
+get_default_field (EAPMethod *method)
+{
+ EAPMethodTTLS *self = EAP_METHOD_TTLS (method);
+ return GTK_WIDGET (self->anon_identity_entry);
+}
+
+static const gchar *
+get_password_flags_name (EAPMethod *method)
+{
+ return NM_SETTING_802_1X_PASSWORD;
+}
+
+static const gchar *
+get_username (EAPMethod *method)
+{
+ EAPMethodTTLS *self = EAP_METHOD_TTLS (method);
+ return eap_method_get_username (get_inner_method (self));
+}
+
+static void
+set_username (EAPMethod *method, const gchar *username)
+{
+ EAPMethodTTLS *self = EAP_METHOD_TTLS (method);
+ return eap_method_set_username (get_inner_method (self), username);
+}
+
+static const gchar *
+get_password (EAPMethod *method)
+{
+ EAPMethodTTLS *self = EAP_METHOD_TTLS (method);
+ return eap_method_get_password (get_inner_method (self));
+}
+
+static void
+set_password (EAPMethod *method, const gchar *password)
+{
+ EAPMethodTTLS *self = EAP_METHOD_TTLS (method);
+ return eap_method_set_password (get_inner_method (self), password);
+}
+
+static gboolean
+get_show_password (EAPMethod *method)
+{
+ EAPMethodTTLS *self = EAP_METHOD_TTLS (method);
+ return eap_method_get_show_password (get_inner_method (self));
+}
+
+static void
+set_show_password (EAPMethod *method, gboolean show_password)
+{
+ EAPMethodTTLS *self = EAP_METHOD_TTLS (method);
+ return eap_method_set_show_password (get_inner_method (self), show_password);
+}
+
+static void
+changed_cb (EAPMethodTTLS *self)
+{
+ eap_method_emit_changed (EAP_METHOD (self));
+}
+
+static void
+eap_method_ttls_init (EAPMethodTTLS *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static void
+eap_method_ttls_class_init (EAPMethodTTLSClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Settings/network/eap-method-ttls.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTTLS, anon_identity_entry);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTTLS, anon_identity_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTTLS, ca_cert_button);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTTLS, ca_cert_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTTLS, ca_cert_not_required_check);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTTLS, domain_match_entry);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTTLS, domain_match_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTTLS, inner_auth_combo);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTTLS, inner_auth_label);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTTLS, inner_auth_model);
+ gtk_widget_class_bind_template_child (widget_class, EAPMethodTTLS, inner_auth_box);
+}
+
+static void
+eap_method_iface_init (EAPMethodInterface *iface)
+{
+ iface->validate = validate;
+ iface->add_to_size_group = add_to_size_group;
+ iface->fill_connection = fill_connection;
+ iface->update_secrets = update_secrets;
+ iface->get_default_field = get_default_field;
+ iface->get_password_flags_name = get_password_flags_name;
+ iface->get_username = get_username;
+ iface->set_username = set_username;
+ iface->get_password = get_password;
+ iface->set_password = set_password;
+ iface->get_show_password = get_show_password;
+ iface->set_show_password = set_show_password;
+}
+
+EAPMethodTTLS *
+eap_method_ttls_new (NMConnection *connection)
+{
+ EAPMethodTTLS *self;
+ GtkFileFilter *filter;
+ NMSetting8021x *s_8021x = NULL;
+ const char *filename;
+ const char *phase2_auth = NULL;
+ GtkTreeIter iter;
+
+ self = g_object_new (eap_method_ttls_get_type (), NULL);
+
+ if (connection)
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+
+ g_signal_connect_swapped (self->ca_cert_not_required_check, "toggled", G_CALLBACK (ca_cert_not_required_toggled), self);
+
+ g_signal_connect_swapped (self->ca_cert_button, "notify::file", G_CALLBACK (changed_cb), self);
+ filter = eap_method_default_file_chooser_filter_new (FALSE);
+ gtk_file_chooser_add_filter (ws_file_chooser_button_get_filechooser (self->ca_cert_button),
+ filter);
+ if (connection && s_8021x) {
+ filename = NULL;
+ if (nm_setting_802_1x_get_ca_cert_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH) {
+ filename = nm_setting_802_1x_get_ca_cert_path (s_8021x);
+ if (filename) {
+ g_autoptr(GFile) file = g_file_new_for_path (filename);
+ ws_file_chooser_button_set_file (self->ca_cert_button, file);
+ }
+ }
+ gtk_check_button_set_active (self->ca_cert_not_required_check,
+ !filename && eap_method_ca_cert_ignore_get (EAP_METHOD (self), connection));
+ }
+
+ if (s_8021x && nm_setting_802_1x_get_anonymous_identity (s_8021x))
+ gtk_editable_set_text (GTK_EDITABLE (self->anon_identity_entry), nm_setting_802_1x_get_anonymous_identity (s_8021x));
+ g_signal_connect_swapped (self->anon_identity_entry, "changed", G_CALLBACK (changed_cb), self);
+ if (s_8021x && nm_setting_802_1x_get_domain_suffix_match (s_8021x))
+ gtk_editable_set_text (GTK_EDITABLE (self->domain_match_entry), nm_setting_802_1x_get_domain_suffix_match (s_8021x));
+ g_signal_connect_swapped (self->domain_match_entry, "changed", G_CALLBACK (changed_cb), self);
+
+ self->em_pap = eap_method_simple_new (connection, "pap", TRUE, FALSE);
+ gtk_widget_show (GTK_WIDGET (self->em_pap));
+ g_signal_connect_object (self->em_pap, "changed", G_CALLBACK (eap_method_emit_changed), self, G_CONNECT_SWAPPED);
+
+ self->em_mschap = eap_method_simple_new (connection, "mschap", TRUE, FALSE);
+ gtk_widget_show (GTK_WIDGET (self->em_mschap));
+ g_signal_connect_object (self->em_mschap, "changed", G_CALLBACK (eap_method_emit_changed), self, G_CONNECT_SWAPPED);
+
+ self->em_mschap_v2 = eap_method_simple_new (connection, "mschapv2", TRUE, TRUE);
+ gtk_widget_show (GTK_WIDGET (self->em_mschap_v2));
+ g_signal_connect_object (self->em_mschap_v2, "changed", G_CALLBACK (eap_method_emit_changed), self, G_CONNECT_SWAPPED);
+
+ self->em_plain_mschap_v2 = eap_method_simple_new (connection, "mschapv2", TRUE, FALSE);
+ gtk_widget_show (GTK_WIDGET (self->em_plain_mschap_v2));
+ g_signal_connect_object (self->em_plain_mschap_v2, "changed", G_CALLBACK (eap_method_emit_changed), self, G_CONNECT_SWAPPED);
+
+ self->em_chap = eap_method_simple_new (connection, "chap", TRUE, FALSE);
+ gtk_widget_show (GTK_WIDGET (self->em_chap));
+ g_signal_connect_object (self->em_chap, "changed", G_CALLBACK (eap_method_emit_changed), self, G_CONNECT_SWAPPED);
+
+ self->em_md5 = eap_method_simple_new (connection, "md5", TRUE, TRUE);
+ gtk_widget_show (GTK_WIDGET (self->em_md5));
+ g_signal_connect_object (self->em_md5, "changed", G_CALLBACK (eap_method_emit_changed), self, G_CONNECT_SWAPPED);
+
+ self->em_gtc = eap_method_simple_new (connection, "gtc", TRUE, TRUE);
+ gtk_widget_show (GTK_WIDGET (self->em_gtc));
+ g_signal_connect_object (self->em_gtc, "changed", G_CALLBACK (eap_method_emit_changed), self, G_CONNECT_SWAPPED);
+
+ if (s_8021x) {
+ if (nm_setting_802_1x_get_phase2_auth (s_8021x))
+ phase2_auth = nm_setting_802_1x_get_phase2_auth (s_8021x);
+ else if (nm_setting_802_1x_get_phase2_autheap (s_8021x))
+ phase2_auth = nm_setting_802_1x_get_phase2_autheap (s_8021x);
+ }
+ if (phase2_auth == NULL)
+ phase2_auth = "pap";
+
+ if (strcmp (phase2_auth, "mschapv2") == 0 && nm_setting_802_1x_get_phase2_auth (s_8021x) != NULL)
+ phase2_auth = "plain_mschapv2";
+
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->inner_auth_model), &iter)) {
+ do {
+ g_autofree gchar *id = NULL;
+ gtk_tree_model_get (GTK_TREE_MODEL (self->inner_auth_model), &iter, I_ID_COLUMN, &id, -1);
+ if (strcmp (id, phase2_auth) == 0)
+ gtk_combo_box_set_active_iter (self->inner_auth_combo, &iter);
+ } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->inner_auth_model), &iter));
+ }
+
+ g_signal_connect_swapped (self->inner_auth_combo, "changed", G_CALLBACK (inner_auth_combo_changed_cb), self);
+ inner_auth_combo_changed_cb (self);
+
+ return self;
+}
+
diff --git a/panels/network/wireless-security/eap-method-ttls.h b/panels/network/wireless-security/eap-method-ttls.h
new file mode 100644
index 0000000..56b7085
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-ttls.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (EAPMethodTTLS, eap_method_ttls, EAP, METHOD_TTLS, GtkGrid)
+
+EAPMethodTTLS *eap_method_ttls_new (NMConnection *connection);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/eap-method-ttls.ui b/panels/network/wireless-security/eap-method-ttls.ui
new file mode 100644
index 0000000..b10dac2
--- /dev/null
+++ b/panels/network/wireless-security/eap-method-ttls.ui
@@ -0,0 +1,160 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.4"/>
+ <object class="GtkListStore" id="inner_auth_model">
+ <columns>
+ <!-- column-name label -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">PAP</col>
+ <col id="1">pap</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">MSCHAP</col>
+ <col id="1">mschap</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">MSCHAPv2</col>
+ <col id="1">mschapv2</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">MSCHAPv2 (no EAP)</col>
+ <col id="1">plain_mschapv2</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">CHAP</col>
+ <col id="1">chap</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">MD5</col>
+ <col id="1">md5</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">GTC</col>
+ <col id="1">gtc</col>
+ </row>
+ </data>
+ </object>
+ <template class="EAPMethodTTLS" parent="GtkGrid">
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="anon_identity_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Anony_mous identity</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">anon_identity_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="anon_identity_entry">
+ <property name="hexpand">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="domain_match_label">
+ <property name="label" translatable="yes">_Domain</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">domain_match_entry</property>
+ <property name="xalign">1</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="domain_match_entry">
+ <property name="hexpand">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="ca_cert_label">
+ <property name="label" translatable="yes">C_A certificate</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">ca_cert_button</property>
+ <property name="xalign">1</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="WsFileChooserButton" id="ca_cert_button">
+ <property name="hexpand">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="ca_cert_not_required_check">
+ <property name="label" translatable="yes">No CA certificate is _required</property>
+ <property name="halign">start</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="inner_auth_label">
+ <property name="label" translatable="yes">_Inner authentication</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">inner_auth_combo</property>
+ <property name="xalign">1</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">4</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="inner_auth_combo">
+ <property name="hexpand">True</property>
+ <property name="model">inner_auth_model</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">4</property>
+ </layout>
+ <child>
+ <object class="GtkCellRendererText"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="inner_auth_box">
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">5</property>
+ <property name="column-span">2</property>
+ </layout>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/wireless-security/eap-method.c b/panels/network/wireless-security/eap-method.c
new file mode 100644
index 0000000..a9d11c7
--- /dev/null
+++ b/panels/network/wireless-security/eap-method.c
@@ -0,0 +1,588 @@
+/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#include <fcntl.h>
+#include <glib/gi18n.h>
+
+#include "eap-method.h"
+#include "helpers.h"
+#include "ui-helpers.h"
+
+G_DEFINE_INTERFACE (EAPMethod, eap_method, G_TYPE_OBJECT)
+
+enum {
+ CHANGED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void
+eap_method_default_init (EAPMethodInterface *iface)
+{
+ signals[CHANGED] =
+ g_signal_new ("changed",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_FIRST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+GtkWidget *
+eap_method_get_default_field (EAPMethod *self)
+{
+ g_return_val_if_fail (self != NULL, NULL);
+
+ return EAP_METHOD_GET_IFACE (self)->get_default_field (self);
+}
+
+const gchar *
+eap_method_get_password_flags_name (EAPMethod *self)
+{
+ g_return_val_if_fail (self != NULL, NULL);
+
+ if (EAP_METHOD_GET_IFACE (self)->get_password_flags_name)
+ return EAP_METHOD_GET_IFACE (self)->get_password_flags_name (self);
+ else
+ return NULL;
+}
+
+gboolean
+eap_method_get_phase2 (EAPMethod *self)
+{
+ g_return_val_if_fail (self != NULL, FALSE);
+
+ if (EAP_METHOD_GET_IFACE (self)->get_phase2)
+ return EAP_METHOD_GET_IFACE (self)->get_phase2 (self);
+ else
+ return FALSE;
+}
+
+gboolean
+eap_method_validate (EAPMethod *self, GError **error)
+{
+ gboolean result;
+
+ g_return_val_if_fail (self != NULL, FALSE);
+
+ result = (*(EAP_METHOD_GET_IFACE (self)->validate)) (self, error);
+ if (!result && error && !*error)
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("undefined error in 802.1X security (wpa-eap)"));
+ return result;
+}
+
+void
+eap_method_update_secrets (EAPMethod *self, NMConnection *connection)
+{
+ g_return_if_fail (self != NULL);
+
+ if (EAP_METHOD_GET_IFACE (self)->update_secrets)
+ EAP_METHOD_GET_IFACE (self)->update_secrets (self, connection);
+}
+
+void
+eap_method_add_to_size_group (EAPMethod *self, GtkSizeGroup *group)
+{
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (group != NULL);
+
+ return (*(EAP_METHOD_GET_IFACE (self)->add_to_size_group)) (self, group);
+}
+
+void
+eap_method_fill_connection (EAPMethod *self,
+ NMConnection *connection,
+ NMSettingSecretFlags flags)
+{
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (connection != NULL);
+
+ return (*(EAP_METHOD_GET_IFACE (self)->fill_connection)) (self, connection, flags);
+}
+
+void
+eap_method_emit_changed (EAPMethod *self)
+{
+ g_return_if_fail (EAP_IS_METHOD (self));
+
+ g_signal_emit (self, signals[CHANGED], 0);
+}
+
+const gchar *
+eap_method_get_username (EAPMethod *self)
+{
+ g_return_val_if_fail (EAP_IS_METHOD (self), NULL);
+ return EAP_METHOD_GET_IFACE (self)->get_username (self);
+}
+
+void
+eap_method_set_username (EAPMethod *self, const gchar *username)
+{
+ g_return_if_fail (EAP_IS_METHOD (self));
+ EAP_METHOD_GET_IFACE (self)->set_username (self, username);
+}
+
+const gchar *
+eap_method_get_password (EAPMethod *self)
+{
+ g_return_val_if_fail (EAP_IS_METHOD (self), NULL);
+ return EAP_METHOD_GET_IFACE (self)->get_password (self);
+}
+
+void
+eap_method_set_password (EAPMethod *self, const gchar *password)
+{
+ g_return_if_fail (EAP_IS_METHOD (self));
+ EAP_METHOD_GET_IFACE (self)->set_password (self, password);
+}
+
+gboolean
+eap_method_get_show_password (EAPMethod *self)
+{
+ g_return_val_if_fail (EAP_IS_METHOD (self), FALSE);
+ return EAP_METHOD_GET_IFACE (self)->get_show_password (self);
+}
+
+void
+eap_method_set_show_password (EAPMethod *self, gboolean show_password)
+{
+ g_return_if_fail (EAP_IS_METHOD (self));
+ EAP_METHOD_GET_IFACE (self)->set_show_password (self, show_password);
+}
+
+gboolean
+eap_method_validate_filepicker (GtkFileChooser *chooser,
+ guint32 item_type,
+ const char *password,
+ NMSetting8021xCKFormat *out_format,
+ GError **error)
+{
+ g_autofree gchar *filename = NULL;
+ g_autoptr(NMSetting8021x) setting = NULL;
+ g_autoptr(GFile) file = NULL;
+ gboolean success = TRUE;
+
+ if (item_type == TYPE_PRIVATE_KEY) {
+ if (!password || *password == '\0')
+ success = FALSE;
+ }
+
+ file = gtk_file_chooser_get_file (chooser);
+ if (!file) {
+ if (item_type != TYPE_CA_CERT) {
+ success = FALSE;
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("no file selected"));
+ }
+ goto out;
+ }
+
+ filename = g_file_get_path (file);
+ if (!g_file_test (filename, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
+ success = FALSE;
+ goto out;
+ }
+
+ setting = (NMSetting8021x *) nm_setting_802_1x_new ();
+
+ success = FALSE;
+ if (item_type == TYPE_PRIVATE_KEY) {
+ if (nm_setting_802_1x_set_private_key (setting, filename, password, NM_SETTING_802_1X_CK_SCHEME_PATH, out_format, error))
+ success = TRUE;
+ } else if (item_type == TYPE_CLIENT_CERT) {
+ if (nm_setting_802_1x_set_client_cert (setting, filename, NM_SETTING_802_1X_CK_SCHEME_PATH, out_format, error))
+ success = TRUE;
+ } else if (item_type == TYPE_CA_CERT) {
+ if (nm_setting_802_1x_set_ca_cert (setting, filename, NM_SETTING_802_1X_CK_SCHEME_PATH, out_format, error))
+ success = TRUE;
+ } else
+ g_warning ("%s: invalid item type %d.", __func__, item_type);
+
+out:
+ if (!success && error && !*error)
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("unspecified error validating eap-method file"));
+
+ if (success)
+ widget_unset_error (GTK_WIDGET (chooser));
+ else
+ widget_set_error (GTK_WIDGET (chooser));
+ return success;
+}
+
+static gboolean
+file_is_mime_type (const char *path, const char *mime_types[])
+{
+ g_autoptr(GFile) file = NULL;
+ g_autoptr(GFileInfo) info = NULL;
+ const char *content_type;
+ int i = 0;
+ gboolean found = FALSE;
+
+ file = g_file_new_for_path (path);
+ info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ NULL);
+ if (info) {
+ content_type = g_file_info_get_content_type (info);
+ if (content_type) {
+ while (mime_types[i]) {
+ if (strcmp (content_type, mime_types[i++]) == 0) {
+ found = TRUE;
+ break;
+ }
+ }
+ }
+ }
+
+ return found;
+}
+
+#if !LIBNM_BUILD
+static const char *
+find_tag (const char *tag, const char *buf, gsize len)
+{
+ gsize i, taglen;
+
+ taglen = strlen (tag);
+ if (len < taglen)
+ return NULL;
+
+ for (i = 0; i < len - taglen + 1; i++) {
+ if (memcmp (buf + i, tag, taglen) == 0)
+ return buf + i;
+ }
+ return NULL;
+}
+
+static const char *pem_rsa_key_begin = "-----BEGIN RSA PRIVATE KEY-----";
+static const char *pem_dsa_key_begin = "-----BEGIN DSA PRIVATE KEY-----";
+static const char *pem_pkcs8_enc_key_begin = "-----BEGIN ENCRYPTED PRIVATE KEY-----";
+static const char *pem_pkcs8_dec_key_begin = "-----BEGIN PRIVATE KEY-----";
+static const char *pem_cert_begin = "-----BEGIN CERTIFICATE-----";
+static const char *proc_type_tag = "Proc-Type: 4,ENCRYPTED";
+static const char *dek_info_tag = "DEK-Info:";
+
+static gboolean
+pem_file_is_encrypted (const char *buffer, gsize bytes_read)
+{
+ /* Check if the private key is encrypted or not by looking for the
+ * old OpenSSL-style proc-type and dec-info tags.
+ */
+ if (find_tag (proc_type_tag, (const char *) buffer, bytes_read)) {
+ if (find_tag (dek_info_tag, (const char *) buffer, bytes_read))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+file_is_der_or_pem (const char *filename,
+ gboolean privkey,
+ gboolean *out_privkey_encrypted)
+{
+ int fd;
+ unsigned char buffer[8192];
+ ssize_t bytes_read;
+ gboolean success = FALSE;
+
+ fd = open (filename, O_RDONLY);
+ if (fd < 0)
+ return FALSE;
+
+ bytes_read = read (fd, buffer, sizeof (buffer) - 1);
+ if (bytes_read < 400) /* needs to be lower? */
+ goto out;
+ buffer[bytes_read] = '\0';
+
+ /* Check for DER signature */
+ if (bytes_read > 2 && buffer[0] == 0x30 && buffer[1] == 0x82) {
+ success = TRUE;
+ goto out;
+ }
+
+ /* Check for PEM signatures */
+ if (privkey) {
+ if (find_tag (pem_rsa_key_begin, (const char *) buffer, bytes_read)) {
+ success = TRUE;
+ if (out_privkey_encrypted)
+ *out_privkey_encrypted = pem_file_is_encrypted ((const char *) buffer, bytes_read);
+ goto out;
+ }
+
+ if (find_tag (pem_dsa_key_begin, (const char *) buffer, bytes_read)) {
+ success = TRUE;
+ if (out_privkey_encrypted)
+ *out_privkey_encrypted = pem_file_is_encrypted ((const char *) buffer, bytes_read);
+ goto out;
+ }
+
+ if (find_tag (pem_pkcs8_enc_key_begin, (const char *) buffer, bytes_read)) {
+ success = TRUE;
+ if (out_privkey_encrypted)
+ *out_privkey_encrypted = TRUE;
+ goto out;
+ }
+
+ if (find_tag (pem_pkcs8_dec_key_begin, (const char *) buffer, bytes_read)) {
+ success = TRUE;
+ if (out_privkey_encrypted)
+ *out_privkey_encrypted = FALSE;
+ goto out;
+ }
+ } else {
+ if (find_tag (pem_cert_begin, (const char *) buffer, bytes_read)) {
+ success = TRUE;
+ goto out;
+ }
+ }
+
+out:
+ close (fd);
+ return success;
+}
+#endif
+
+static const char *privkey_mime_types[] = {
+ "application/x-x509-ca-cert", "application/pkcs12", "application/x-pkcs12", "application/pgp-keys", NULL
+};
+static const char *cert_mime_types[] = {
+ "application/x-x509-ca-cert", NULL
+};
+
+static void
+add_mime_types_to_filter (GtkFileFilter *filter,
+ const char **mime_types)
+{
+ int i;
+
+ for (i = 0; mime_types[i] != NULL; i++)
+ gtk_file_filter_add_mime_type (filter, mime_types[i]);
+}
+
+
+GtkFileFilter *
+eap_method_default_file_chooser_filter_new (gboolean privkey)
+{
+ GtkFileFilter *filter;
+
+ filter = gtk_file_filter_new ();
+ if (privkey) {
+ add_mime_types_to_filter (filter, privkey_mime_types);
+ gtk_file_filter_set_name (filter, _("DER, PEM, PKCS#12, or PGP private keys"));
+ } else {
+ add_mime_types_to_filter (filter, cert_mime_types);
+ gtk_file_filter_set_name (filter, _("DER or PEM certificates"));
+ }
+ return filter;
+}
+
+gboolean
+eap_method_is_encrypted_private_key (const char *path)
+{
+ gboolean is_encrypted;
+
+ if (!file_is_mime_type (path, privkey_mime_types))
+ return FALSE;
+
+#if LIBNM_BUILD
+ is_encrypted = FALSE;
+ if (!nm_utils_file_is_private_key (path, &is_encrypted))
+ return FALSE;
+#else
+ is_encrypted = TRUE;
+ if ( !file_is_der_or_pem (path, TRUE, &is_encrypted)
+ && !nm_utils_file_is_pkcs12 (path))
+ return FALSE;
+#endif
+ return is_encrypted;
+}
+
+void
+eap_method_ca_cert_not_required_toggled (GtkCheckButton *id_ca_cert_not_required_checkbutton, GtkFileChooser *id_ca_cert_chooser)
+{
+ g_autoptr(GFile) file = NULL;
+ g_autoptr(GFile) file_old = NULL;
+ gboolean is_not_required;
+
+ g_assert (id_ca_cert_not_required_checkbutton && id_ca_cert_chooser);
+
+ is_not_required = gtk_check_button_get_active (id_ca_cert_not_required_checkbutton);
+
+ file = gtk_file_chooser_get_file (id_ca_cert_chooser);
+ file_old = g_object_steal_data (G_OBJECT (id_ca_cert_chooser), "filename-old");
+ if (is_not_required) {
+ g_clear_object (&file_old);
+ file_old = g_steal_pointer (&file);
+ } else {
+ g_clear_object (&file);
+ file = g_steal_pointer (&file_old);
+ }
+ gtk_widget_set_sensitive (GTK_WIDGET (id_ca_cert_chooser), !is_not_required);
+ if (file)
+ gtk_file_chooser_set_file (id_ca_cert_chooser, file, NULL);
+ g_object_set_data_full (G_OBJECT (id_ca_cert_chooser), "filename-old", g_steal_pointer (&file_old), g_free);
+}
+
+/* Used as both GSettings keys and GObject data tags */
+#define IGNORE_CA_CERT_TAG "ignore-ca-cert"
+#define IGNORE_PHASE2_CA_CERT_TAG "ignore-phase2-ca-cert"
+
+/**
+ * eap_method_ca_cert_ignore_set:
+ * @method: the #EAPMethod object
+ * @connection: the #NMConnection
+ * @filename: the certificate file, if any
+ * @ca_cert_error: %TRUE if an error was encountered loading the given CA
+ * certificate, %FALSE if not or if a CA certificate is not present
+ *
+ * Updates the connection's CA cert ignore value to %TRUE if the "CA certificate
+ * not required" checkbox is checked. If @ca_cert_error is %TRUE, then the
+ * connection's CA cert ignore value will always be set to %FALSE, because it
+ * means that the user selected an invalid certificate (thus he does not want to
+ * ignore the CA cert)..
+ */
+void
+eap_method_ca_cert_ignore_set (EAPMethod *self,
+ NMConnection *connection,
+ const char *filename,
+ gboolean ca_cert_error)
+{
+ NMSetting8021x *s_8021x;
+ gboolean ignore;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ if (s_8021x) {
+ ignore = !ca_cert_error && filename == NULL;
+ g_object_set_data (G_OBJECT (s_8021x),
+ eap_method_get_phase2 (self) ? IGNORE_PHASE2_CA_CERT_TAG : IGNORE_CA_CERT_TAG,
+ GUINT_TO_POINTER (ignore));
+ }
+}
+
+/**
+ * eap_method_ca_cert_ignore_get:
+ * @method: the #EAPMethod object
+ * @connection: the #NMConnection
+ *
+ * Returns: %TRUE if a missing CA certificate can be ignored, %FALSE if a CA
+ * certificate should be required for the connection to be valid.
+ */
+gboolean
+eap_method_ca_cert_ignore_get (EAPMethod *self, NMConnection *connection)
+{
+ NMSetting8021x *s_8021x;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ if (s_8021x) {
+ return !!g_object_get_data (G_OBJECT (s_8021x),
+ eap_method_get_phase2 (self) ? IGNORE_PHASE2_CA_CERT_TAG : IGNORE_CA_CERT_TAG);
+ }
+ return FALSE;
+}
+
+static GSettings *
+_get_ca_ignore_settings (NMConnection *connection)
+{
+ GSettings *settings;
+ g_autofree gchar *path = NULL;
+ const char *uuid;
+
+ g_return_val_if_fail (connection, NULL);
+
+ uuid = nm_connection_get_uuid (connection);
+ g_return_val_if_fail (uuid && *uuid, NULL);
+
+ path = g_strdup_printf ("/org/gnome/nm-applet/eap/%s/", uuid);
+ settings = g_settings_new_with_path ("org.gnome.nm-applet.eap", path);
+
+ return settings;
+}
+
+/**
+ * eap_method_ca_cert_ignore_save:
+ * @connection: the connection for which to save CA cert ignore values to GSettings
+ *
+ * Reads the CA cert ignore tags from the 802.1x setting GObject data and saves
+ * then to GSettings if present, using the connection UUID as the index.
+ */
+void
+eap_method_ca_cert_ignore_save (NMConnection *connection)
+{
+ NMSetting8021x *s_8021x;
+ g_autoptr(GSettings) settings = NULL;
+ gboolean ignore = FALSE, phase2_ignore = FALSE;
+
+ g_return_if_fail (connection);
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ if (s_8021x) {
+ ignore = !!g_object_get_data (G_OBJECT (s_8021x), IGNORE_CA_CERT_TAG);
+ phase2_ignore = !!g_object_get_data (G_OBJECT (s_8021x), IGNORE_PHASE2_CA_CERT_TAG);
+ }
+
+ settings = _get_ca_ignore_settings (connection);
+ if (!settings)
+ return;
+
+ g_settings_set_boolean (settings, IGNORE_CA_CERT_TAG, ignore);
+ g_settings_set_boolean (settings, IGNORE_PHASE2_CA_CERT_TAG, phase2_ignore);
+}
+
+/**
+ * eap_method_ca_cert_ignore_load:
+ * @connection: the connection for which to load CA cert ignore values to GSettings
+ *
+ * Reads the CA cert ignore tags from the 802.1x setting GObject data and saves
+ * then to GSettings if present, using the connection UUID as the index.
+ */
+void
+eap_method_ca_cert_ignore_load (NMConnection *connection)
+{
+ g_autoptr(GSettings) settings = NULL;
+ NMSetting8021x *s_8021x;
+ gboolean ignore, phase2_ignore;
+
+ g_return_if_fail (connection);
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ if (!s_8021x)
+ return;
+
+ settings = _get_ca_ignore_settings (connection);
+ if (!settings)
+ return;
+
+ ignore = g_settings_get_boolean (settings, IGNORE_CA_CERT_TAG);
+ phase2_ignore = g_settings_get_boolean (settings, IGNORE_PHASE2_CA_CERT_TAG);
+
+ g_object_set_data (G_OBJECT (s_8021x),
+ IGNORE_CA_CERT_TAG,
+ GUINT_TO_POINTER (ignore));
+ g_object_set_data (G_OBJECT (s_8021x),
+ IGNORE_PHASE2_CA_CERT_TAG,
+ GUINT_TO_POINTER (phase2_ignore));
+}
+
diff --git a/panels/network/wireless-security/eap-method.h b/panels/network/wireless-security/eap-method.h
new file mode 100644
index 0000000..d5a8908
--- /dev/null
+++ b/panels/network/wireless-security/eap-method.h
@@ -0,0 +1,108 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_INTERFACE (EAPMethod, eap_method, EAP, METHOD, GObject)
+
+struct _EAPMethodInterface {
+ GTypeInterface g_iface;
+
+ void (*add_to_size_group) (EAPMethod *method, GtkSizeGroup *group);
+ void (*fill_connection) (EAPMethod *method, NMConnection *connection, NMSettingSecretFlags flags);
+ void (*update_secrets) (EAPMethod *method, NMConnection *connection);
+ gboolean (*validate) (EAPMethod *method, GError **error);
+ GtkWidget* (*get_default_field) (EAPMethod *method);
+ const gchar* (*get_password_flags_name) (EAPMethod *method);
+ gboolean (*get_phase2) (EAPMethod *method);
+ const gchar* (*get_username) (EAPMethod *method);
+ void (*set_username) (EAPMethod *method, const gchar *username);
+ const gchar* (*get_password) (EAPMethod *method);
+ void (*set_password) (EAPMethod *method, const gchar *password);
+ gboolean (*get_show_password) (EAPMethod *method);
+ void (*set_show_password) (EAPMethod *method, gboolean show_password);
+};
+
+GtkWidget *eap_method_get_default_field (EAPMethod *method);
+
+const gchar *eap_method_get_password_flags_name (EAPMethod *method);
+
+gboolean eap_method_get_phase2 (EAPMethod *method);
+
+void eap_method_update_secrets (EAPMethod *method, NMConnection *connection);
+
+gboolean eap_method_validate (EAPMethod *method, GError **error);
+
+void eap_method_add_to_size_group (EAPMethod *method, GtkSizeGroup *group);
+
+void eap_method_fill_connection (EAPMethod *method,
+ NMConnection *connection,
+ NMSettingSecretFlags flags);
+
+void eap_method_emit_changed (EAPMethod *method);
+
+const gchar *eap_method_get_username (EAPMethod *method);
+
+void eap_method_set_username (EAPMethod *method, const gchar *username);
+
+const gchar *eap_method_get_password (EAPMethod *method);
+
+void eap_method_set_password (EAPMethod *method, const gchar *password);
+
+gboolean eap_method_get_show_password (EAPMethod *method);
+
+void eap_method_set_show_password (EAPMethod *method, gboolean show_password);
+
+/* Below for internal use only */
+
+GtkFileFilter * eap_method_default_file_chooser_filter_new (gboolean privkey);
+
+gboolean eap_method_is_encrypted_private_key (const char *path);
+
+#define TYPE_CLIENT_CERT 0
+#define TYPE_CA_CERT 1
+#define TYPE_PRIVATE_KEY 2
+
+gboolean eap_method_validate_filepicker (GtkFileChooser *chooser,
+ guint32 item_type,
+ const char *password,
+ NMSetting8021xCKFormat *out_format,
+ GError **error);
+
+void eap_method_ca_cert_not_required_toggled (GtkCheckButton *id_ca_cert_is_not_required_checkbox,
+ GtkFileChooser *id_ca_cert_chooser);
+
+void eap_method_ca_cert_ignore_set (EAPMethod *method,
+ NMConnection *connection,
+ const char *filename,
+ gboolean ca_cert_error);
+gboolean eap_method_ca_cert_ignore_get (EAPMethod *method, NMConnection *connection);
+
+void eap_method_ca_cert_ignore_save (NMConnection *connection);
+void eap_method_ca_cert_ignore_load (NMConnection *connection);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/helpers.c b/panels/network/wireless-security/helpers.c
new file mode 100644
index 0000000..fc8446b
--- /dev/null
+++ b/panels/network/wireless-security/helpers.c
@@ -0,0 +1,60 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2009 - 2014 Red Hat, Inc.
+ */
+
+#include "helpers.h"
+
+void
+helper_fill_secret_entry (NMConnection *connection,
+ GtkEntry *entry,
+ GType setting_type,
+ HelperSecretFunc func)
+{
+ NMSetting *setting;
+ const char *tmp;
+
+ g_return_if_fail (connection != NULL);
+ g_return_if_fail (entry != NULL);
+ g_return_if_fail (func != NULL);
+
+ setting = nm_connection_get_setting (connection, setting_type);
+ if (setting) {
+ tmp = (*func) (setting);
+ if (tmp) {
+ gtk_editable_set_text (GTK_EDITABLE (entry), tmp);
+ }
+ }
+}
+
+void
+wireless_security_clear_ciphers (NMConnection *connection)
+{
+ NMSettingWirelessSecurity *s_wireless_sec;
+
+ g_return_if_fail (connection != NULL);
+
+ s_wireless_sec = nm_connection_get_setting_wireless_security (connection);
+ g_assert (s_wireless_sec);
+
+ nm_setting_wireless_security_clear_protos (s_wireless_sec);
+ nm_setting_wireless_security_clear_pairwise (s_wireless_sec);
+ nm_setting_wireless_security_clear_groups (s_wireless_sec);
+}
diff --git a/panels/network/wireless-security/helpers.h b/panels/network/wireless-security/helpers.h
new file mode 100644
index 0000000..6a402d8
--- /dev/null
+++ b/panels/network/wireless-security/helpers.h
@@ -0,0 +1,45 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2009 - 2014 Red Hat, Inc.
+ */
+
+#ifndef _HELPERS_H_
+#define _HELPERS_H_
+
+#include <NetworkManager.h>
+#include <gtk/gtk.h>
+
+#define NMA_ERROR (g_quark_from_static_string ("nma-error-quark"))
+
+typedef enum {
+ NMA_ERROR_GENERIC
+} NMAError;
+
+typedef const char * (*HelperSecretFunc)(NMSetting *);
+
+void helper_fill_secret_entry (NMConnection *connection,
+ GtkEntry *entry,
+ GType setting_type,
+ HelperSecretFunc func);
+
+void wireless_security_clear_ciphers (NMConnection *connection);
+
+#endif /* _HELPERS_H_ */
+
diff --git a/panels/network/wireless-security/meson.build b/panels/network/wireless-security/meson.build
new file mode 100644
index 0000000..7f43efc
--- /dev/null
+++ b/panels/network/wireless-security/meson.build
@@ -0,0 +1,73 @@
+name = 'wireless-security'
+
+wireless_security_inc = include_directories('.')
+
+nm_applet_headers = [
+ 'eap-method.h',
+ 'eap-method-fast.h',
+ 'eap-method-leap.h',
+ 'eap-method-peap.h',
+ 'eap-method-simple.h',
+ 'eap-method-tls.h',
+ 'eap-method-ttls.h',
+ 'helpers.h',
+ 'wireless-security.h',
+ 'ws-leap.h',
+ 'ws-dynamic-wep.h',
+ 'ws-file-chooser-button.h',
+ 'ws-sae.h',
+ 'ws-wep-key.h',
+ 'ws-wpa-eap.h',
+ 'ws-wpa-psk.h'
+]
+
+nm_applet_sources = [
+ 'eap-method.c',
+ 'eap-method-fast.c',
+ 'eap-method-leap.c',
+ 'eap-method-peap.c',
+ 'eap-method-simple.c',
+ 'eap-method-tls.c',
+ 'eap-method-ttls.c',
+ 'helpers.c',
+ 'wireless-security.c',
+ 'ws-leap.c',
+ 'ws-dynamic-wep.c',
+ 'ws-file-chooser-button.c',
+ 'ws-sae.c',
+ 'ws-wep-key.c',
+ 'ws-wpa-eap.c',
+ 'ws-wpa-psk.c'
+]
+
+sources = files(nm_applet_sources)
+
+nm_resource_data = [
+ 'eap-method-fast.ui',
+ 'eap-method-leap.ui',
+ 'eap-method-peap.ui',
+ 'eap-method-simple.ui',
+ 'eap-method-tls.ui',
+ 'eap-method-ttls.ui',
+ 'ws-dynamic-wep.ui',
+ 'ws-leap.ui',
+ 'ws-sae.ui',
+ 'ws-wep-key.ui',
+ 'ws-wpa-eap.ui',
+ 'ws-wpa-psk.ui'
+]
+
+sources += gnome.compile_resources(
+ name + '-resources',
+ name + '.gresource.xml',
+ c_name: name.underscorify(),
+ dependencies: files(nm_resource_data),
+ export: true
+)
+
+libwireless_security = static_library(
+ name,
+ sources: sources,
+ include_directories: [top_inc, network_inc],
+ dependencies: deps
+)
diff --git a/panels/network/wireless-security/wireless-security.c b/panels/network/wireless-security/wireless-security.c
new file mode 100644
index 0000000..9f083f6
--- /dev/null
+++ b/panels/network/wireless-security/wireless-security.c
@@ -0,0 +1,101 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#include <glib/gi18n.h>
+
+#include "helpers.h"
+#include "wireless-security.h"
+#include "wireless-security-resources.h"
+
+G_DEFINE_INTERFACE (WirelessSecurity, wireless_security, G_TYPE_OBJECT)
+
+enum {
+ CHANGED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void
+wireless_security_default_init (WirelessSecurityInterface *iface)
+{
+ g_resources_register (wireless_security_get_resource ());
+
+ signals[CHANGED] =
+ g_signal_new ("changed",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_FIRST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+void
+wireless_security_notify_changed (WirelessSecurity *self)
+{
+ g_return_if_fail (WIRELESS_IS_SECURITY (self));
+
+ g_signal_emit (self, signals[CHANGED], 0);
+}
+
+gboolean
+wireless_security_validate (WirelessSecurity *self, GError **error)
+{
+ gboolean result;
+
+ g_return_val_if_fail (WIRELESS_IS_SECURITY (self), FALSE);
+ g_return_val_if_fail (!error || !*error, FALSE);
+
+ result = WIRELESS_SECURITY_GET_IFACE (self)->validate (self, error);
+ if (!result && error && !*error)
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("Unknown error validating 802.1X security"));
+ return result;
+}
+
+void
+wireless_security_add_to_size_group (WirelessSecurity *self, GtkSizeGroup *group)
+{
+ g_return_if_fail (WIRELESS_IS_SECURITY (self));
+ g_return_if_fail (GTK_IS_SIZE_GROUP (group));
+
+ return WIRELESS_SECURITY_GET_IFACE (self)->add_to_size_group (self, group);
+}
+
+void
+wireless_security_fill_connection (WirelessSecurity *self,
+ NMConnection *connection)
+{
+ g_return_if_fail (WIRELESS_IS_SECURITY (self));
+ g_return_if_fail (connection != NULL);
+
+ return WIRELESS_SECURITY_GET_IFACE (self)->fill_connection (self, connection);
+}
+
+gboolean
+wireless_security_adhoc_compatible (WirelessSecurity *self)
+{
+ if (WIRELESS_SECURITY_GET_IFACE (self)->adhoc_compatible)
+ return WIRELESS_SECURITY_GET_IFACE (self)->adhoc_compatible (self);
+ else
+ return TRUE;
+}
diff --git a/panels/network/wireless-security/wireless-security.gresource.xml b/panels/network/wireless-security/wireless-security.gresource.xml
new file mode 100644
index 0000000..c82860c
--- /dev/null
+++ b/panels/network/wireless-security/wireless-security.gresource.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/Settings/network/">
+ <file preprocess="xml-stripblanks">eap-method-leap.ui</file>
+ <file preprocess="xml-stripblanks">eap-method-fast.ui</file>
+ <file preprocess="xml-stripblanks">eap-method-peap.ui</file>
+ <file preprocess="xml-stripblanks">eap-method-simple.ui</file>
+ <file preprocess="xml-stripblanks">eap-method-tls.ui</file>
+ <file preprocess="xml-stripblanks">eap-method-ttls.ui</file>
+ <file preprocess="xml-stripblanks">ws-dynamic-wep.ui</file>
+ <file preprocess="xml-stripblanks">ws-leap.ui</file>
+ <file preprocess="xml-stripblanks">ws-sae.ui</file>
+ <file preprocess="xml-stripblanks">ws-wep-key.ui</file>
+ <file preprocess="xml-stripblanks">ws-wpa-eap.ui</file>
+ <file preprocess="xml-stripblanks">ws-wpa-psk.ui</file>
+ </gresource>
+</gresources>
diff --git a/panels/network/wireless-security/wireless-security.h b/panels/network/wireless-security/wireless-security.h
new file mode 100644
index 0000000..7f1cbed
--- /dev/null
+++ b/panels/network/wireless-security/wireless-security.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_INTERFACE (WirelessSecurity, wireless_security, WIRELESS, SECURITY, GObject)
+
+struct _WirelessSecurityInterface {
+ GTypeInterface g_iface;
+
+ void (*add_to_size_group) (WirelessSecurity *sec, GtkSizeGroup *group);
+ void (*fill_connection) (WirelessSecurity *sec, NMConnection *connection);
+ gboolean (*validate) (WirelessSecurity *sec, GError **error);
+ gboolean (*adhoc_compatible) (WirelessSecurity *sec);
+};
+
+gboolean wireless_security_validate (WirelessSecurity *sec, GError **error);
+
+void wireless_security_add_to_size_group (WirelessSecurity *sec,
+ GtkSizeGroup *group);
+
+void wireless_security_fill_connection (WirelessSecurity *sec,
+ NMConnection *connection);
+
+gboolean wireless_security_adhoc_compatible (WirelessSecurity *sec);
+
+void wireless_security_notify_changed (WirelessSecurity *sec);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/ws-dynamic-wep.c b/panels/network/wireless-security/ws-dynamic-wep.c
new file mode 100644
index 0000000..87a5bb9
--- /dev/null
+++ b/panels/network/wireless-security/ws-dynamic-wep.c
@@ -0,0 +1,262 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#include <glib/gi18n.h>
+
+#include "eap-method.h"
+#include "eap-method-fast.h"
+#include "eap-method-leap.h"
+#include "eap-method-peap.h"
+#include "eap-method-simple.h"
+#include "eap-method-tls.h"
+#include "eap-method-ttls.h"
+#include "wireless-security.h"
+#include "ws-dynamic-wep.h"
+
+struct _WirelessSecurityDynamicWEP {
+ GtkGrid parent;
+
+ GtkComboBox *auth_combo;
+ GtkLabel *auth_label;
+ GtkListStore *auth_model;
+ GtkBox *method_box;
+
+ EAPMethodTLS *em_tls;
+ EAPMethodLEAP *em_leap;
+ EAPMethodSimple *em_pwd;
+ EAPMethodFAST *em_fast;
+ EAPMethodTTLS *em_ttls;
+ EAPMethodPEAP *em_peap;
+};
+
+static void wireless_security_iface_init (WirelessSecurityInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (WirelessSecurityDynamicWEP, ws_dynamic_wep, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (wireless_security_get_type (), wireless_security_iface_init));
+
+#define AUTH_NAME_COLUMN 0
+#define AUTH_ID_COLUMN 1
+
+static EAPMethod *
+get_eap (WirelessSecurityDynamicWEP *self)
+{
+ GtkTreeIter iter;
+ g_autofree gchar *id = NULL;
+
+ if (!gtk_combo_box_get_active_iter (self->auth_combo, &iter))
+ return NULL;
+ gtk_tree_model_get (GTK_TREE_MODEL (self->auth_model), &iter, AUTH_ID_COLUMN, &id, -1);
+
+ if (strcmp (id, "tls") == 0)
+ return EAP_METHOD (self->em_tls);
+ if (strcmp (id, "leap") == 0)
+ return EAP_METHOD (self->em_leap);
+ if (strcmp (id, "pwd") == 0)
+ return EAP_METHOD (self->em_pwd);
+ if (strcmp (id, "fast") == 0)
+ return EAP_METHOD (self->em_fast);
+ if (strcmp (id, "ttls") == 0)
+ return EAP_METHOD (self->em_ttls);
+ if (strcmp (id, "peap") == 0)
+ return EAP_METHOD (self->em_peap);
+
+ return NULL;
+}
+
+static gboolean
+validate (WirelessSecurity *security, GError **error)
+{
+ WirelessSecurityDynamicWEP *self = WS_DYNAMIC_WEP (security);
+ return eap_method_validate (get_eap (self), error);
+}
+
+static void
+add_to_size_group (WirelessSecurity *security, GtkSizeGroup *group)
+{
+ WirelessSecurityDynamicWEP *self = WS_DYNAMIC_WEP (security);
+
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->auth_label));
+ eap_method_add_to_size_group (EAP_METHOD (self->em_tls), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_leap), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_pwd), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_fast), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_ttls), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_peap), group);
+}
+
+static void
+fill_connection (WirelessSecurity *security, NMConnection *connection)
+{
+ WirelessSecurityDynamicWEP *self = WS_DYNAMIC_WEP (security);
+ NMSettingWirelessSecurity *s_wireless_sec;
+ NMSetting8021x *s_8021x;
+ NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
+ EAPMethod *eap;
+
+ /* Get the EAPMethod object */
+ eap = get_eap (self);
+
+ /* Get previous pasword flags, if any. Otherwise default to agent-owned secrets */
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ if (s_8021x)
+ nm_setting_get_secret_flags (NM_SETTING (s_8021x), eap_method_get_password_flags_name (eap), &secret_flags, NULL);
+ else
+ secret_flags = NM_SETTING_SECRET_FLAG_AGENT_OWNED;
+
+ /* Blow away the old wireless security setting by adding a clear one */
+ s_wireless_sec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+ nm_connection_add_setting (connection, (NMSetting *) s_wireless_sec);
+
+ /* Blow away the old 802.1x setting by adding a clear one */
+ s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
+ nm_connection_add_setting (connection, (NMSetting *) s_8021x);
+
+ eap_method_fill_connection (eap, connection, secret_flags);
+
+ g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x", NULL);
+}
+
+static gboolean
+adhoc_compatible (WirelessSecurity *security)
+{
+ return FALSE;
+}
+
+static void
+auth_combo_changed_cb (WirelessSecurityDynamicWEP *self)
+{
+ EAPMethod *eap;
+ GtkWidget *eap_default_field;
+ GtkWidget *child;
+
+ eap = get_eap (self);
+
+ /* Remove the previous method and migrate username/password across */
+ child = gtk_widget_get_first_child (GTK_WIDGET (self->method_box));
+ if (child != NULL) {
+ EAPMethod *old_eap = EAP_METHOD (child);
+ eap_method_set_username (eap, eap_method_get_username (old_eap));
+ eap_method_set_password (eap, eap_method_get_password (old_eap));
+ eap_method_set_show_password (eap, eap_method_get_show_password (old_eap));
+ gtk_box_remove (self->method_box, child);
+ }
+
+ gtk_box_append (self->method_box, g_object_ref (GTK_WIDGET (eap)));
+ eap_default_field = eap_method_get_default_field (eap);
+ if (eap_default_field)
+ gtk_widget_grab_focus (eap_default_field);
+
+ wireless_security_notify_changed (WIRELESS_SECURITY (self));
+}
+
+void
+ws_dynamic_wep_init (WirelessSecurityDynamicWEP *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+void
+ws_dynamic_wep_class_init (WirelessSecurityDynamicWEPClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Settings/network/ws-dynamic-wep.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityDynamicWEP, auth_combo);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityDynamicWEP, auth_label);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityDynamicWEP, auth_model);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityDynamicWEP, method_box);
+}
+
+static void
+wireless_security_iface_init (WirelessSecurityInterface *iface)
+{
+ iface->validate = validate;
+ iface->add_to_size_group = add_to_size_group;
+ iface->fill_connection = fill_connection;
+ iface->adhoc_compatible = adhoc_compatible;
+}
+
+WirelessSecurityDynamicWEP *
+ws_dynamic_wep_new (NMConnection *connection)
+{
+ WirelessSecurityDynamicWEP *self;
+ const gchar *default_method = NULL;
+ GtkTreeIter iter;
+
+ self = g_object_new (ws_dynamic_wep_get_type (), NULL);
+
+ /* Grab the default EAP method out of the security object */
+ if (connection) {
+ NMSetting8021x *s_8021x;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ if (s_8021x && nm_setting_802_1x_get_num_eap_methods (s_8021x))
+ default_method = nm_setting_802_1x_get_eap_method (s_8021x, 0);
+ }
+ if (default_method == NULL)
+ default_method = "tls";
+
+ self->em_tls = eap_method_tls_new (connection);
+ gtk_widget_show (GTK_WIDGET (self->em_tls));
+ g_signal_connect_object (self->em_tls, "changed", G_CALLBACK (wireless_security_notify_changed), self, G_CONNECT_SWAPPED);
+ self->em_leap = eap_method_leap_new (connection);
+ gtk_widget_show (GTK_WIDGET (self->em_leap));
+ g_signal_connect_object (self->em_leap, "changed", G_CALLBACK (wireless_security_notify_changed), self, G_CONNECT_SWAPPED);
+ self->em_pwd = eap_method_simple_new (connection, "pwd", FALSE, FALSE);
+ gtk_widget_show (GTK_WIDGET (self->em_pwd));
+ g_signal_connect_object (self->em_pwd, "changed", G_CALLBACK (wireless_security_notify_changed), self, G_CONNECT_SWAPPED);
+ self->em_fast = eap_method_fast_new (connection);
+ gtk_widget_show (GTK_WIDGET (self->em_fast));
+ g_signal_connect_object (self->em_fast, "changed", G_CALLBACK (wireless_security_notify_changed), self, G_CONNECT_SWAPPED);
+ self->em_ttls = eap_method_ttls_new (connection);
+ gtk_widget_show (GTK_WIDGET (self->em_ttls));
+ g_signal_connect_object (self->em_ttls, "changed", G_CALLBACK (wireless_security_notify_changed), self, G_CONNECT_SWAPPED);
+ self->em_peap = eap_method_peap_new (connection);
+ gtk_widget_show (GTK_WIDGET (self->em_peap));
+ g_signal_connect_object (self->em_peap, "changed", G_CALLBACK (wireless_security_notify_changed), self, G_CONNECT_SWAPPED);
+
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->auth_model), &iter)) {
+ do {
+ g_autofree gchar *id = NULL;
+ gtk_tree_model_get (GTK_TREE_MODEL (self->auth_model), &iter, AUTH_ID_COLUMN, &id, -1);
+ if (strcmp (id, default_method) == 0)
+ gtk_combo_box_set_active_iter (self->auth_combo, &iter);
+ } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->auth_model), &iter));
+ }
+
+ if (connection) {
+ NMSetting8021x *setting;
+
+ setting = nm_connection_get_setting_802_1x (connection);
+ if (setting) {
+ eap_method_set_username (get_eap (self), nm_setting_802_1x_get_identity (setting));
+ eap_method_set_password (get_eap (self), nm_setting_802_1x_get_password (setting));
+ }
+ }
+
+ g_signal_connect_object (G_OBJECT (self->auth_combo), "changed", G_CALLBACK (auth_combo_changed_cb), self, G_CONNECT_SWAPPED);
+ auth_combo_changed_cb (self);
+
+ return self;
+}
+
diff --git a/panels/network/wireless-security/ws-dynamic-wep.h b/panels/network/wireless-security/ws-dynamic-wep.h
new file mode 100644
index 0000000..80c914b
--- /dev/null
+++ b/panels/network/wireless-security/ws-dynamic-wep.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (WirelessSecurityDynamicWEP, ws_dynamic_wep, WS, DYNAMIC_WEP, GtkGrid)
+
+WirelessSecurityDynamicWEP *ws_dynamic_wep_new (NMConnection *connection);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/ws-dynamic-wep.ui b/panels/network/wireless-security/ws-dynamic-wep.ui
new file mode 100644
index 0000000..85d6389
--- /dev/null
+++ b/panels/network/wireless-security/ws-dynamic-wep.ui
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.4"/>
+ <object class="GtkListStore" id="auth_model">
+ <columns>
+ <!-- column-name label -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ <!-- column-name visible -->
+ <column type="gboolean"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">TLS</col>
+ <col id="1">tls</col>
+ <col id="2">True</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">LEAP</col>
+ <col id="1">leap</col>
+ <col id="2">True</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">PWD</col>
+ <col id="1">pwd</col>
+ <col id="2">True</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">FAST</col>
+ <col id="1">fast</col>
+ <col id="2">True</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Tunneled TLS</col>
+ <col id="1">ttls</col>
+ <col id="2">True</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Protected EAP (PEAP)</col>
+ <col id="1">peap</col>
+ <col id="2">True</col>
+ </row>
+ </data>
+ </object>
+ <template class="WirelessSecurityDynamicWEP" parent="GtkGrid">
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="auth_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Au_thentication</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">auth_combo</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="auth_combo">
+ <property name="hexpand">True</property>
+ <property name="model">auth_model</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ <child>
+ <object class="GtkCellRendererText"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="method_box">
+ <property name="spacing">6</property>
+ <property name="orientation">vertical</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="column-span">2</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/wireless-security/ws-file-chooser-button.c b/panels/network/wireless-security/ws-file-chooser-button.c
new file mode 100644
index 0000000..998df42
--- /dev/null
+++ b/panels/network/wireless-security/ws-file-chooser-button.c
@@ -0,0 +1,268 @@
+/* cc-file-chooser-button.c
+ *
+ * Copyright 2021 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "ws-file-chooser-button.h"
+
+#include <glib/gi18n.h>
+
+struct _WsFileChooserButton
+{
+ GtkButton parent_instance;
+
+ GtkFileChooser *filechooser;
+ GFile *file;
+ char *title;
+};
+
+G_DEFINE_FINAL_TYPE (WsFileChooserButton, ws_file_chooser_button, GTK_TYPE_BUTTON)
+
+enum
+{
+ PROP_0,
+ PROP_FILE,
+ PROP_TITLE,
+ N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS] = { NULL, };
+
+static const char *
+get_title (WsFileChooserButton *self)
+{
+ return self->title ? self->title : _("Select a file");
+}
+
+static void
+update_label (WsFileChooserButton *self)
+{
+ g_autofree gchar *label = NULL;
+
+ if (self->file)
+ label = g_file_get_basename (self->file);
+ else
+ label = g_strdup (get_title (self));
+
+ gtk_button_set_label (GTK_BUTTON (self), label);
+}
+
+static void
+on_filechooser_dialog_response_cb (GtkFileChooser *filechooser,
+ gint response,
+ WsFileChooserButton *self)
+{
+ if (response == GTK_RESPONSE_ACCEPT)
+ {
+ g_autoptr(GFile) file = NULL;
+
+ file = gtk_file_chooser_get_file (filechooser);
+ ws_file_chooser_button_set_file (self, file);
+ }
+
+ gtk_widget_hide (GTK_WIDGET (filechooser));
+}
+static void
+ensure_filechooser (WsFileChooserButton *self)
+{
+ GtkNative *native;
+ GtkWidget *dialog;
+
+ if (self->filechooser)
+ return;
+
+ native = gtk_widget_get_native (GTK_WIDGET (self));
+
+ dialog = gtk_file_chooser_dialog_new (get_title (self),
+ GTK_WINDOW (native),
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ _("Cancel"),
+ GTK_RESPONSE_CANCEL,
+ _("Open"),
+ GTK_RESPONSE_ACCEPT,
+ NULL);
+ gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
+ gtk_window_set_hide_on_close (GTK_WINDOW (dialog), TRUE);
+ gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+
+ if (self->file)
+ gtk_file_chooser_set_file (GTK_FILE_CHOOSER (dialog), self->file, NULL);
+
+ g_signal_connect (dialog, "response", G_CALLBACK (on_filechooser_dialog_response_cb), self);
+
+ self->filechooser = GTK_FILE_CHOOSER (dialog);
+}
+
+
+static void
+ws_file_chooser_button_clicked (GtkButton *button)
+{
+ WsFileChooserButton *self = WS_FILE_CHOOSER_BUTTON (button);
+ GtkNative *native = gtk_widget_get_native (GTK_WIDGET (self));
+
+ ensure_filechooser (self);
+
+ gtk_window_set_transient_for (GTK_WINDOW (self->filechooser), GTK_WINDOW (native));
+ gtk_window_present (GTK_WINDOW (self->filechooser));
+}
+
+static void
+ws_file_chooser_button_finalize (GObject *object)
+{
+ WsFileChooserButton *self = (WsFileChooserButton *)object;
+
+ g_clear_pointer (&self->title, g_free);
+ g_clear_object (&self->file);
+
+ G_OBJECT_CLASS (ws_file_chooser_button_parent_class)->finalize (object);
+}
+
+static void
+ws_file_chooser_button_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ WsFileChooserButton *self = WS_FILE_CHOOSER_BUTTON (object);
+
+ switch (prop_id)
+ {
+ case PROP_FILE:
+ g_value_set_object (value, self->file);
+ break;
+
+ case PROP_TITLE:
+ g_value_set_string (value, self->title);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ws_file_chooser_button_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ WsFileChooserButton *self = WS_FILE_CHOOSER_BUTTON (object);
+
+ switch (prop_id)
+ {
+ case PROP_FILE:
+ ws_file_chooser_button_set_file (self, g_value_get_object (value));
+ break;
+
+ case PROP_TITLE:
+ ws_file_chooser_button_set_title (self, g_value_get_string (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ws_file_chooser_button_class_init (WsFileChooserButtonClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkButtonClass *button_class = GTK_BUTTON_CLASS (klass);
+
+ button_class->clicked = ws_file_chooser_button_clicked;
+
+ object_class->finalize = ws_file_chooser_button_finalize;
+ object_class->get_property = ws_file_chooser_button_get_property;
+ object_class->set_property = ws_file_chooser_button_set_property;
+
+ properties[PROP_FILE] = g_param_spec_object ("file", "", "",
+ G_TYPE_FILE,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+ properties[PROP_TITLE] = g_param_spec_string ("title", "", "", NULL,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+ws_file_chooser_button_init (WsFileChooserButton *self)
+{
+ update_label (self);
+}
+
+GtkWidget *
+ws_file_chooser_button_new (void)
+{
+ return g_object_new (WS_TYPE_FILE_CHOOSER_BUTTON, NULL);
+}
+
+void
+ws_file_chooser_button_set_file (WsFileChooserButton *self,
+ GFile *file)
+{
+ g_return_if_fail (WS_IS_FILE_CHOOSER_BUTTON (self));
+
+ if (g_set_object (&self->file, file))
+ {
+ gtk_file_chooser_set_file (self->filechooser, file, NULL);
+ update_label (self);
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FILE]);
+ }
+}
+
+GFile *
+ws_file_chooser_button_get_file (WsFileChooserButton *self)
+{
+ g_return_val_if_fail (WS_IS_FILE_CHOOSER_BUTTON (self), NULL);
+
+ return self->file ? g_object_ref (self->file) : NULL;
+}
+
+void
+ws_file_chooser_button_set_title (WsFileChooserButton *self,
+ const char *title)
+{
+ g_autofree char *old_title = NULL;
+
+ g_return_if_fail (WS_IS_FILE_CHOOSER_BUTTON (self));
+
+ old_title = g_steal_pointer (&self->title);
+ self->title = g_strdup (title);
+
+ update_label (self);
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TITLE]);
+}
+
+const char *
+ws_file_chooser_button_get_title (WsFileChooserButton *self)
+{
+ g_return_val_if_fail (WS_IS_FILE_CHOOSER_BUTTON (self), NULL);
+
+ return self->title;
+}
+
+GtkFileChooser *
+ws_file_chooser_button_get_filechooser (WsFileChooserButton *self)
+{
+ g_return_val_if_fail (WS_IS_FILE_CHOOSER_BUTTON (self), NULL);
+
+ ensure_filechooser (self);
+
+ return self->filechooser;
+}
diff --git a/panels/network/wireless-security/ws-file-chooser-button.h b/panels/network/wireless-security/ws-file-chooser-button.h
new file mode 100644
index 0000000..db02020
--- /dev/null
+++ b/panels/network/wireless-security/ws-file-chooser-button.h
@@ -0,0 +1,44 @@
+/* ws-file-chooser-button.h
+ *
+ * Copyright 2021 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define WS_TYPE_FILE_CHOOSER_BUTTON (ws_file_chooser_button_get_type())
+G_DECLARE_FINAL_TYPE (WsFileChooserButton, ws_file_chooser_button, WS, FILE_CHOOSER_BUTTON, GtkButton)
+
+GtkWidget *ws_file_chooser_button_new (void);
+
+void ws_file_chooser_button_set_file (WsFileChooserButton *self,
+ GFile *file);
+
+GFile *ws_file_chooser_button_get_file (WsFileChooserButton *self);
+
+void ws_file_chooser_button_set_title (WsFileChooserButton *self,
+ const char *title);
+
+const char *ws_file_chooser_button_get_title (WsFileChooserButton *self);
+
+GtkFileChooser *ws_file_chooser_button_get_filechooser (WsFileChooserButton *self);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/ws-leap.c b/panels/network/wireless-security/ws-leap.c
new file mode 100644
index 0000000..a234015
--- /dev/null
+++ b/panels/network/wireless-security/ws-leap.c
@@ -0,0 +1,211 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#include <glib/gi18n.h>
+
+#include "helpers.h"
+#include "nma-ui-utils.h"
+#include "ui-helpers.h"
+#include "wireless-security.h"
+#include "ws-leap.h"
+
+struct _WirelessSecurityLEAP {
+ GtkGrid parent;
+
+ GtkEntry *password_entry;
+ GtkLabel *password_label;
+ GtkCheckButton *show_password_check;
+ GtkEntry *username_entry;
+ GtkLabel *username_label;
+};
+
+static void wireless_security_iface_init (WirelessSecurityInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (WirelessSecurityLEAP, ws_leap, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (wireless_security_get_type (), wireless_security_iface_init));
+
+static void
+show_toggled_cb (WirelessSecurityLEAP *self)
+{
+ gboolean visible;
+
+ visible = gtk_check_button_get_active (GTK_CHECK_BUTTON (self->show_password_check));
+ gtk_entry_set_visibility (self->password_entry, visible);
+}
+
+static gboolean
+validate (WirelessSecurity *security, GError **error)
+{
+ WirelessSecurityLEAP *self = WS_LEAP (security);
+ NMSettingSecretFlags secret_flags;
+ const char *text;
+ gboolean ret = TRUE;
+
+ text = gtk_editable_get_text (GTK_EDITABLE (self->username_entry));
+ if (!text || !strlen (text)) {
+ widget_set_error (GTK_WIDGET (self->username_entry));
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("missing leap-username"));
+ ret = FALSE;
+ } else
+ widget_unset_error (GTK_WIDGET (self->username_entry));
+
+ secret_flags = nma_utils_menu_to_secret_flags (GTK_WIDGET (self->password_entry));
+ if (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED) {
+ widget_unset_error (GTK_WIDGET (self->password_entry));
+ return TRUE;
+ }
+
+ text = gtk_editable_get_text (GTK_EDITABLE (self->password_entry));
+ if (!text || !strlen (text)) {
+ widget_set_error (GTK_WIDGET (self->password_entry));
+ if (ret) {
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("missing leap-password"));
+ ret = FALSE;
+ }
+ } else
+ widget_unset_error (GTK_WIDGET (self->password_entry));
+
+ return ret;
+}
+
+static void
+add_to_size_group (WirelessSecurity *security, GtkSizeGroup *group)
+{
+ WirelessSecurityLEAP *self = WS_LEAP (security);
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->username_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->password_label));
+}
+
+static void
+fill_connection (WirelessSecurity *security, NMConnection *connection)
+{
+ WirelessSecurityLEAP *self = WS_LEAP (security);
+ NMSettingWirelessSecurity *s_wireless_sec;
+ NMSettingSecretFlags secret_flags;
+ const char *leap_password = NULL, *leap_username = NULL;
+
+ /* Blow away the old security setting by adding a clear one */
+ s_wireless_sec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+ nm_connection_add_setting (connection, (NMSetting *) s_wireless_sec);
+
+ leap_username = gtk_editable_get_text (GTK_EDITABLE (self->username_entry));
+ leap_password = gtk_editable_get_text (GTK_EDITABLE (self->password_entry));
+
+ g_object_set (s_wireless_sec,
+ NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x",
+ NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "leap",
+ NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, leap_username,
+ NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD, leap_password,
+ NULL);
+
+ /* Save LEAP_PASSWORD_FLAGS to the connection */
+ secret_flags = nma_utils_menu_to_secret_flags (GTK_WIDGET (self->password_entry));
+ nm_setting_set_secret_flags (NM_SETTING (s_wireless_sec), NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD,
+ secret_flags, NULL);
+
+ /* Update secret flags and popup when editing the connection */
+ nma_utils_update_password_storage (GTK_WIDGET (self->password_entry), secret_flags,
+ NM_SETTING (s_wireless_sec), NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD);
+}
+
+static gboolean
+adhoc_compatible (WirelessSecurity *security)
+{
+ return FALSE;
+}
+
+static void
+changed_cb (WirelessSecurityLEAP *self)
+{
+ wireless_security_notify_changed ((WirelessSecurity *) self);
+}
+
+void
+ws_leap_init (WirelessSecurityLEAP *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+void
+ws_leap_class_init (WirelessSecurityLEAPClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Settings/network/ws-leap.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityLEAP, password_entry);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityLEAP, password_label);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityLEAP, show_password_check);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityLEAP, username_entry);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityLEAP, username_label);
+}
+
+static void
+wireless_security_iface_init (WirelessSecurityInterface *iface)
+{
+ iface->validate = validate;
+ iface->add_to_size_group = add_to_size_group;
+ iface->fill_connection = fill_connection;
+ iface->adhoc_compatible = adhoc_compatible;
+}
+
+WirelessSecurityLEAP *
+ws_leap_new (NMConnection *connection)
+{
+ WirelessSecurityLEAP *self;
+ NMSettingWirelessSecurity *wsec = NULL;
+
+ self = g_object_new (ws_leap_get_type (), NULL);
+
+ if (connection) {
+ wsec = nm_connection_get_setting_wireless_security (connection);
+ if (wsec) {
+ const char *auth_alg;
+
+ /* Ignore if wireless security doesn't specify LEAP */
+ auth_alg = nm_setting_wireless_security_get_auth_alg (wsec);
+ if (!auth_alg || strcmp (auth_alg, "leap"))
+ wsec = NULL;
+ }
+ }
+
+ g_signal_connect_swapped (self->password_entry, "changed", G_CALLBACK (changed_cb), self);
+
+ /* Create password-storage popup menu for password entry under entry's secondary icon */
+ nma_utils_setup_password_storage (GTK_WIDGET (self->password_entry), 0, (NMSetting *) wsec, NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD,
+ FALSE, FALSE);
+
+ if (wsec)
+ helper_fill_secret_entry (connection,
+ self->password_entry,
+ NM_TYPE_SETTING_WIRELESS_SECURITY,
+ (HelperSecretFunc) nm_setting_wireless_security_get_leap_password);
+
+ g_signal_connect_swapped (self->username_entry, "changed", G_CALLBACK (changed_cb), self);
+ if (wsec)
+ gtk_editable_set_text (GTK_EDITABLE (self->username_entry), nm_setting_wireless_security_get_leap_username (wsec));
+
+ g_signal_connect_swapped (self->show_password_check, "toggled", G_CALLBACK (show_toggled_cb), self);
+
+ return self;
+}
+
diff --git a/panels/network/wireless-security/ws-leap.h b/panels/network/wireless-security/ws-leap.h
new file mode 100644
index 0000000..ebe90bb
--- /dev/null
+++ b/panels/network/wireless-security/ws-leap.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (WirelessSecurityLEAP, ws_leap, WS, LEAP, GtkGrid)
+
+WirelessSecurityLEAP *ws_leap_new (NMConnection *connection);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/ws-leap.ui b/panels/network/wireless-security/ws-leap.ui
new file mode 100644
index 0000000..41e21d6
--- /dev/null
+++ b/panels/network/wireless-security/ws-leap.ui
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.4"/>
+ <template class="WirelessSecurityLEAP" parent="GtkGrid">
+ <property name="valign">start</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="username_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Username</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">username_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="password_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Password</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">password_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="password_entry">
+ <property name="hexpand">True</property>
+ <property name="visibility">False</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="show_password_check">
+ <property name="label" translatable="yes">Sho_w password</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="username_entry">
+ <property name="hexpand">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/wireless-security/ws-sae.c b/panels/network/wireless-security/ws-sae.c
new file mode 100644
index 0000000..c9e4e50
--- /dev/null
+++ b/panels/network/wireless-security/ws-sae.c
@@ -0,0 +1,225 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Jonathan Kang <songchuan.kang@suse.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (c) 2020 SUSE LINUX GmbH, Nuernberg, Germany.
+ */
+
+#include <ctype.h>
+#include <glib/gi18n.h>
+
+#include "helpers.h"
+#include "nma-ui-utils.h"
+#include "ui-helpers.h"
+#include "ws-sae.h"
+#include "wireless-security.h"
+
+#define WPA_PMK_LEN 32
+
+struct _WirelessSecuritySAE
+{
+ GtkGrid parent;
+
+ GtkEntry *password_entry;
+ GtkLabel *password_label;
+ GtkCheckButton *show_password_check;
+ GtkComboBox *type_combo;
+ GtkLabel *type_label;
+};
+
+static void wireless_security_iface_init (WirelessSecurityInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (WirelessSecuritySAE, ws_sae, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (wireless_security_get_type (), wireless_security_iface_init));
+
+static void
+show_toggled_cb (WirelessSecuritySAE *self)
+{
+ gboolean visible;
+
+ visible = gtk_check_button_get_active (GTK_CHECK_BUTTON (self->show_password_check));
+ gtk_entry_set_visibility (self->password_entry, visible);
+}
+
+static gboolean
+validate (WirelessSecurity *security, GError **error)
+{
+ WirelessSecuritySAE *self = WS_SAE (security);
+ NMSettingSecretFlags secret_flags;
+ const char *key;
+
+ secret_flags = nma_utils_menu_to_secret_flags (GTK_WIDGET (self->password_entry));
+ if (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED)
+ {
+ widget_unset_error (GTK_WIDGET (self->password_entry));
+ return TRUE;
+ }
+
+ key = gtk_editable_get_text (GTK_EDITABLE (self->password_entry));
+
+ if (key == NULL || key[0] == '\0')
+ {
+ widget_set_error (GTK_WIDGET (self->password_entry));
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("Wi-Fi password is missing."));
+ return FALSE;
+ }
+ widget_unset_error (GTK_WIDGET (self->password_entry));
+
+ return TRUE;
+}
+
+static void
+add_to_size_group (WirelessSecurity *security, GtkSizeGroup *group)
+{
+ WirelessSecuritySAE *self = WS_SAE (security);
+
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->type_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->password_label));
+}
+
+static void
+fill_connection (WirelessSecurity *security, NMConnection *connection)
+{
+ WirelessSecuritySAE *self = WS_SAE (security);
+ const char *key;
+ NMSettingWireless *s_wireless;
+ NMSettingWirelessSecurity *s_wireless_sec;
+ NMSettingSecretFlags secret_flags;
+ const char *mode;
+ gboolean is_adhoc = FALSE;
+
+ s_wireless = nm_connection_get_setting_wireless (connection);
+ g_assert (s_wireless);
+
+ mode = nm_setting_wireless_get_mode (s_wireless);
+ if (mode && !g_strcmp0 (mode, "adhoc"))
+ is_adhoc = TRUE;
+
+ /* Blow away the old security setting by adding a clear one */
+ s_wireless_sec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+ nm_connection_add_setting (connection, (NMSetting *) s_wireless_sec);
+
+ key = gtk_editable_get_text (GTK_EDITABLE (self->password_entry));
+ g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_PSK, key, NULL);
+
+ /* Save PSK_FLAGS to the connection */
+ secret_flags = nma_utils_menu_to_secret_flags (GTK_WIDGET (self->password_entry));
+ nm_setting_set_secret_flags (NM_SETTING (s_wireless_sec), NM_SETTING_WIRELESS_SECURITY_PSK,
+ secret_flags, NULL);
+
+ /* Update secret flags and popup when editing the connection */
+ nma_utils_update_password_storage (GTK_WIDGET (self->password_entry), secret_flags,
+ NM_SETTING (s_wireless_sec), NM_SETTING_WIRELESS_SECURITY_PSK);
+
+ wireless_security_clear_ciphers (connection);
+ if (is_adhoc)
+ {
+ /* Ad-Hoc settings as specified by the supplicant */
+ g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "sae", NULL);
+ nm_setting_wireless_security_add_proto (s_wireless_sec, "rsn");
+ nm_setting_wireless_security_add_pairwise (s_wireless_sec, "ccmp");
+ nm_setting_wireless_security_add_group (s_wireless_sec, "ccmp");
+ }
+ else
+ {
+ g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "sae", NULL);
+
+ /* Just leave ciphers and protocol empty, the supplicant will
+ * figure that out magically based on the AP IEs and card capabilities.
+ */
+ }
+}
+
+static gboolean
+adhoc_compatible (WirelessSecurity *security)
+{
+ return FALSE;
+}
+
+static void
+changed_cb (WirelessSecuritySAE *self)
+{
+ wireless_security_notify_changed ((WirelessSecurity *) self);
+}
+
+void
+ws_sae_init (WirelessSecuritySAE *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+void
+ws_sae_class_init (WirelessSecuritySAEClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Settings/network/ws-sae.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecuritySAE, password_entry);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecuritySAE, password_label);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecuritySAE, show_password_check);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecuritySAE, type_combo);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecuritySAE, type_label);
+}
+
+static void
+wireless_security_iface_init (WirelessSecurityInterface *iface)
+{
+ iface->validate = validate;
+ iface->add_to_size_group = add_to_size_group;
+ iface->fill_connection = fill_connection;
+ iface->adhoc_compatible = adhoc_compatible;
+}
+
+WirelessSecuritySAE *
+ws_sae_new (NMConnection *connection)
+{
+ WirelessSecuritySAE *self;
+ NMSetting *setting = NULL;
+
+ self = g_object_new (ws_sae_get_type (), NULL);
+
+ g_signal_connect_swapped (self->password_entry, "changed", G_CALLBACK (changed_cb), self);
+ gtk_editable_set_width_chars (GTK_EDITABLE (self->password_entry), 28);
+
+ /* Create password-storage popup menu for password entry under entry's secondary icon */
+ if (connection)
+ setting = (NMSetting *) nm_connection_get_setting_wireless_security (connection);
+ nma_utils_setup_password_storage (GTK_WIDGET (self->password_entry),
+ 0, setting, NM_SETTING_WIRELESS_SECURITY_PSK,
+ FALSE, FALSE);
+
+ /* Fill secrets, if any */
+ if (connection)
+ {
+ helper_fill_secret_entry (connection,
+ self->password_entry,
+ NM_TYPE_SETTING_WIRELESS_SECURITY,
+ (HelperSecretFunc) nm_setting_wireless_security_get_psk);
+ }
+
+ g_signal_connect_swapped (self->show_password_check, "toggled",
+ G_CALLBACK (show_toggled_cb), self);
+
+ /* Hide WPA/RSN for now since this can be autodetected by NM and the
+ * supplicant when connecting to the AP.
+ */
+ gtk_widget_hide (GTK_WIDGET (self->type_combo));
+ gtk_widget_hide (GTK_WIDGET (self->type_label));
+
+ return self;
+}
diff --git a/panels/network/wireless-security/ws-sae.h b/panels/network/wireless-security/ws-sae.h
new file mode 100644
index 0000000..770f658
--- /dev/null
+++ b/panels/network/wireless-security/ws-sae.h
@@ -0,0 +1,33 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Jonathan Kang <songchuan.kang@suse.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (c) 2020 SUSE LINUX GmbH, Nuernberg, Germany.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (WirelessSecuritySAE, ws_sae, WS, SAE, GtkGrid)
+
+WirelessSecuritySAE* ws_sae_new (NMConnection *connection);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/ws-sae.ui b/panels/network/wireless-security/ws-sae.ui
new file mode 100644
index 0000000..028cd9f
--- /dev/null
+++ b/panels/network/wireless-security/ws-sae.ui
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.0 -->
+<interface domain="nm-applet">
+ <requires lib="gtk+" version="3.10"/>
+ <template class="WirelessSecuritySAE" parent="GtkGrid">
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="password_label">
+ <property name="label" translatable="yes">_Password</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">password_entry</property>
+ <property name="xalign">1</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="password_entry">
+ <property name="hexpand">True</property>
+ <property name="max_length">64</property>
+ <property name="visibility">False</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="type_label">
+ <property name="label" translatable="yes">_Type</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">type_combo</property>
+ <property name="xalign">1</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="show_password_check">
+ <property name="label" translatable="yes">Sho_w password</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="type_combo">
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/wireless-security/ws-wep-key.c b/panels/network/wireless-security/ws-wep-key.c
new file mode 100644
index 0000000..8b354d5
--- /dev/null
+++ b/panels/network/wireless-security/ws-wep-key.c
@@ -0,0 +1,369 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#include <glib/gi18n.h>
+
+#include "helpers.h"
+#include "nma-ui-utils.h"
+#include "ui-helpers.h"
+#include "ws-wep-key.h"
+#include "wireless-security.h"
+
+struct _WirelessSecurityWEPKey {
+ GtkGrid parent;
+
+ GtkComboBox *auth_method_combo;
+ GtkLabel *auth_method_label;
+ GtkEntry *key_entry;
+ GtkComboBox *key_index_combo;
+ GtkLabel *key_index_label;
+ GtkLabel *key_label;
+ GtkCheckButton *show_key_check;
+
+ NMWepKeyType type;
+ char keys[4][65];
+ guint8 cur_index;
+};
+
+static void wireless_security_iface_init (WirelessSecurityInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (WirelessSecurityWEPKey, ws_wep_key, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (wireless_security_get_type (), wireless_security_iface_init));
+
+static void
+show_toggled_cb (WirelessSecurityWEPKey *self)
+{
+ gboolean visible;
+
+ visible = gtk_check_button_get_active (GTK_CHECK_BUTTON (self->show_key_check));
+ gtk_entry_set_visibility (self->key_entry, visible);
+}
+
+static void
+key_index_combo_changed_cb (WirelessSecurityWEPKey *self)
+{
+ const char *key;
+ int key_index;
+
+ /* Save WEP key for old key index */
+ key = gtk_editable_get_text (GTK_EDITABLE (self->key_entry));
+ if (key)
+ g_strlcpy (self->keys[self->cur_index], key, sizeof (self->keys[self->cur_index]));
+ else
+ memset (self->keys[self->cur_index], 0, sizeof (self->keys[self->cur_index]));
+
+ key_index = gtk_combo_box_get_active (self->key_index_combo);
+ g_return_if_fail (key_index <= 3);
+ g_return_if_fail (key_index >= 0);
+
+ /* Populate entry with key from new index */
+ gtk_editable_set_text (GTK_EDITABLE (self->key_entry), self->keys[key_index]);
+ self->cur_index = key_index;
+
+ wireless_security_notify_changed ((WirelessSecurity *) self);
+}
+
+static void
+ws_wep_key_dispose (GObject *object)
+{
+ WirelessSecurityWEPKey *self = WS_WEP_KEY (object);
+ int i;
+
+ for (i = 0; i < 4; i++)
+ memset (self->keys[i], 0, sizeof (self->keys[i]));
+
+ G_OBJECT_CLASS (ws_wep_key_parent_class)->dispose (object);
+}
+
+static gboolean
+validate (WirelessSecurity *security, GError **error)
+{
+ WirelessSecurityWEPKey *self = WS_WEP_KEY (security);
+ NMSettingSecretFlags secret_flags;
+ const char *key;
+ int i;
+
+ secret_flags = nma_utils_menu_to_secret_flags (GTK_WIDGET (self->key_entry));
+ if (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED) {
+ widget_unset_error (GTK_WIDGET (self->key_entry));
+ return TRUE;
+ }
+
+ key = gtk_editable_get_text (GTK_EDITABLE (self->key_entry));
+ if (!key) {
+ widget_set_error (GTK_WIDGET (self->key_entry));
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("missing wep-key"));
+ return FALSE;
+ }
+
+ if (self->type == NM_WEP_KEY_TYPE_KEY) {
+ if ((strlen (key) == 10) || (strlen (key) == 26)) {
+ for (i = 0; i < strlen (key); i++) {
+ if (!g_ascii_isxdigit (key[i])) {
+ widget_set_error (GTK_WIDGET (self->key_entry));
+ g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid wep-key: key with a length of %zu must contain only hex-digits"), strlen (key));
+ return FALSE;
+ }
+ }
+ } else if ((strlen (key) == 5) || (strlen (key) == 13)) {
+ for (i = 0; i < strlen (key); i++) {
+ if (!g_ascii_isprint (key[i])) {
+ widget_set_error (GTK_WIDGET (self->key_entry));
+ g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid wep-key: key with a length of %zu must contain only ascii characters"), strlen (key));
+ return FALSE;
+ }
+ }
+ } else {
+ widget_set_error (GTK_WIDGET (self->key_entry));
+ g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid wep-key: wrong key length %zu. A key must be either of length 5/13 (ascii) or 10/26 (hex)"), strlen (key));
+ return FALSE;
+ }
+ } else if (self->type == NM_WEP_KEY_TYPE_PASSPHRASE) {
+ if (!*key || (strlen (key) > 64)) {
+ widget_set_error (GTK_WIDGET (self->key_entry));
+ if (!*key)
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid wep-key: passphrase must be non-empty"));
+ else
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid wep-key: passphrase must be shorter than 64 characters"));
+ return FALSE;
+ }
+ }
+ widget_unset_error (GTK_WIDGET (self->key_entry));
+
+ return TRUE;
+}
+
+static void
+add_to_size_group (WirelessSecurity *security, GtkSizeGroup *group)
+{
+ WirelessSecurityWEPKey *self = WS_WEP_KEY (security);
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->auth_method_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->key_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->key_index_label));
+}
+
+static void
+fill_connection (WirelessSecurity *security, NMConnection *connection)
+{
+ WirelessSecurityWEPKey *self = WS_WEP_KEY (security);
+ NMSettingWirelessSecurity *s_wsec;
+ NMSettingSecretFlags secret_flags;
+ gint auth_alg;
+ const char *key;
+ int i;
+
+ auth_alg = gtk_combo_box_get_active (self->auth_method_combo);
+
+ key = gtk_editable_get_text (GTK_EDITABLE (self->key_entry));
+ g_strlcpy (self->keys[self->cur_index], key, sizeof (self->keys[self->cur_index]));
+
+ /* Blow away the old security setting by adding a clear one */
+ s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+ nm_connection_add_setting (connection, (NMSetting *) s_wsec);
+
+ g_object_set (s_wsec,
+ NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none",
+ NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX, self->cur_index,
+ NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, (auth_alg == 1) ? "shared" : "open",
+ NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, self->type,
+ NULL);
+
+ for (i = 0; i < 4; i++) {
+ if (strlen (self->keys[i]))
+ nm_setting_wireless_security_set_wep_key (s_wsec, i, self->keys[i]);
+ }
+
+ /* Save WEP_KEY_FLAGS to the connection */
+ secret_flags = nma_utils_menu_to_secret_flags (GTK_WIDGET (self->key_entry));
+ g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, secret_flags, NULL);
+
+ /* Update secret flags and popup when editing the connection */
+ nma_utils_update_password_storage (GTK_WIDGET (self->key_entry), secret_flags,
+ NM_SETTING (s_wsec), NM_SETTING_WIRELESS_SECURITY_WEP_KEY0);
+}
+
+static void
+wep_entry_filter_cb (WirelessSecurityWEPKey *self,
+ gchar *text,
+ gint length,
+ gint *position)
+{
+ if (self->type == NM_WEP_KEY_TYPE_KEY) {
+ int i, count = 0;
+ g_autofree gchar *result = g_new (gchar, length+1);
+
+ for (i = 0; i < length; i++) {
+ if (g_ascii_isprint (text[i]))
+ result[count++] = text[i];
+ }
+ result[count] = 0;
+
+ if (count > 0) {
+ g_signal_handlers_block_by_func (self->key_entry, G_CALLBACK (wep_entry_filter_cb), self);
+ gtk_editable_insert_text (GTK_EDITABLE (self->key_entry), result, count, position);
+ g_signal_handlers_unblock_by_func (self->key_entry, G_CALLBACK (wep_entry_filter_cb), self);
+ }
+ g_signal_stop_emission_by_name (self->key_entry, "insert-text");
+ }
+}
+
+static void
+update_secrets (WirelessSecurityWEPKey *self, NMConnection *connection)
+{
+ NMSettingWirelessSecurity *s_wsec;
+ const char *tmp;
+ int i;
+
+ s_wsec = nm_connection_get_setting_wireless_security (connection);
+ for (i = 0; s_wsec && i < 4; i++) {
+ tmp = nm_setting_wireless_security_get_wep_key (s_wsec, i);
+ if (tmp)
+ g_strlcpy (self->keys[i], tmp, sizeof (self->keys[i]));
+ }
+
+ if (strlen (self->keys[self->cur_index]))
+ gtk_editable_set_text (GTK_EDITABLE (self->key_entry), self->keys[self->cur_index]);
+}
+
+static void
+changed_cb (WirelessSecurityWEPKey *self)
+{
+ wireless_security_notify_changed ((WirelessSecurity *) self);
+}
+
+void
+ws_wep_key_init (WirelessSecurityWEPKey *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+void
+ws_wep_key_class_init (WirelessSecurityWEPKeyClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = ws_wep_key_dispose;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Settings/network/ws-wep-key.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWEPKey, auth_method_combo);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWEPKey, auth_method_label);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWEPKey, key_entry);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWEPKey, key_index_combo);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWEPKey, key_index_label);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWEPKey, key_label);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWEPKey, show_key_check);
+}
+
+static void
+wireless_security_iface_init (WirelessSecurityInterface *iface)
+{
+ iface->validate = validate;
+ iface->add_to_size_group = add_to_size_group;
+ iface->fill_connection = fill_connection;
+}
+
+WirelessSecurityWEPKey *
+ws_wep_key_new (NMConnection *connection,
+ NMWepKeyType type)
+{
+ WirelessSecurityWEPKey *self;
+ NMSettingWirelessSecurity *s_wsec = NULL;
+ NMSetting *setting = NULL;
+ guint8 default_key_idx = 0;
+ gboolean is_adhoc = FALSE;
+ gboolean is_shared_key = FALSE;
+
+ self = g_object_new (ws_wep_key_get_type (), NULL);
+
+ self->type = type;
+
+ gtk_editable_set_width_chars (GTK_EDITABLE (self->key_entry), 28);
+
+ /* Create password-storage popup menu for password entry under entry's secondary icon */
+ if (connection)
+ setting = (NMSetting *) nm_connection_get_setting_wireless_security (connection);
+ nma_utils_setup_password_storage (GTK_WIDGET (self->key_entry), 0, setting, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0,
+ FALSE, FALSE);
+
+ if (connection) {
+ NMSettingWireless *s_wireless;
+ const char *mode, *auth_alg;
+
+ s_wireless = nm_connection_get_setting_wireless (connection);
+ mode = s_wireless ? nm_setting_wireless_get_mode (s_wireless) : NULL;
+ if (mode && !strcmp (mode, "adhoc"))
+ is_adhoc = TRUE;
+
+ s_wsec = nm_connection_get_setting_wireless_security (connection);
+ if (s_wsec) {
+ auth_alg = nm_setting_wireless_security_get_auth_alg (s_wsec);
+ if (auth_alg && !strcmp (auth_alg, "shared"))
+ is_shared_key = TRUE;
+ }
+ }
+
+ g_signal_connect_swapped (self->key_entry, "changed", G_CALLBACK (changed_cb), self);
+ g_signal_connect_swapped (self->key_entry, "insert-text", G_CALLBACK (wep_entry_filter_cb), self);
+ if (self->type == NM_WEP_KEY_TYPE_KEY)
+ gtk_entry_set_max_length (self->key_entry, 26);
+ else if (self->type == NM_WEP_KEY_TYPE_PASSPHRASE)
+ gtk_entry_set_max_length (self->key_entry, 64);
+
+ if (connection && s_wsec)
+ default_key_idx = nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec);
+
+ gtk_combo_box_set_active (self->key_index_combo, default_key_idx);
+ self->cur_index = default_key_idx;
+ g_signal_connect_swapped (self->key_index_combo, "changed", G_CALLBACK (key_index_combo_changed_cb), self);
+
+ /* Key index is useless with adhoc networks */
+ if (is_adhoc) {
+ gtk_widget_hide (GTK_WIDGET (self->key_index_combo));
+ gtk_widget_hide (GTK_WIDGET (self->key_index_label));
+ }
+
+ /* Fill the key entry with the key for that index */
+ if (connection)
+ update_secrets (self, connection);
+
+ g_signal_connect_swapped (self->show_key_check, "toggled", G_CALLBACK (show_toggled_cb), self);
+
+ gtk_combo_box_set_active (self->auth_method_combo, is_shared_key ? 1 : 0);
+
+ g_signal_connect_swapped (self->auth_method_combo, "changed", G_CALLBACK (changed_cb), self);
+
+ /* Don't show auth method for adhoc (which always uses open-system) or
+ * when in "simple" mode.
+ */
+ if (is_adhoc) {
+ /* Ad-Hoc connections can't use Shared Key auth */
+ if (is_adhoc)
+ gtk_combo_box_set_active (self->auth_method_combo, 0);
+ gtk_widget_hide (GTK_WIDGET (self->auth_method_combo));
+ gtk_widget_hide (GTK_WIDGET (self->auth_method_label));
+ }
+
+ return self;
+}
+
diff --git a/panels/network/wireless-security/ws-wep-key.h b/panels/network/wireless-security/ws-wep-key.h
new file mode 100644
index 0000000..dc85e8b
--- /dev/null
+++ b/panels/network/wireless-security/ws-wep-key.h
@@ -0,0 +1,35 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (WirelessSecurityWEPKey, ws_wep_key, WS, WEP_KEY, GtkGrid)
+
+WirelessSecurityWEPKey *ws_wep_key_new (NMConnection *connection,
+ NMWepKeyType type);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/ws-wep-key.ui b/panels/network/wireless-security/ws-wep-key.ui
new file mode 100644
index 0000000..49f525e
--- /dev/null
+++ b/panels/network/wireless-security/ws-wep-key.ui
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.4"/>
+ <object class="GtkListStore" id="key_index_model">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">1 (Default)</col>
+ </row>
+ <row>
+ <col id="0">2</col>
+ </row>
+ <row>
+ <col id="0">3</col>
+ </row>
+ <row>
+ <col id="0">4</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="auth_method_model">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">Open System</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Shared Key</col>
+ </row>
+ </data>
+ </object>
+ <template class="WirelessSecurityWEPKey" parent="GtkGrid">
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="key_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Key</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">key_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="key_entry">
+ <property name="hexpand">True</property>
+ <property name="max_length">64</property>
+ <property name="visibility">False</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="show_key_check">
+ <property name="label" translatable="yes">Sho_w key</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="auth_method_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Au_thentication</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">auth_method_combo</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">3</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="auth_method_combo">
+ <property name="hexpand">True</property>
+ <property name="model">auth_method_model</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">3</property>
+ </layout>
+ <child>
+ <object class="GtkCellRendererText"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="key_index_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">WEP inde_x</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">key_index_combo</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="key_index_combo">
+ <property name="hexpand">True</property>
+ <property name="model">key_index_model</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ <child>
+ <object class="GtkCellRendererText"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/wireless-security/ws-wpa-eap.c b/panels/network/wireless-security/ws-wpa-eap.c
new file mode 100644
index 0000000..d2b01b6
--- /dev/null
+++ b/panels/network/wireless-security/ws-wpa-eap.c
@@ -0,0 +1,313 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#include <glib/gi18n.h>
+
+#include "ws-wpa-eap.h"
+#include "wireless-security.h"
+#include "eap-method.h"
+#include "eap-method-fast.h"
+#include "eap-method-leap.h"
+#include "eap-method-peap.h"
+#include "eap-method-simple.h"
+#include "eap-method-tls.h"
+#include "eap-method-ttls.h"
+
+struct _WirelessSecurityWPAEAP {
+ GtkGrid parent;
+
+ GtkComboBox *auth_combo;
+ GtkLabel *auth_label;
+ GtkListStore *auth_model;
+ GtkBox *method_box;
+
+ EAPMethodSimple *em_md5;
+ EAPMethodTLS *em_tls;
+ EAPMethodLEAP *em_leap;
+ EAPMethodSimple *em_pwd;
+ EAPMethodFAST *em_fast;
+ EAPMethodTTLS *em_ttls;
+ EAPMethodPEAP *em_peap;
+};
+
+static void wireless_security_iface_init (WirelessSecurityInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (WirelessSecurityWPAEAP, ws_wpa_eap, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (wireless_security_get_type (), wireless_security_iface_init));
+
+#define AUTH_NAME_COLUMN 0
+#define AUTH_ID_COLUMN 1
+
+static EAPMethod *
+get_eap (WirelessSecurityWPAEAP *self)
+{
+ GtkTreeIter iter;
+ g_autofree gchar *id = NULL;
+
+ if (!gtk_combo_box_get_active_iter (self->auth_combo, &iter))
+ return NULL;
+ gtk_tree_model_get (GTK_TREE_MODEL (self->auth_model), &iter, AUTH_ID_COLUMN, &id, -1);
+
+ if (strcmp (id, "md5") == 0)
+ return EAP_METHOD (self->em_md5);
+ if (strcmp (id, "tls") == 0)
+ return EAP_METHOD (self->em_tls);
+ if (strcmp (id, "leap") == 0)
+ return EAP_METHOD (self->em_leap);
+ if (strcmp (id, "pwd") == 0)
+ return EAP_METHOD (self->em_pwd);
+ if (strcmp (id, "fast") == 0)
+ return EAP_METHOD (self->em_fast);
+ if (strcmp (id, "ttls") == 0)
+ return EAP_METHOD (self->em_ttls);
+ if (strcmp (id, "peap") == 0)
+ return EAP_METHOD (self->em_peap);
+
+ return NULL;
+}
+
+static gboolean
+validate (WirelessSecurity *security, GError **error)
+{
+ WirelessSecurityWPAEAP *self = WS_WPA_EAP (security);
+ return eap_method_validate (get_eap (self), error);
+}
+
+static void
+add_to_size_group (WirelessSecurity *security, GtkSizeGroup *group)
+{
+ WirelessSecurityWPAEAP *self = WS_WPA_EAP (security);
+
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->auth_label));
+ eap_method_add_to_size_group (EAP_METHOD (self->em_md5), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_tls), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_leap), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_pwd), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_fast), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_ttls), group);
+ eap_method_add_to_size_group (EAP_METHOD (self->em_peap), group);
+}
+
+static void
+ws_802_1x_fill_connection (WirelessSecurityWPAEAP *self, NMConnection *connection)
+{
+ NMSettingWirelessSecurity *s_wireless_sec;
+ NMSetting8021x *s_8021x;
+ NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
+ EAPMethod *eap;
+
+ /* Get the EAPMethod object */
+ eap = get_eap (self);
+
+ /* Get previous pasword flags, if any. Otherwise default to agent-owned secrets */
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ if (s_8021x)
+ nm_setting_get_secret_flags (NM_SETTING (s_8021x), eap_method_get_password_flags_name (eap), &secret_flags, NULL);
+ else
+ secret_flags = NM_SETTING_SECRET_FLAG_AGENT_OWNED;
+
+ /* Blow away the old wireless security setting by adding a clear one */
+ s_wireless_sec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+ nm_connection_add_setting (connection, (NMSetting *) s_wireless_sec);
+
+ /* Blow away the old 802.1x setting by adding a clear one */
+ s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
+ nm_connection_add_setting (connection, (NMSetting *) s_8021x);
+
+ eap_method_fill_connection (eap, connection, secret_flags);
+}
+
+static void
+fill_connection (WirelessSecurity *security, NMConnection *connection)
+{
+ WirelessSecurityWPAEAP *self = WS_WPA_EAP (security);
+ NMSettingWirelessSecurity *s_wireless_sec;
+
+ ws_802_1x_fill_connection (self, connection);
+
+ s_wireless_sec = nm_connection_get_setting_wireless_security (connection);
+ g_assert (s_wireless_sec);
+
+ g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap", NULL);
+}
+
+static gboolean
+adhoc_compatible (WirelessSecurity *security)
+{
+ return FALSE;
+}
+
+static void
+auth_combo_changed_cb (WirelessSecurityWPAEAP *self)
+{
+ EAPMethod *eap;
+ GtkWidget *eap_default_field;
+ GtkWidget *child;
+
+ eap = get_eap (self);
+
+ /* Remove the previous method and migrate username/password across */
+ child = gtk_widget_get_first_child (GTK_WIDGET (self->method_box));
+ if (child != NULL) {
+ EAPMethod *old_eap = EAP_METHOD (child);
+ eap_method_set_username (eap, eap_method_get_username (old_eap));
+ eap_method_set_password (eap, eap_method_get_password (old_eap));
+ eap_method_set_show_password (eap, eap_method_get_show_password (old_eap));
+ gtk_box_remove (self->method_box, child);
+ }
+
+ gtk_box_append (self->method_box, g_object_ref (GTK_WIDGET (eap)));
+ eap_default_field = eap_method_get_default_field (eap);
+ if (eap_default_field)
+ gtk_widget_grab_focus (eap_default_field);
+
+ wireless_security_notify_changed (WIRELESS_SECURITY (self));
+}
+
+void
+ws_wpa_eap_init (WirelessSecurityWPAEAP *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+void
+ws_wpa_eap_class_init (WirelessSecurityWPAEAPClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Settings/network/ws-wpa-eap.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWPAEAP, auth_combo);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWPAEAP, auth_label);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWPAEAP, auth_model);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWPAEAP, method_box);
+}
+
+static void
+wireless_security_iface_init (WirelessSecurityInterface *iface)
+{
+ iface->validate = validate;
+ iface->add_to_size_group = add_to_size_group;
+ iface->fill_connection = fill_connection;
+ iface->adhoc_compatible = adhoc_compatible;
+}
+
+WirelessSecurityWPAEAP *
+ws_wpa_eap_new (NMConnection *connection)
+{
+ WirelessSecurityWPAEAP *self;
+ const gchar *remove_method, *default_method = NULL;
+ gboolean wired = FALSE;
+ GtkTreeIter iter;
+
+ self = g_object_new (ws_wpa_eap_get_type (), NULL);
+
+ /* Grab the default EAP method out of the security object */
+ if (connection) {
+ NMSettingConnection *s_con;
+ NMSetting8021x *s_8021x;
+ const char *ctype = NULL;
+
+ s_con = nm_connection_get_setting_connection (connection);
+ if (s_con)
+ ctype = nm_setting_connection_get_connection_type (s_con);
+ if ((g_strcmp0 (ctype, NM_SETTING_WIRED_SETTING_NAME) == 0)
+ || nm_connection_get_setting_wired (connection))
+ wired = TRUE;
+
+ s_8021x = nm_connection_get_setting_802_1x (connection);
+ if (s_8021x && nm_setting_802_1x_get_num_eap_methods (s_8021x))
+ default_method = nm_setting_802_1x_get_eap_method (s_8021x, 0);
+ }
+ if (wired)
+ remove_method = "leap";
+ else
+ remove_method = "md5";
+ if (default_method == NULL) {
+ if (wired)
+ default_method = "md5";
+ else
+ default_method = "tls";
+ }
+
+ self->em_md5 = eap_method_simple_new (connection, "md5", FALSE, FALSE);
+ gtk_widget_show (GTK_WIDGET (self->em_md5));
+ g_signal_connect_object (self->em_md5, "changed", G_CALLBACK (wireless_security_notify_changed), self, G_CONNECT_SWAPPED);
+ self->em_tls = eap_method_tls_new (connection);
+ gtk_widget_show (GTK_WIDGET (self->em_tls));
+ g_signal_connect_object (self->em_tls, "changed", G_CALLBACK (wireless_security_notify_changed), self, G_CONNECT_SWAPPED);
+ self->em_leap = eap_method_leap_new (connection);
+ gtk_widget_show (GTK_WIDGET (self->em_leap));
+ g_signal_connect_object (self->em_leap, "changed", G_CALLBACK (wireless_security_notify_changed), self, G_CONNECT_SWAPPED);
+ self->em_pwd = eap_method_simple_new (connection, "pwd", FALSE, FALSE);
+ gtk_widget_show (GTK_WIDGET (self->em_pwd));
+ g_signal_connect_object (self->em_pwd, "changed", G_CALLBACK (wireless_security_notify_changed), self, G_CONNECT_SWAPPED);
+ self->em_fast = eap_method_fast_new (connection);
+ gtk_widget_show (GTK_WIDGET (self->em_fast));
+ g_signal_connect_object (self->em_fast, "changed", G_CALLBACK (wireless_security_notify_changed), self, G_CONNECT_SWAPPED);
+ self->em_ttls = eap_method_ttls_new (connection);
+ gtk_widget_show (GTK_WIDGET (self->em_ttls));
+ g_signal_connect_object (self->em_ttls, "changed", G_CALLBACK (wireless_security_notify_changed), self, G_CONNECT_SWAPPED);
+ self->em_peap = eap_method_peap_new (connection);
+ gtk_widget_show (GTK_WIDGET (self->em_peap));
+ g_signal_connect_object (self->em_peap, "changed", G_CALLBACK (wireless_security_notify_changed), self, G_CONNECT_SWAPPED);
+
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->auth_model), &iter)) {
+ do {
+ g_autofree gchar *id = NULL;
+ gtk_tree_model_get (GTK_TREE_MODEL (self->auth_model), &iter, AUTH_ID_COLUMN, &id, -1);
+ if (strcmp (id, remove_method) == 0) {
+ gtk_list_store_remove (self->auth_model, &iter);
+ break;
+ }
+ } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->auth_model), &iter));
+ }
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->auth_model), &iter)) {
+ do {
+ g_autofree gchar *id = NULL;
+ gtk_tree_model_get (GTK_TREE_MODEL (self->auth_model), &iter, AUTH_ID_COLUMN, &id, -1);
+ if (strcmp (id, default_method) == 0)
+ gtk_combo_box_set_active_iter (self->auth_combo, &iter);
+ } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->auth_model), &iter));
+ }
+
+ if (connection) {
+ NMSetting8021x *setting;
+
+ setting = nm_connection_get_setting_802_1x (connection);
+ if (setting) {
+ eap_method_set_username (get_eap (self), nm_setting_802_1x_get_identity (setting));
+ eap_method_set_password (get_eap (self), nm_setting_802_1x_get_password (setting));
+ }
+ }
+
+ g_signal_connect_object (G_OBJECT (self->auth_combo), "changed", G_CALLBACK (auth_combo_changed_cb), self, G_CONNECT_SWAPPED);
+ auth_combo_changed_cb (self);
+
+ return self;
+}
+
+void
+ws_wpa_eap_fill_connection (WirelessSecurityWPAEAP *self, NMConnection *connection)
+{
+ ws_802_1x_fill_connection (self, connection);
+}
diff --git a/panels/network/wireless-security/ws-wpa-eap.h b/panels/network/wireless-security/ws-wpa-eap.h
new file mode 100644
index 0000000..da5aa7f
--- /dev/null
+++ b/panels/network/wireless-security/ws-wpa-eap.h
@@ -0,0 +1,37 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (WirelessSecurityWPAEAP, ws_wpa_eap, WS, WPA_EAP, GtkGrid)
+
+WirelessSecurityWPAEAP *ws_wpa_eap_new (NMConnection *connection);
+
+void ws_wpa_eap_fill_connection (WirelessSecurityWPAEAP *sec,
+ NMConnection *connection);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/ws-wpa-eap.ui b/panels/network/wireless-security/ws-wpa-eap.ui
new file mode 100644
index 0000000..222eba7
--- /dev/null
+++ b/panels/network/wireless-security/ws-wpa-eap.ui
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.4"/>
+ <object class="GtkListStore" id="auth_model">
+ <columns>
+ <!-- column-name label -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ <!-- column-name visible -->
+ <column type="gboolean"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">MD5</col>
+ <col id="1">md5</col>
+ <col id="2">True</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">TLS</col>
+ <col id="1">tls</col>
+ <col id="2">True</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">LEAP</col>
+ <col id="1">leap</col>
+ <col id="2">True</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">PWD</col>
+ <col id="1">pwd</col>
+ <col id="2">True</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">FAST</col>
+ <col id="1">fast</col>
+ <col id="2">True</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Tunneled TLS</col>
+ <col id="1">ttls</col>
+ <col id="2">True</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Protected EAP (PEAP)</col>
+ <col id="1">peap</col>
+ <col id="2">True</col>
+ </row>
+ </data>
+ </object>
+ <template class="WirelessSecurityWPAEAP" parent="GtkGrid">
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="auth_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Au_thentication</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">auth_combo</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="auth_combo">
+ <property name="hexpand">True</property>
+ <property name="model">auth_model</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ <child>
+ <object class="GtkCellRendererText"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="method_box">
+ <property name="orientation">vertical</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="column-span">2</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/panels/network/wireless-security/ws-wpa-psk.c b/panels/network/wireless-security/ws-wpa-psk.c
new file mode 100644
index 0000000..b911b36
--- /dev/null
+++ b/panels/network/wireless-security/ws-wpa-psk.c
@@ -0,0 +1,237 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#include <ctype.h>
+#include <glib/gi18n.h>
+
+#include "helpers.h"
+#include "nma-ui-utils.h"
+#include "ui-helpers.h"
+#include "ws-wpa-psk.h"
+#include "wireless-security.h"
+
+#define WPA_PMK_LEN 32
+
+struct _WirelessSecurityWPAPSK {
+ GtkGrid parent;
+
+ GtkEntry *password_entry;
+ GtkLabel *password_label;
+ GtkCheckButton *show_password_check;
+ GtkComboBox *type_combo;
+ GtkLabel *type_label;
+};
+
+static void wireless_security_iface_init (WirelessSecurityInterface *);
+
+G_DEFINE_TYPE_WITH_CODE (WirelessSecurityWPAPSK, ws_wpa_psk, GTK_TYPE_GRID,
+ G_IMPLEMENT_INTERFACE (wireless_security_get_type (), wireless_security_iface_init));
+
+static void
+show_toggled_cb (WirelessSecurityWPAPSK *self)
+{
+ gboolean visible;
+
+ visible = gtk_check_button_get_active (GTK_CHECK_BUTTON (self->show_password_check));
+ gtk_entry_set_visibility (self->password_entry, visible);
+}
+
+static gboolean
+validate (WirelessSecurity *security, GError **error)
+{
+ WirelessSecurityWPAPSK *self = WS_WPA_PSK (security);
+ NMSettingSecretFlags secret_flags;
+ const char *key;
+ gsize len;
+ int i;
+
+ secret_flags = nma_utils_menu_to_secret_flags (GTK_WIDGET (self->password_entry));
+ if (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED) {
+ widget_unset_error (GTK_WIDGET (self->password_entry));
+ return TRUE;
+ }
+
+ key = gtk_editable_get_text (GTK_EDITABLE (self->password_entry));
+ len = key ? strlen (key) : 0;
+ if ((len < 8) || (len > 64)) {
+ widget_set_error (GTK_WIDGET (self->password_entry));
+ g_set_error (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid wpa-psk: invalid key-length %zu. Must be [8,63] bytes or 64 hex digits"), len);
+ return FALSE;
+ }
+
+ if (len == 64) {
+ /* Hex PSK */
+ for (i = 0; i < len; i++) {
+ if (!isxdigit (key[i])) {
+ widget_set_error (GTK_WIDGET (self->password_entry));
+ g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("invalid wpa-psk: cannot interpret key with 64 bytes as hex"));
+ return FALSE;
+ }
+ }
+ }
+ widget_unset_error (GTK_WIDGET (self->password_entry));
+
+ /* passphrase can be between 8 and 63 characters inclusive */
+
+ return TRUE;
+}
+
+static void
+add_to_size_group (WirelessSecurity *security, GtkSizeGroup *group)
+{
+ WirelessSecurityWPAPSK *self = WS_WPA_PSK (security);
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->type_label));
+ gtk_size_group_add_widget (group, GTK_WIDGET (self->password_label));
+}
+
+static void
+fill_connection (WirelessSecurity *security, NMConnection *connection)
+{
+ WirelessSecurityWPAPSK *self = WS_WPA_PSK (security);
+ const char *key;
+ NMSettingWireless *s_wireless;
+ NMSettingWirelessSecurity *s_wireless_sec;
+ NMSettingSecretFlags secret_flags;
+ const char *mode;
+ gboolean is_adhoc = FALSE;
+
+ s_wireless = nm_connection_get_setting_wireless (connection);
+ g_assert (s_wireless);
+
+ mode = nm_setting_wireless_get_mode (s_wireless);
+ if (mode && !strcmp (mode, "adhoc"))
+ is_adhoc = TRUE;
+
+ /* Blow away the old security setting by adding a clear one */
+ s_wireless_sec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+ nm_connection_add_setting (connection, (NMSetting *) s_wireless_sec);
+
+ key = gtk_editable_get_text (GTK_EDITABLE (self->password_entry));
+ g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_PSK, key, NULL);
+
+ /* Save PSK_FLAGS to the connection */
+ secret_flags = nma_utils_menu_to_secret_flags (GTK_WIDGET (self->password_entry));
+ nm_setting_set_secret_flags (NM_SETTING (s_wireless_sec), NM_SETTING_WIRELESS_SECURITY_PSK,
+ secret_flags, NULL);
+
+ /* Update secret flags and popup when editing the connection */
+ nma_utils_update_password_storage (GTK_WIDGET (self->password_entry), secret_flags,
+ NM_SETTING (s_wireless_sec), NM_SETTING_WIRELESS_SECURITY_PSK);
+
+ wireless_security_clear_ciphers (connection);
+ if (is_adhoc) {
+ /* Ad-Hoc settings as specified by the supplicant */
+ g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-none", NULL);
+ nm_setting_wireless_security_add_proto (s_wireless_sec, "wpa");
+ nm_setting_wireless_security_add_pairwise (s_wireless_sec, "none");
+
+ /* Ad-hoc can only have _one_ group cipher... default to TKIP to be more
+ * compatible for now. Maybe we'll support selecting CCMP later.
+ */
+ nm_setting_wireless_security_add_group (s_wireless_sec, "tkip");
+ } else {
+ g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", NULL);
+
+ /* Just leave ciphers and protocol empty, the supplicant will
+ * figure that out magically based on the AP IEs and card capabilities.
+ */
+ }
+}
+
+static gboolean
+adhoc_compatible (WirelessSecurity *security)
+{
+ return FALSE;
+}
+
+static void
+changed_cb (WirelessSecurityWPAPSK *self)
+{
+ wireless_security_notify_changed ((WirelessSecurity *) self);
+}
+
+void
+ws_wpa_psk_init (WirelessSecurityWPAPSK *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+void
+ws_wpa_psk_class_init (WirelessSecurityWPAPSKClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Settings/network/ws-wpa-psk.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWPAPSK, password_entry);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWPAPSK, password_label);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWPAPSK, show_password_check);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWPAPSK, type_combo);
+ gtk_widget_class_bind_template_child (widget_class, WirelessSecurityWPAPSK, type_label);
+}
+
+static void
+wireless_security_iface_init (WirelessSecurityInterface *iface)
+{
+ iface->validate = validate;
+ iface->add_to_size_group = add_to_size_group;
+ iface->fill_connection = fill_connection;
+ iface->adhoc_compatible = adhoc_compatible;
+}
+
+WirelessSecurityWPAPSK *
+ws_wpa_psk_new (NMConnection *connection)
+{
+ WirelessSecurityWPAPSK *self;
+ NMSetting *setting = NULL;
+
+ self = g_object_new (ws_wpa_psk_get_type (), NULL);
+
+ g_signal_connect_swapped (self->password_entry, "changed", G_CALLBACK (changed_cb), self);
+ gtk_editable_set_width_chars (GTK_EDITABLE (self->password_entry), 28);
+
+ /* Create password-storage popup menu for password entry under entry's secondary icon */
+ if (connection)
+ setting = (NMSetting *) nm_connection_get_setting_wireless_security (connection);
+ nma_utils_setup_password_storage (GTK_WIDGET (self->password_entry), 0, setting, NM_SETTING_WIRELESS_SECURITY_PSK,
+ FALSE, FALSE);
+
+ /* Fill secrets, if any */
+ if (connection) {
+ helper_fill_secret_entry (connection,
+ self->password_entry,
+ NM_TYPE_SETTING_WIRELESS_SECURITY,
+ (HelperSecretFunc) nm_setting_wireless_security_get_psk);
+ }
+
+ g_signal_connect_swapped (self->show_password_check, "toggled", G_CALLBACK (show_toggled_cb), self);
+
+ /* Hide WPA/RSN for now since this can be autodetected by NM and the
+ * supplicant when connecting to the AP.
+ */
+
+ gtk_widget_hide (GTK_WIDGET (self->type_combo));
+ gtk_widget_hide (GTK_WIDGET (self->type_label));
+
+ return self;
+}
+
diff --git a/panels/network/wireless-security/ws-wpa-psk.h b/panels/network/wireless-security/ws-wpa-psk.h
new file mode 100644
index 0000000..7ca8676
--- /dev/null
+++ b/panels/network/wireless-security/ws-wpa-psk.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <NetworkManager.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE (WirelessSecurityWPAPSK, ws_wpa_psk, WS, WPA_PSK, GtkGrid)
+
+WirelessSecurityWPAPSK *ws_wpa_psk_new (NMConnection *connection);
+
+G_END_DECLS
diff --git a/panels/network/wireless-security/ws-wpa-psk.ui b/panels/network/wireless-security/ws-wpa-psk.ui
new file mode 100644
index 0000000..26c9415
--- /dev/null
+++ b/panels/network/wireless-security/ws-wpa-psk.ui
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.4"/>
+ <template class="WirelessSecurityWPAPSK" parent="GtkGrid">
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="password_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Password</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">password_entry</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="password_entry">
+ <property name="hexpand">True</property>
+ <property name="max_length">64</property>
+ <property name="visibility">False</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="type_label">
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Type</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">type_combo</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="show_password_check">
+ <property name="label" translatable="yes">Sho_w password</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="type_combo">
+ <property name="hexpand">True</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
+ </object>
+ </child>
+ </template>
+</interface>