[network-manager-applet/jk/rh879566-secret-flags: 1/4] editor: store secrets by default only for current user (rh #879566)



commit 4222caf8fdfbd561c76b33ee5ce7f3ab88ba7e49
Author: Jiří Klimeš <jklimes redhat com>
Date:   Fri Nov 1 15:45:35 2013 +0100

    editor: store secrets by default only for current user (rh #879566)
    
    Storing secrets system-wide can be a security breach. Because such a secret is
    available to all users on the system.
    
    So we default to NM_SETTING_SECRET_FLAG_AGENT_OWNED flag for all passwords,
    regardless whether the connection profile itself is available to all users or
    not. And we add a popup menu for password entries that allows users to override
    password storage. This is useful e.g. for the case when a user (admin) needs
    the connection profile to be usable at boot time.
    
    There and two pieces of data to store:
    profile storage/availability - it is influenced with "Available to all users"
    secret  storage/availability - it is influenced with secret flags
    This commit decouples these two things, so that they are independent now.
    
    Test case:
    Alice creates a connection profile for her WPA Wi-Fi access point. When she
    logouts, Bobs comes in, logs into his own account and he is able to connect to
    Alice's AP, because the profile contains the password, and it is available for
    Bob (and all users).
    
    https://bugzilla.redhat.com/show_bug.cgi?id=879566

 src/connection-editor/nm-connection-editor.c |   44 -------
 src/wireless-security/eap-method-fast.c      |    5 +-
 src/wireless-security/eap-method-leap.c      |   13 ++-
 src/wireless-security/eap-method-peap.c      |    5 +-
 src/wireless-security/eap-method-simple.c    |   18 ++-
 src/wireless-security/eap-method-tls.c       |   15 ++-
 src/wireless-security/eap-method-ttls.c      |    5 +-
 src/wireless-security/eap-method.c           |    6 +-
 src/wireless-security/eap-method.h           |    7 +-
 src/wireless-security/wireless-security.c    |  168 ++++++++++++++++++++++++--
 src/wireless-security/wireless-security.h    |   10 ++
 src/wireless-security/ws-leap.c              |   26 +++-
 src/wireless-security/ws-wep-key.c           |   26 ++++-
 src/wireless-security/ws-wpa-psk.c           |   25 ++++-
 14 files changed, 286 insertions(+), 87 deletions(-)
---
diff --git a/src/connection-editor/nm-connection-editor.c b/src/connection-editor/nm-connection-editor.c
index eb4055a..a433690 100644
--- a/src/connection-editor/nm-connection-editor.c
+++ b/src/connection-editor/nm-connection-editor.c
@@ -494,40 +494,6 @@ nm_connection_editor_get_connection (NMConnectionEditor *editor)
 }
 
 static void
-update_secret_flags (NMSetting *setting,
-                     const char *key,
-                     const GValue *value,
-                     GParamFlags flags,
-                     gpointer user_data)
-{
-       gboolean everyone = !!GPOINTER_TO_UINT (user_data);
-       NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
-
-       if (!(flags & NM_SETTING_PARAM_SECRET))
-               return;
-
-       /* VPN connections never get changed */
-       if (NM_IS_SETTING_VPN (setting))
-               return;
-
-       /* 802.1x passwords don't get changed either */
-       if (NM_IS_SETTING_802_1X (setting)) {
-               if (   g_strcmp0 (key, NM_SETTING_802_1X_PASSWORD) == 0
-                   || g_strcmp0 (key, NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD) == 0
-                   || g_strcmp0 (key, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD) == 0)
-                       return;
-       }
-
-       nm_setting_get_secret_flags (setting, key, &secret_flags, NULL);
-       if (everyone)
-               secret_flags &= ~NM_SETTING_SECRET_FLAG_AGENT_OWNED;
-       else
-               secret_flags |= NM_SETTING_SECRET_FLAG_AGENT_OWNED;
-
-       nm_setting_set_secret_flags (setting, key, secret_flags, NULL);
-}
-
-static void
 populate_connection_ui (NMConnectionEditor *editor)
 {
        NMSettingConnection *s_con;
@@ -967,18 +933,8 @@ updated_connection_cb (NMRemoteConnection *connection, GError *error, gpointer u
 static void
 ok_button_clicked_save_connection (NMConnectionEditor *self)
 {
-       NMSettingConnection *s_con;
-       gboolean everyone = FALSE;
        GError *error = NULL;
 
-       /* Update secret flags right before sending to NM (after all the editor
-        * pages have updated the modified connection) to ensure that the secret
-        * flags are always synchronized with the "Available to all users" checkbox.
-        */
-       s_con = nm_connection_get_setting_connection (self->connection);
-       everyone = !nm_setting_connection_get_num_permissions (s_con);
-       nm_connection_for_each_setting_value (self->connection, update_secret_flags, GUINT_TO_POINTER 
(everyone));
-
        /* Copy the modified connection to the original connection */
        if (!nm_connection_replace_settings_from_connection (self->orig_connection,
                                                             self->connection,
diff --git a/src/wireless-security/eap-method-fast.c b/src/wireless-security/eap-method-fast.c
index 853367f..6077495 100644
--- a/src/wireless-security/eap-method-fast.c
+++ b/src/wireless-security/eap-method-fast.c
@@ -124,7 +124,7 @@ add_to_size_group (EAPMethod *parent, GtkSizeGroup *group)
 }
 
 static void
-fill_connection (EAPMethod *parent, NMConnection *connection)
+fill_connection (EAPMethod *parent, NMConnection *connection, NMSettingSecretFlags flags)
 {
        NMSetting8021x *s_8021x;
        GtkWidget *widget;
@@ -183,7 +183,7 @@ fill_connection (EAPMethod *parent, NMConnection *connection)
        gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
        g_assert (eap);
 
-       eap_method_fill_connection (eap, connection);
+       eap_method_fill_connection (eap, connection, flags);
        eap_method_unref (eap);
 }
 
@@ -350,6 +350,7 @@ eap_method_fast_new (WirelessSecurity *ws_parent,
        if (!parent)
                return NULL;
 
+       parent->password_flags_name = NM_SETTING_802_1X_PASSWORD;
        method = (EAPMethodFAST *) parent;
        method->sec_parent = ws_parent;
        method->is_editor = is_editor;
diff --git a/src/wireless-security/eap-method-leap.c b/src/wireless-security/eap-method-leap.c
index 44f2342..44eb720 100644
--- a/src/wireless-security/eap-method-leap.c
+++ b/src/wireless-security/eap-method-leap.c
@@ -81,7 +81,7 @@ add_to_size_group (EAPMethod *parent, GtkSizeGroup *group)
 }
 
 static void
-fill_connection (EAPMethod *parent, NMConnection *connection)
+fill_connection (EAPMethod *parent, NMConnection *connection, NMSettingSecretFlags flags)
 {
        EAPMethodLEAP *method = (EAPMethodLEAP *) parent;
        NMSetting8021x *s_8021x;
@@ -96,9 +96,10 @@ fill_connection (EAPMethod *parent, NMConnection *connection)
 
        /* Default to agent-owned secrets for new connections */
        if (method->new_connection) {
-               g_object_set (s_8021x,
-                             NM_SETTING_802_1X_PASSWORD_FLAGS, NM_SETTING_SECRET_FLAG_AGENT_OWNED,
-                             NULL);
+               GtkWidget *passwd_entry = GTK_WIDGET (gtk_builder_get_object (parent->builder, 
"eap_leap_password_entry"));
+               g_assert (passwd_entry);
+
+               ws_update_password_storage (NM_SETTING (s_8021x), flags, passwd_entry, 
parent->password_flags_name);
        }
 }
 
@@ -187,6 +188,7 @@ eap_method_leap_new (WirelessSecurity *ws_parent,
        if (!parent)
                return NULL;
 
+       parent->password_flags_name = NM_SETTING_802_1X_PASSWORD;
        method = (EAPMethodLEAP *) parent;
        method->new_connection = secrets_only ? FALSE : TRUE;
        method->ws_parent = wireless_security_ref (ws_parent);
@@ -217,6 +219,9 @@ eap_method_leap_new (WirelessSecurity *ws_parent,
                          (GCallback) wireless_security_changed_cb,
                          ws_parent);
 
+       /* Create password-storage popup menu for password entry under entry's secondary icon */
+       ws_setup_password_storage (connection, NM_SETTING_802_1X_SETTING_NAME, widget, 
parent->password_flags_name);
+
        widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "show_checkbutton_eapleap"));
        g_assert (widget);
        method->show_password = GTK_TOGGLE_BUTTON (widget);
diff --git a/src/wireless-security/eap-method-peap.c b/src/wireless-security/eap-method-peap.c
index 932ae25..e88552e 100644
--- a/src/wireless-security/eap-method-peap.c
+++ b/src/wireless-security/eap-method-peap.c
@@ -131,7 +131,7 @@ add_to_size_group (EAPMethod *parent, GtkSizeGroup *group)
 }
 
 static void
-fill_connection (EAPMethod *parent, NMConnection *connection)
+fill_connection (EAPMethod *parent, NMConnection *connection, NMSettingSecretFlags flags)
 {
        NMSetting8021x *s_8021x;
        NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
@@ -187,7 +187,7 @@ fill_connection (EAPMethod *parent, NMConnection *connection)
        gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
        g_assert (eap);
 
-       eap_method_fill_connection (eap, connection);
+       eap_method_fill_connection (eap, connection, flags);
        eap_method_unref (eap);
 }
 static void
@@ -352,6 +352,7 @@ eap_method_peap_new (WirelessSecurity *ws_parent,
        if (!parent)
                return NULL;
 
+       parent->password_flags_name = NM_SETTING_802_1X_PASSWORD;
        method = (EAPMethodPEAP *) parent;
        method->sec_parent = ws_parent;
        method->is_editor = is_editor;
diff --git a/src/wireless-security/eap-method-simple.c b/src/wireless-security/eap-method-simple.c
index 74830bc..ffbf8df 100644
--- a/src/wireless-security/eap-method-simple.c
+++ b/src/wireless-security/eap-method-simple.c
@@ -89,13 +89,13 @@ add_to_size_group (EAPMethod *parent, GtkSizeGroup *group)
 }
 
 static void
-fill_connection (EAPMethod *parent, NMConnection *connection)
+fill_connection (EAPMethod *parent, NMConnection *connection, NMSettingSecretFlags prev_flags)
 {
        EAPMethodSimple *method = (EAPMethodSimple *) parent;
        NMSetting8021x *s_8021x;
        gboolean not_saved = FALSE;
        const char *eap = NULL;
-       NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
+       NMSettingSecretFlags flags = prev_flags;
 
        s_8021x = nm_connection_get_setting_802_1x (connection);
        g_assert (s_8021x);
@@ -143,7 +143,6 @@ fill_connection (EAPMethod *parent, NMConnection *connection)
        /* Save the password always ask setting */
        not_saved = gtk_toggle_button_get_active (method->always_ask);
 
-       nm_setting_get_secret_flags (NM_SETTING (s_8021x), NM_SETTING_802_1X_PASSWORD, &flags, NULL);
        flags &= ~(NM_SETTING_SECRET_FLAG_NOT_SAVED);
        if (not_saved)
                flags |= NM_SETTING_SECRET_FLAG_NOT_SAVED;
@@ -159,10 +158,11 @@ fill_connection (EAPMethod *parent, NMConnection *connection)
        }
 
        /* Default to agent-owned secrets for new connections */
-       if (method->new_connection && (not_saved == FALSE)) {
-               g_object_set (s_8021x,
-                             NM_SETTING_802_1X_PASSWORD_FLAGS, NM_SETTING_SECRET_FLAG_AGENT_OWNED,
-                             NULL);
+       if (method->new_connection) {
+               GtkWidget *passwd_entry = GTK_WIDGET (gtk_builder_get_object (parent->builder, 
"eap_simple_password_entry"));
+               g_assert (passwd_entry);
+
+               ws_update_password_storage (NM_SETTING (s_8021x), flags, passwd_entry, 
parent->password_flags_name);
        }
 }
 
@@ -297,6 +297,7 @@ eap_method_simple_new (WirelessSecurity *ws_parent,
        if (!parent)
                return NULL;
 
+       parent->password_flags_name = NM_SETTING_802_1X_PASSWORD;
        method = (EAPMethodSimple *) parent;
        method->type = type;
        method->is_editor = is_editor;
@@ -329,6 +330,9 @@ eap_method_simple_new (WirelessSecurity *ws_parent,
                          (GCallback) wireless_security_changed_cb,
                          ws_parent);
 
+       /* Create password-storage popup menu for password entry under entry's secondary icon */
+       ws_setup_password_storage (connection, NM_SETTING_802_1X_SETTING_NAME, widget, 
parent->password_flags_name);
+
        widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_password_always_ask"));
        g_assert (widget);
        method->always_ask = GTK_TOGGLE_BUTTON (widget);
diff --git a/src/wireless-security/eap-method-tls.c b/src/wireless-security/eap-method-tls.c
index a48b491..8777fed 100644
--- a/src/wireless-security/eap-method-tls.c
+++ b/src/wireless-security/eap-method-tls.c
@@ -132,12 +132,12 @@ add_to_size_group (EAPMethod *parent, GtkSizeGroup *group)
 }
 
 static void
-fill_connection (EAPMethod *parent, NMConnection *connection)
+fill_connection (EAPMethod *parent, NMConnection *connection, NMSettingSecretFlags flags)
 {
        EAPMethodTLS *method = (EAPMethodTLS *) parent;
        NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
        NMSetting8021x *s_8021x;
-       GtkWidget *widget;
+       GtkWidget *widget, *passwd_entry;
        char *ca_filename, *pk_filename, *cc_filename;
        const char *password = NULL;
        GError *error = NULL;
@@ -161,6 +161,7 @@ fill_connection (EAPMethod *parent, NMConnection *connection)
        g_assert (widget);
        password = gtk_entry_get_text (GTK_ENTRY (widget));
        g_assert (password);
+       passwd_entry = widget;
 
        widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "eap_tls_private_key_button"));
        g_assert (widget);
@@ -184,9 +185,7 @@ fill_connection (EAPMethod *parent, NMConnection *connection)
 
        /* Default to agent-owned secrets for new connections */
        if (method->new_connection) {
-               g_object_set (s_8021x,
-                             secret_flag_prop, NM_SETTING_SECRET_FLAG_AGENT_OWNED,
-                             NULL);
+               ws_update_password_storage (NM_SETTING (s_8021x), flags, passwd_entry, 
parent->password_flags_name);
        }
 
        /* TLS client certificate */
@@ -428,6 +427,9 @@ eap_method_tls_new (WirelessSecurity *ws_parent,
        if (!parent)
                return NULL;
 
+       parent->password_flags_name = phase2 ?
+                                       NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD :
+                                       NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD;
        method = (EAPMethodTLS *) parent;
        method->new_connection = secrets_only ? FALSE : TRUE;
 
@@ -487,6 +489,9 @@ eap_method_tls_new (WirelessSecurity *ws_parent,
                          (GCallback) wireless_security_changed_cb,
                          ws_parent);
 
+       /* Create password-storage popup menu for password entry under entry's secondary icon */
+       ws_setup_password_storage (connection, NM_SETTING_802_1X_SETTING_NAME, widget, 
parent->password_flags_name);
+
        widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "show_checkbutton_eaptls"));
        g_assert (widget);
        g_signal_connect (G_OBJECT (widget), "toggled",
diff --git a/src/wireless-security/eap-method-ttls.c b/src/wireless-security/eap-method-ttls.c
index 8d45865..d4e0f36 100644
--- a/src/wireless-security/eap-method-ttls.c
+++ b/src/wireless-security/eap-method-ttls.c
@@ -127,7 +127,7 @@ add_to_size_group (EAPMethod *parent, GtkSizeGroup *group)
 }
 
 static void
-fill_connection (EAPMethod *parent, NMConnection *connection)
+fill_connection (EAPMethod *parent, NMConnection *connection, NMSettingSecretFlags flags)
 {
        NMSetting8021x *s_8021x;
        NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
@@ -168,7 +168,7 @@ fill_connection (EAPMethod *parent, NMConnection *connection)
        gtk_tree_model_get (model, &iter, I_METHOD_COLUMN, &eap, -1);
        g_assert (eap);
 
-       eap_method_fill_connection (eap, connection);
+       eap_method_fill_connection (eap, connection, flags);
        eap_method_unref (eap);
 }
 
@@ -352,6 +352,7 @@ eap_method_ttls_new (WirelessSecurity *ws_parent,
        if (!parent)
                return NULL;
 
+       parent->password_flags_name = NM_SETTING_802_1X_PASSWORD;
        method = (EAPMethodTTLS *) parent;
        method->sec_parent = ws_parent;
        method->is_editor = is_editor;
diff --git a/src/wireless-security/eap-method.c b/src/wireless-security/eap-method.c
index bdd67d0..ffadeeb 100644
--- a/src/wireless-security/eap-method.c
+++ b/src/wireless-security/eap-method.c
@@ -67,13 +67,15 @@ eap_method_add_to_size_group (EAPMethod *method, GtkSizeGroup *group)
 }
 
 void
-eap_method_fill_connection (EAPMethod *method, NMConnection *connection)
+eap_method_fill_connection (EAPMethod *method,
+                            NMConnection *connection,
+                            NMSettingSecretFlags flags)
 {
        g_return_if_fail (method != NULL);
        g_return_if_fail (connection != NULL);
 
        g_assert (method->fill_connection);
-       return (*(method->fill_connection)) (method, connection);
+       return (*(method->fill_connection)) (method, connection, flags);
 }
 
 void
diff --git a/src/wireless-security/eap-method.h b/src/wireless-security/eap-method.h
index 0dd6c63..cf02081 100644
--- a/src/wireless-security/eap-method.h
+++ b/src/wireless-security/eap-method.h
@@ -32,7 +32,7 @@
 typedef struct _EAPMethod EAPMethod;
 
 typedef void        (*EMAddToSizeGroupFunc) (EAPMethod *method, GtkSizeGroup *group);
-typedef void        (*EMFillConnectionFunc) (EAPMethod *method, NMConnection *connection);
+typedef void        (*EMFillConnectionFunc) (EAPMethod *method, NMConnection *connection, 
NMSettingSecretFlags flags);
 typedef void        (*EMUpdateSecretsFunc)  (EAPMethod *method, NMConnection *connection);
 typedef void        (*EMDestroyFunc)        (EAPMethod *method);
 typedef gboolean    (*EMValidateFunc)       (EAPMethod *method);
@@ -45,6 +45,7 @@ struct _EAPMethod {
        GtkWidget *ui_widget;
 
        const char *default_field;
+       const char *password_flags_name;
 
        gboolean phase2;
        gboolean secrets_only;
@@ -65,7 +66,9 @@ gboolean eap_method_validate (EAPMethod *method);
 
 void eap_method_add_to_size_group (EAPMethod *method, GtkSizeGroup *group);
 
-void eap_method_fill_connection (EAPMethod *method, NMConnection *connection);
+void eap_method_fill_connection (EAPMethod *method,
+                                 NMConnection *connection,
+                                 NMSettingSecretFlags flags);
 
 void eap_method_update_secrets (EAPMethod *method, NMConnection *connection);
 
diff --git a/src/wireless-security/wireless-security.c b/src/wireless-security/wireless-security.c
index 47131ee..7c7d9f3 100644
--- a/src/wireless-security/wireless-security.c
+++ b/src/wireless-security/wireless-security.c
@@ -245,7 +245,7 @@ wireless_security_set_userpass_802_1x (WirelessSecurity *sec,
        password = nm_setting_802_1x_get_password (setting);
 
        if (nm_setting_get_secret_flags (NM_SETTING (setting), NM_SETTING_802_1X_PASSWORD, &flags, NULL))
-               always_ask = flags & NM_SETTING_SECRET_FLAG_NOT_SAVED;
+               always_ask = !!(flags & NM_SETTING_SECRET_FLAG_NOT_SAVED);
 
 set:
        wireless_security_set_userpass (sec, user, password, always_ask, show_password);
@@ -518,10 +518,25 @@ ws_802_1x_fill_connection (WirelessSecurity *sec,
        GtkWidget *widget;
        NMSettingWirelessSecurity *s_wireless_sec;
        NMSetting8021x *s_8021x;
+       NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
        EAPMethod *eap = NULL;
        GtkTreeModel *model;
        GtkTreeIter iter;
 
+       /* Get the EAPMethod object */
+       widget = GTK_WIDGET (gtk_builder_get_object (sec->builder, combo_name));
+       model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+       gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
+       gtk_tree_model_get (model, &iter, AUTH_METHOD_COLUMN, &eap, -1);
+       g_assert (eap);
+
+       /* 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->password_flags_name, &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);
@@ -530,13 +545,7 @@ ws_802_1x_fill_connection (WirelessSecurity *sec,
        s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
        nm_connection_add_setting (connection, (NMSetting *) s_8021x);
 
-       widget = GTK_WIDGET (gtk_builder_get_object (sec->builder, combo_name));
-       model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
-       gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
-       gtk_tree_model_get (model, &iter, AUTH_METHOD_COLUMN, &eap, -1);
-       g_assert (eap);
-
-       eap_method_fill_connection (eap, connection);
+       eap_method_fill_connection (eap, connection, secret_flags);
        eap_method_unref (eap);
 }
 
@@ -570,3 +579,146 @@ ws_802_1x_update_secrets (WirelessSecurity *sec,
        }
 }
 
+typedef struct {
+       NMConnection *connection;
+       const char *setting_name;
+       const char *password_flags_name;
+       int item_number;
+} PopupMenuItemInfo;
+
+static void
+popup_menu_item_info_destroy (gpointer data)
+{
+       g_slice_free (PopupMenuItemInfo, data);
+}
+
+static void
+activate_menu_item_cb (GtkMenuItem *menuitem, gpointer user_data)
+{
+       PopupMenuItemInfo *info = (PopupMenuItemInfo *) user_data;
+       NMSetting *setting;
+       NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
+
+       /* Get current secret flags */
+       setting = nm_connection_get_setting_by_name (info->connection, info->setting_name);
+       if (setting)
+               nm_setting_get_secret_flags (setting, info->password_flags_name, &secret_flags, NULL);
+
+       /* Update password flags according to the password-storage popup menu */
+       if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (menuitem))) {
+               if (info->item_number == 1)
+                       secret_flags |= NM_SETTING_SECRET_FLAG_AGENT_OWNED;
+               else
+                       secret_flags &= ~NM_SETTING_SECRET_FLAG_AGENT_OWNED;
+
+               /* Update the secret flags */
+               if (setting)
+                       nm_setting_set_secret_flags (setting, info->password_flags_name, secret_flags, NULL);
+       }
+}
+
+static void
+icon_release_cb (GtkEntry *entry,
+                 GtkEntryIconPosition position,
+                 GdkEventButton *event,
+                 gpointer data)
+{
+       GtkMenu *menu = GTK_MENU (data);
+       if (position == GTK_ENTRY_ICON_SECONDARY) {
+               gtk_widget_show_all (GTK_WIDGET (data));
+               gtk_menu_popup (menu, NULL, NULL, NULL, NULL,
+                               event->button, event->time);
+       }
+}
+
+/* Add secondary icon and create popup menu for password entry */
+void
+ws_setup_password_storage (NMConnection *connection,
+                           const char *setting_name,
+                           GtkWidget *passwd_entry,
+                           const char *password_flags_name)
+{
+       GtkWidget *popup_menu;
+       GtkWidget *item1, *item2;
+       GSList *group;
+       PopupMenuItemInfo *info;
+       NMSetting *setting;
+
+       gtk_entry_set_icon_from_icon_name (GTK_ENTRY (passwd_entry), GTK_ENTRY_ICON_SECONDARY, 
"document-save");
+       popup_menu = gtk_menu_new ();
+       group = NULL;
+       item1 = gtk_radio_menu_item_new_with_mnemonic (group, _("Store the password only for this _user"));
+       group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item1));
+       item2 = gtk_radio_menu_item_new_with_mnemonic (group, _("Store the password for _all users"));
+
+       gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), item1);
+       gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), item2);
+
+       info = g_slice_new0 (PopupMenuItemInfo);
+       info->connection = connection;
+       info->setting_name = setting_name;
+       info->password_flags_name = password_flags_name;
+       info->item_number = 1;
+       g_signal_connect_data (item1, "activate",
+                              G_CALLBACK (activate_menu_item_cb),
+                              info,
+                              (GClosureNotify) popup_menu_item_info_destroy, 0);
+
+       info = g_slice_new0 (PopupMenuItemInfo);
+       info->connection = connection;
+       info->setting_name = setting_name;
+       info->password_flags_name = password_flags_name;
+       info->item_number = 2;
+       g_signal_connect_data (item2, "activate",
+                              G_CALLBACK (activate_menu_item_cb),
+                              info,
+                              (GClosureNotify) popup_menu_item_info_destroy, 0);
+
+       g_signal_connect (passwd_entry, "icon-release", G_CALLBACK (icon_release_cb), popup_menu);
+       gtk_menu_attach_to_widget (GTK_MENU (popup_menu), passwd_entry, NULL);
+
+       /* Initialize active item for password-storage popup menu */
+       setting = nm_connection_get_setting_by_name (connection, setting_name);
+       if (setting) {
+               NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
+               nm_setting_get_secret_flags (setting, password_flags_name, &secret_flags, NULL);
+
+               if (secret_flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED)
+                       gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item1), TRUE);
+               else
+                       gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item2), TRUE);
+       } else {
+               gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item1), TRUE);
+       }
+}
+
+void
+ws_update_password_storage (NMSetting *setting,
+                            NMSettingSecretFlags secret_flags,
+                            GtkWidget *passwd_entry,
+                            const char *password_flags_name)
+{
+       GList *menu;
+
+       /* Update secret flags (WEP_KEY_FLAGS, PSK_FLAGS, ...) in the security setting */
+       nm_setting_set_secret_flags (setting, password_flags_name, secret_flags, NULL);
+
+       /* Update password-storage popup menu to reflect secret flags */
+       menu = gtk_menu_get_for_attach_widget (passwd_entry);
+       if (menu && menu->data) {
+               GtkRadioMenuItem *item, *item_user, *item_system;
+               GSList *group;
+
+               /* radio menu group list contains the menu items in reverse order */
+               item = (GtkRadioMenuItem *) gtk_menu_get_active (GTK_MENU (menu->data));
+               group = gtk_radio_menu_item_get_group (item);
+               item_system = group->data;
+               item_user = group->next->data;
+
+               if (secret_flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED)
+                       gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item_user), TRUE);
+               else
+                       gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item_system), TRUE);
+       }
+}
+
diff --git a/src/wireless-security/wireless-security.h b/src/wireless-security/wireless-security.h
index 4a1a4fe..f100a67 100644
--- a/src/wireless-security/wireless-security.h
+++ b/src/wireless-security/wireless-security.h
@@ -148,5 +148,15 @@ void ws_802_1x_update_secrets (WirelessSecurity *sec,
                                const char *combo_name,
                                NMConnection *connection);
 
+void ws_setup_password_storage (NMConnection *connection,
+                                const char *setting_name,
+                                GtkWidget *passwd_entry,
+                                const char *password_flags_name);
+
+void ws_update_password_storage (NMSetting *setting,
+                                 NMSettingSecretFlags secret_flags,
+                                 GtkWidget *passwd_entry,
+                                 const char *password_flags_name);
+
 #endif /* WIRELESS_SECURITY_H */
 
diff --git a/src/wireless-security/ws-leap.c b/src/wireless-security/ws-leap.c
index 0db9c1a..a7adccd 100644
--- a/src/wireless-security/ws-leap.c
+++ b/src/wireless-security/ws-leap.c
@@ -29,6 +29,7 @@
 struct _WirelessSecurityLEAP {
        WirelessSecurity parent;
        gboolean new_connection;
+       const char *password_flags_name;
 };
 
 static void
@@ -82,9 +83,19 @@ fill_connection (WirelessSecurity *parent, NMConnection *connection)
 {
        WirelessSecurityLEAP *sec = (WirelessSecurityLEAP *) parent;
        NMSettingWirelessSecurity *s_wireless_sec;
-       GtkWidget *widget;
+       NMSettingSecretFlags secret_flags;
+       GtkWidget *widget, *passwd_entry;
        const char *leap_password = NULL, *leap_username = NULL;
 
+       /* Get LEAP_PASSWORD_FLAGS from the old security setting, if any, or
+        * set the flags to NM_SETTING_SECRET_FLAG_AGENT_OWNED by default.
+        */
+       s_wireless_sec = nm_connection_get_setting_wireless_security (connection);
+       if (s_wireless_sec)
+               secret_flags = nm_setting_wireless_security_get_leap_password_flags (s_wireless_sec);
+       else
+               secret_flags = NM_SETTING_SECRET_FLAG_AGENT_OWNED;
+
        /* 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);
@@ -93,6 +104,7 @@ fill_connection (WirelessSecurity *parent, NMConnection *connection)
        leap_username = gtk_entry_get_text (GTK_ENTRY (widget));
 
        widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "leap_password_entry"));
+       passwd_entry = widget;
        leap_password = gtk_entry_get_text (GTK_ENTRY (widget));
 
        g_object_set (s_wireless_sec,
@@ -103,11 +115,8 @@ fill_connection (WirelessSecurity *parent, NMConnection *connection)
                      NULL);
 
        /* Default to agent-owned secrets for new connections */
-       if (sec->new_connection) {
-               g_object_set (s_wireless_sec,
-                             NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS, 
NM_SETTING_SECRET_FLAG_AGENT_OWNED,
-                             NULL);
-       }
+       if (sec->new_connection)
+               ws_update_password_storage (NM_SETTING (s_wireless_sec), secret_flags, passwd_entry, 
sec->password_flags_name);
 }
 
 static void
@@ -155,12 +164,17 @@ ws_leap_new (NMConnection *connection, gboolean secrets_only)
        parent->adhoc_compatible = FALSE;
        sec = (WirelessSecurityLEAP *) parent;
        sec->new_connection = secrets_only ? FALSE : TRUE;
+       sec->password_flags_name = NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD;
 
        widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "leap_password_entry"));
        g_assert (widget);
        g_signal_connect (G_OBJECT (widget), "changed",
                          (GCallback) wireless_security_changed_cb,
                          sec);
+
+       /* Create password-storage popup menu for password entry under entry's secondary icon */
+       ws_setup_password_storage (connection, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, widget, 
sec->password_flags_name);
+
        if (wsec)
                update_secrets (WIRELESS_SECURITY (sec), connection);
 
diff --git a/src/wireless-security/ws-wep-key.c b/src/wireless-security/ws-wep-key.c
index 37dbceb..ed86030 100644
--- a/src/wireless-security/ws-wep-key.c
+++ b/src/wireless-security/ws-wep-key.c
@@ -32,6 +32,9 @@
 struct _WirelessSecurityWEPKey {
        WirelessSecurity parent;
 
+       gboolean new_connection;
+       const char *password_flags_name;
+
        NMWepKeyType type;
        char keys[4][65];
        guint8 cur_index;
@@ -144,7 +147,8 @@ fill_connection (WirelessSecurity *parent, NMConnection *connection)
 {
        WirelessSecurityWEPKey *sec = (WirelessSecurityWEPKey *) parent;
        NMSettingWirelessSecurity *s_wsec;
-       GtkWidget *widget;
+       NMSettingSecretFlags secret_flags;
+       GtkWidget *widget, *passwd_entry;
        gint auth_alg;
        const char *key;
        int i;
@@ -153,9 +157,19 @@ fill_connection (WirelessSecurity *parent, NMConnection *connection)
        auth_alg = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
 
        widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wep_key_entry"));
+       passwd_entry = widget;
        key = gtk_entry_get_text (GTK_ENTRY (widget));
        strcpy (sec->keys[sec->cur_index], key);
 
+       /* Get WEP_KEY_FLAGS from the old security setting, if any. Else
+        * initialize the flags to NM_SETTING_SECRET_FLAG_AGENT_OWNED.
+        */
+       s_wsec = nm_connection_get_setting_wireless_security (connection);
+       if (s_wsec)
+               secret_flags = nm_setting_wireless_security_get_wep_key_flags (s_wsec);
+       else
+               secret_flags = NM_SETTING_SECRET_FLAG_AGENT_OWNED;
+
        /* 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);
@@ -171,6 +185,9 @@ fill_connection (WirelessSecurity *parent, NMConnection *connection)
                if (strlen (sec->keys[i]))
                        nm_setting_wireless_security_set_wep_key (s_wsec, i, sec->keys[i]);
        }
+
+       if (sec->new_connection)
+               ws_update_password_storage (NM_SETTING (s_wsec), secret_flags, passwd_entry, 
sec->password_flags_name);
 }
 
 static void
@@ -236,14 +253,19 @@ ws_wep_key_new (NMConnection *connection,
                                         "wep_key_entry");
        if (!parent)
                return NULL;
-       
+
        sec = (WirelessSecurityWEPKey *) parent;
+       sec->new_connection = secrets_only ? FALSE : TRUE;
+       sec->password_flags_name = NM_SETTING_WIRELESS_SECURITY_WEP_KEY0;
        sec->type = type;
 
        widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wep_key_entry"));
        g_assert (widget);
        gtk_entry_set_width_chars (GTK_ENTRY (widget), 28);
 
+       /* Create password-storage popup menu for password entry under entry's secondary icon */
+       ws_setup_password_storage (connection, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, widget, 
sec->password_flags_name);
+
        if (connection) {
                NMSettingWireless *s_wireless;
                const char *mode, *auth_alg;
diff --git a/src/wireless-security/ws-wpa-psk.c b/src/wireless-security/ws-wpa-psk.c
index bc27a2f..8ab7f76 100644
--- a/src/wireless-security/ws-wpa-psk.c
+++ b/src/wireless-security/ws-wpa-psk.c
@@ -31,6 +31,9 @@
 
 struct _WirelessSecurityWPAPSK {
        WirelessSecurity parent;
+
+       gboolean new_connection;
+       const char *password_flags_name;
 };
 
 static void
@@ -90,10 +93,12 @@ add_to_size_group (WirelessSecurity *parent, GtkSizeGroup *group)
 static void
 fill_connection (WirelessSecurity *parent, NMConnection *connection)
 {
-       GtkWidget *widget;
+       WirelessSecurityWPAPSK *wpa_psk = (WirelessSecurityWPAPSK *) parent;
+       GtkWidget *widget, *passwd_entry;
        const char *key;
        NMSettingWireless *s_wireless;
        NMSettingWirelessSecurity *s_wireless_sec;
+       NMSettingSecretFlags secret_flags;
        const char *mode;
        gboolean is_adhoc = FALSE;
 
@@ -104,14 +109,27 @@ fill_connection (WirelessSecurity *parent, NMConnection *connection)
        if (mode && !strcmp (mode, "adhoc"))
                is_adhoc = TRUE;
 
+       /* Get PSK_FLAGS from the old security setting, if any. Else
+        * initialize the flags to NM_SETTING_SECRET_FLAG_AGENT_OWNED.
+        */
+       s_wireless_sec = nm_connection_get_setting_wireless_security (connection);
+       if (s_wireless_sec)
+               secret_flags = nm_setting_wireless_security_get_psk_flags (s_wireless_sec);
+       else
+               secret_flags = NM_SETTING_SECRET_FLAG_AGENT_OWNED;
+
        /* 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);
 
        widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wpa_psk_entry"));
+       passwd_entry = widget;
        key = gtk_entry_get_text (GTK_ENTRY (widget));
        g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_PSK, key, NULL);
 
+       if (wpa_psk->new_connection)
+               ws_update_password_storage (NM_SETTING (s_wireless_sec), secret_flags, passwd_entry, 
wpa_psk->password_flags_name);
+
        wireless_security_clear_ciphers (connection);
        if (is_adhoc) {
                /* Ad-Hoc settings as specified by the supplicant */
@@ -163,6 +181,8 @@ ws_wpa_psk_new (NMConnection *connection, gboolean secrets_only)
 
        parent->adhoc_compatible = FALSE;
        sec = (WirelessSecurityWPAPSK *) parent;
+       sec->new_connection = secrets_only ? FALSE : TRUE;
+       sec->password_flags_name = NM_SETTING_WIRELESS_SECURITY_PSK;
 
        widget = GTK_WIDGET (gtk_builder_get_object (parent->builder, "wpa_psk_entry"));
        g_assert (widget);
@@ -171,6 +191,9 @@ ws_wpa_psk_new (NMConnection *connection, gboolean secrets_only)
                          sec);
        gtk_entry_set_width_chars (GTK_ENTRY (widget), 28);
 
+       /* Create password-storage popup menu for password entry under entry's secondary icon */
+       ws_setup_password_storage (connection, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, widget, 
sec->password_flags_name);
+
        /* Fill secrets, if any */
        if (connection)
                update_secrets (WIRELESS_SECURITY (sec), connection);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]