[network-manager-applet] gsm: fix secret requests when connection has multiple secrets
- From: Dan Williams <dcbw src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [network-manager-applet] gsm: fix secret requests when connection has multiple secrets
- Date: Fri, 12 Feb 2010 05:52:16 +0000 (UTC)
commit 4f6d7def24645840604551b7f2dde4e1bb4db5d8
Author: Dan Williams <dcbw redhat com>
Date: Thu Feb 11 21:47:45 2010 -0800
gsm: fix secret requests when connection has multiple secrets
We need to return either *all* secrets in the secret request
reply (either only all the secrets, or the whole setting hash
including all the secrets). But not a setting hash including
only *some* secrets like we were doing. Otherwise if there are
multiple secrets (like a GSM password and a PIN) we'll get into
a loop asking for each secret in turn, but never actually using
them correctly.
src/applet-device-gsm.c | 159 ++++++++++++++++++++++++++++++++++-------------
1 files changed, 115 insertions(+), 44 deletions(-)
---
diff --git a/src/applet-device-gsm.c b/src/applet-device-gsm.c
index 09c4c35..31575e9 100644
--- a/src/applet-device-gsm.c
+++ b/src/applet-device-gsm.c
@@ -423,75 +423,146 @@ update_cb (NMSettingsConnectionInterface *connection,
}
static void
-get_gsm_secrets_cb (GtkDialog *dialog,
- gint response,
- gpointer user_data)
+get_existing_secrets_cb (NMSettingsConnectionInterface *connection,
+ GHashTable *existing_secrets,
+ GError *secrets_error,
+ gpointer user_data)
{
NMGsmInfo *info = (NMGsmInfo *) user_data;
- NMSettingGsm *setting;
- GHashTable *settings_hash;
- GHashTable *secrets;
- GError *err = NULL;
+ GHashTable *settings;
+ GError *error = NULL;
+ gboolean save_secret = FALSE;
+ const char *new_secret = NULL;
- /* Got a user response, clear the NMActiveConnection destroy handler for
- * this dialog since this function will now take over dialog destruction.
- */
- g_object_weak_unref (G_OBJECT (info->active_connection), destroy_gsm_dialog, info);
+ if (secrets_error) {
+ error = g_error_copy (secrets_error);
+ goto done;
+ }
- if (response != GTK_RESPONSE_OK) {
- g_set_error (&err,
+ /* Be a bit paranoid */
+ if (connection != info->connection) {
+ g_set_error (&error,
NM_SETTINGS_INTERFACE_ERROR,
NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR,
- "%s.%d (%s): canceled",
+ "%s.%d (%s): unexpected reply for wrong connection.",
__FILE__, __LINE__, __func__);
goto done;
}
- setting = NM_SETTING_GSM (nm_connection_get_setting (NM_CONNECTION (info->connection), NM_TYPE_SETTING_GSM));
-
- if (!strcmp (info->secret_name, NM_SETTING_GSM_PIN) ||
- !strcmp (info->secret_name, NM_SETTING_GSM_PUK) ||
- !strcmp (info->secret_name, NM_SETTING_GSM_PASSWORD))
- g_object_set (setting, info->secret_name, gtk_entry_get_text (info->secret_entry), NULL);
+ /* Update connection's secrets so we can hash them for sending back to
+ * NM, and so we can save them all back out to GConf if needed.
+ */
+ if (existing_secrets) {
+ GHashTableIter iter;
+ gpointer key, value;
+
+ g_hash_table_iter_init (&iter, existing_secrets);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ GError *update_error = NULL;
+ const char *setting_name = key;
+ GHashTable *setting_hash = value;
+
+ /* Keep track of whether or not the user originall saved the secret */
+ if (!strcmp (setting_name, NM_SETTING_GSM_SETTING_NAME)) {
+ if (g_hash_table_lookup (setting_hash, info->secret_name))
+ save_secret = TRUE;
+ }
- secrets = nm_setting_to_hash (NM_SETTING (setting));
- if (!secrets) {
- g_set_error (&err,
- NM_SETTINGS_INTERFACE_ERROR,
- NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR,
- "%s.%d (%s): failed to hash setting '%s'.",
- __FILE__, __LINE__, __func__, nm_setting_get_name (NM_SETTING (setting)));
- goto done;
+ if (!nm_connection_update_secrets (NM_CONNECTION (info->connection),
+ setting_name,
+ setting_hash,
+ &update_error)) {
+ g_warning ("%s: error updating connection secrets: (%d) %s",
+ __func__,
+ update_error ? update_error->code : -1,
+ update_error && update_error->message ? update_error->message : "(unknown)");
+ g_clear_error (&update_error);
+ }
+ }
}
- /* Returned secrets are a{sa{sv}}; this is the outer a{s...} hash that
- * will contain all the individual settings hashes.
- */
- settings_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, (GDestroyNotify) g_hash_table_destroy);
+ /* Now update the secret the user just entered */
+ if ( !strcmp (info->secret_name, NM_SETTING_GSM_PIN)
+ || !strcmp (info->secret_name, NM_SETTING_GSM_PASSWORD)) {
+ NMSetting *s_gsm;
+
+ s_gsm = (NMSetting *) nm_connection_get_setting (NM_CONNECTION (info->connection),
+ NM_TYPE_SETTING_GSM);
+ if (s_gsm) {
+ new_secret = gtk_entry_get_text (info->secret_entry);
+ g_object_set (G_OBJECT (s_gsm), info->secret_name, new_secret, NULL);
+ }
+ }
- g_hash_table_insert (settings_hash, g_strdup (nm_setting_get_name (NM_SETTING (setting))), secrets);
- info->callback (info->connection, settings_hash, NULL, info->callback_data);
- g_hash_table_destroy (settings_hash);
+ settings = nm_connection_to_hash (NM_CONNECTION (info->connection));
+ info->callback (info->connection, settings, NULL, info->callback_data);
+ g_hash_table_destroy (settings);
- /* Save the connection back to GConf _after_ hashing it, because
- * saving to GConf might trigger the GConf change notifiers, resulting
- * in the connection being read back in from GConf which clears secrets.
+ /* Save secrets back to GConf if the user had entered them into the
+ * connection originally. This lets users enter their secret every time if
+ * they want.
*/
- if (NMA_IS_GCONF_CONNECTION (info->connection))
+ if (new_secret && save_secret)
nm_settings_connection_interface_update (info->connection, update_cb, NULL);
done:
- if (err) {
- g_warning ("%s", err->message);
- info->callback (info->connection, NULL, err, info->callback_data);
- g_error_free (err);
+ if (error) {
+ g_warning ("%s", error->message);
+ info->callback (info->connection, NULL, error, info->callback_data);
+ g_clear_error (&error);
}
nm_connection_clear_secrets (NM_CONNECTION (info->connection));
destroy_gsm_dialog (info, NULL);
}
+static void
+get_gsm_secrets_cb (GtkDialog *dialog,
+ gint response,
+ gpointer user_data)
+{
+ NMGsmInfo *info = (NMGsmInfo *) user_data;
+ GError *error = NULL;
+
+ /* Got a user response, clear the NMActiveConnection destroy handler for
+ * this dialog since this function will now take over dialog destruction.
+ */
+ g_object_weak_unref (G_OBJECT (info->active_connection), destroy_gsm_dialog, info);
+
+ if (response == GTK_RESPONSE_OK) {
+ const char *hints[2] = { info->secret_name, NULL };
+
+ /* Get existing connection secrets since NM will want those too */
+ if (!nm_settings_connection_interface_get_secrets (info->connection,
+ NM_SETTING_GSM_SETTING_NAME,
+ (const char **) &hints,
+ FALSE,
+ get_existing_secrets_cb,
+ info)) {
+ g_set_error (&error,
+ NM_SETTINGS_INTERFACE_ERROR,
+ NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR,
+ "%s.%d (%s): failed to get existing connection secrets",
+ __FILE__, __LINE__, __func__);
+ }
+ } else {
+ g_set_error (&error,
+ NM_SETTINGS_INTERFACE_ERROR,
+ NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR,
+ "%s.%d (%s): canceled",
+ __FILE__, __LINE__, __func__);
+ }
+
+ if (error) {
+ g_warning ("%s", error->message);
+ info->callback (info->connection, NULL, error, info->callback_data);
+ g_error_free (error);
+
+ nm_connection_clear_secrets (NM_CONNECTION (info->connection));
+ destroy_gsm_dialog (info, NULL);
+ }
+}
+
static GtkWidget *
ask_for_pin_puk (NMDevice *device,
NMConnection *connection,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]