diff options
Diffstat (limited to 'panels/network/wireless-security')
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> |