[network-manager-applet/rm-userset] applet: implement agent API for secrets handling
- From: Dan Williams <dcbw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [network-manager-applet/rm-userset] applet: implement agent API for secrets handling
- Date: Wed, 19 Jan 2011 01:23:03 +0000 (UTC)
commit 203d74540d39682761328e7e75ab96c517e84f96
Author: Dan Williams <dcbw redhat com>
Date: Tue Jan 18 17:20:32 2011 -0600
applet: implement agent API for secrets handling
Still a number of issues to work out, but it compiles.
src/Makefile.am | 4 +-
src/applet-agent.c | 563 ++++++++++++++++++++++++++++++++++++-
src/applet-agent.h | 20 ++
src/applet-device-bt.c | 148 +++-------
src/applet-device-cdma.c | 131 +++------
src/applet-device-gsm.c | 243 +++++------------
src/applet-device-wifi.c | 104 ++------
src/applet-device-wired.c | 371 +++++++-----------------
src/applet-dialogs.c | 10 +-
src/applet-dialogs.h | 3 +-
src/applet-vpn-request.c | 377 +++++++++++++++++++++++++
src/applet-vpn-request.h | 58 ++++
src/applet.c | 366 +++++++++++++++++++-----
src/applet.h | 46 +++-
src/gconf-helpers/gconf-helpers.c | 24 +--
src/marshallers/nma-marshal.list | 3 +-
src/utils/utils.c | 45 +++-
src/utils/utils.h | 14 +-
src/vpn-password-dialog.c | 334 ----------------------
src/vpn-password-dialog.h | 35 ---
src/wired-dialog.c | 19 +-
src/wired-dialog.h | 12 +-
22 files changed, 1699 insertions(+), 1231 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 5c8e043..18cea49 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -27,8 +27,8 @@ nm_applet_SOURCES = \
applet.h \
applet-agent.c \
applet-agent.h \
- vpn-password-dialog.c \
- vpn-password-dialog.h \
+ applet-vpn-request.c \
+ applet-vpn-request.h \
wired-dialog.h \
wired-dialog.c \
wireless-dialog.h \
diff --git a/src/applet-agent.c b/src/applet-agent.c
index c95d220..e342e5f 100644
--- a/src/applet-agent.c
+++ b/src/applet-agent.c
@@ -25,38 +25,507 @@
#include <glib/gi18n.h>
#include <string.h>
+#include <gnome-keyring.h>
+#include <dbus/dbus-glib.h>
+#include <nm-setting-connection.h>
+#include <nm-setting-8021x.h>
+#include <nm-setting-vpn.h>
#include "applet-agent.h"
+#include "utils.h"
+#include "nma-marshal.h"
+#include "gconf-helpers.h"
G_DEFINE_TYPE (AppletAgent, applet_agent, NM_TYPE_SECRET_AGENT);
#define APPLET_AGENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), APPLET_TYPE_AGENT, AppletAgentPrivate))
typedef struct {
-
+ GHashTable *requests;
gboolean disposed;
} AppletAgentPrivate;
+enum {
+ GET_SECRETS,
+ CANCEL_SECRETS,
+ LAST_SIGNAL
+};
+static guint signals[LAST_SIGNAL] = { 0 };
+
+
+/*******************************************************/
+
+static const char *applet_8021x_cert_keys[] = {
+ "ca-cert",
+ "client-cert",
+ "private-key",
+ "phase2-ca-cert",
+ "phase2-client-cert",
+ "phase2-private-key",
+ NULL
+};
+
+static gboolean
+string_in_list (const char *str, const char **valid_strings)
+{
+ int i;
+
+ for (i = 0; valid_strings[i]; i++) {
+ if (!g_strcmp0 (str, valid_strings[i]))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*******************************************************/
+
+#define DBUS_TYPE_G_MAP_OF_STRING (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING))
+
+typedef struct {
+ guint id;
+
+ NMSecretAgent *agent;
+ NMConnection *connection;
+ char *path;
+ char *setting_name;
+ char **hints;
+ guint32 flags;
+ NMSecretAgentGetSecretsFunc get_callback;
+ NMSecretAgentSaveSecretsFunc save_callback;
+ NMSecretAgentDeleteSecretsFunc delete_callback;
+ gpointer callback_data;
+
+ gpointer keyring_id;
+ guint32 op_count;
+ gboolean canceled;
+} Request;
+
+static Request *
+request_new (NMSecretAgent *agent,
+ NMConnection *connection,
+ const char *connection_path,
+ const char *setting_name,
+ const char **hints,
+ guint32 flags,
+ NMSecretAgentGetSecretsFunc get_callback,
+ NMSecretAgentSaveSecretsFunc save_callback,
+ NMSecretAgentDeleteSecretsFunc delete_callback,
+ gpointer callback_data)
+{
+ static guint32 counter = 1;
+ Request *r;
+
+ r = g_slice_new0 (Request);
+ r->id = counter++;
+ r->connection = g_object_ref (connection);
+ r->path = g_strdup (connection_path);
+ r->setting_name = g_strdup (setting_name);
+ if (hints)
+ r->hints = g_strdupv ((gchar **) hints);
+ r->flags = flags;
+ r->get_callback = get_callback;
+ r->save_callback = save_callback;
+ r->delete_callback = delete_callback;
+ r->callback_data = callback_data;
+ return r;
+}
+
+static void
+request_free (Request *r)
+{
+ if (r->canceled == FALSE)
+ g_hash_table_remove (APPLET_AGENT_GET_PRIVATE (r->agent)->requests, GUINT_TO_POINTER (r->id));
+
+ g_object_unref (r->connection);
+ g_free (r->path);
+ g_free (r->setting_name);
+ g_strfreev (r->hints);
+ memset (r, 0, sizeof (*r));
+ g_slice_free (Request, r);
+}
+
/*******************************************************/
static void
+get_secrets_cb (AppletAgent *self,
+ GHashTable *secrets,
+ GError *error,
+ gpointer user_data)
+{
+ Request *r = user_data;
+
+ if (r->canceled == FALSE)
+ r->get_callback (NM_SECRET_AGENT (r->agent), r->connection, error ? NULL : secrets, error, r->callback_data);
+ request_free (r);
+}
+
+static void
+ask_for_secrets (Request *r)
+{
+ /* FIXME: clear the actual NMRemoteConnection matching the requests' NMConnection */
+ nm_connection_clear_secrets (r->connection);
+
+ /* Ask the applet to get some secrets for us */
+ g_signal_emit (r->agent,
+ signals[GET_SECRETS],
+ 0,
+ r->connection,
+ r->setting_name,
+ r->hints,
+ r->flags,
+ get_secrets_cb,
+ r);
+}
+
+static gboolean
+is_otp_always_ask (NMConnection *connection)
+{
+ NMSetting8021x *s_8021x;
+ NMSettingConnection *s_con;
+ const char *uuid, *eap_method, *phase2;
+
+ s_8021x = (NMSetting8021x *) nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X);
+ if (s_8021x) {
+ gboolean can_always_ask = FALSE;
+
+ /* Check if PEAP or TTLS is used */
+ eap_method = nm_setting_802_1x_get_eap_method (s_8021x, 0);
+ s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
+ if (!strcmp (eap_method, "peap"))
+ can_always_ask = TRUE;
+ else if (!strcmp (eap_method, "ttls")) {
+ /* Now make sure the phase2 method isn't TLS */
+ phase2 = nm_setting_802_1x_get_phase2_auth (s_8021x);
+ if (phase2 && strcmp (phase2, "tls"))
+ can_always_ask = TRUE;
+ else {
+ phase2 = nm_setting_802_1x_get_phase2_autheap (s_8021x);
+ if (phase2 && strcmp (phase2, "tls"))
+ can_always_ask = TRUE;
+ }
+ }
+
+ if (can_always_ask) {
+ uuid = nm_setting_connection_get_uuid (s_con);
+ if (nm_gconf_get_8021x_password_always_ask (uuid))
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static GValue *
+string_to_gvalue (const char *str)
+{
+ GValue *val;
+
+ val = g_slice_new0 (GValue);
+ g_value_init (val, G_TYPE_STRING);
+ g_value_set_string (val, str);
+ return val;
+}
+
+static void
+destroy_gvalue (gpointer data)
+{
+ g_value_unset ((GValue *) data);
+ g_slice_free (GValue, data);
+}
+
+static void
+keyring_find_secrets_cb (GnomeKeyringResult result,
+ GList *list,
+ gpointer user_data)
+{
+ Request *r = user_data;
+ GError *error = NULL;
+ NMSettingConnection *s_con;
+ const char *connection_id = NULL;
+ GHashTable *secrets = NULL, *settings = NULL;
+ GList *iter;
+ gboolean hint_found = FALSE;
+
+ if (r->canceled) {
+ /* Callback already called by cancelation handler */
+ request_free (r);
+ return;
+ }
+
+ s_con = (NMSettingConnection *) nm_connection_get_setting (r->connection, NM_TYPE_SETTING_CONNECTION);
+ g_assert (s_con);
+ connection_id = nm_setting_connection_get_id (s_con);
+
+ if (result == GNOME_KEYRING_RESULT_CANCELLED) {
+ error = g_error_new_literal (NM_SECRET_AGENT_ERROR,
+ NM_SECRET_AGENT_ERROR_USER_CANCELED,
+ "The secrets request was canceled by the user");
+ goto done;
+ } else if (result != GNOME_KEYRING_RESULT_OK) {
+ error = g_error_new (NM_SECRET_AGENT_ERROR,
+ NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
+ "%s.%d - failed to read secrets from keyring (result %d)",
+ __FILE__, __LINE__, result);
+ goto done;
+ }
+
+ if (g_list_length (list) == 0) {
+ g_message ("No keyring secrets found for %s/%s; asking user.", connection_id, r->setting_name);
+ ask_for_secrets (r);
+ return;
+ }
+
+ secrets = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, destroy_gvalue);
+
+ /* Extract the secrets from the list of matching keyring items */
+ for (iter = list; iter != NULL; iter = g_list_next (iter)) {
+ GnomeKeyringFound *found = iter->data;
+ GnomeKeyringAttribute *attr;
+ const char *key_name = NULL;
+ int i;
+
+ for (i = 0; i < found->attributes->len; i++) {
+ attr = &(gnome_keyring_attribute_list_index (found->attributes, i));
+ if ( (strcmp (attr->name, KEYRING_SK_TAG) == 0)
+ && (attr->type == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING)) {
+
+ key_name = attr->value.string;
+ g_hash_table_insert (secrets, g_strdup (key_name), string_to_gvalue (found->secret));
+
+ /* See if this property matches a given hint */
+ if (r->hints && r->hints[0]) {
+ if (!g_strcmp0 (r->hints[0], key_name) || !g_strcmp0 (r->hints[1], key_name))
+ hint_found = TRUE;
+ }
+ break;
+ }
+ }
+ }
+
+ /* If there were hints, and none of the hints were returned by the keyring,
+ * get some new secrets.
+ */
+ if (r->hints && r->hints[0] && !hint_found) {
+ g_hash_table_destroy (secrets);
+ ask_for_secrets (r);
+ return;
+ }
+
+ /* Returned secrets are a{sa{sv}}; this is the outer a{s...} hash that
+ * will contain all the individual settings hashes.
+ */
+ settings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_hash_table_destroy);
+ g_hash_table_insert (settings, g_strdup (r->setting_name), secrets);
+
+done:
+ r->get_callback (NM_SECRET_AGENT (r->agent), r->connection, error ? NULL : settings, error, r->callback_data);
+ request_free (r);
+
+ if (settings)
+ g_hash_table_destroy (settings);
+ g_clear_error (&error);
+}
+
+static void
get_secrets (NMSecretAgent *agent,
NMConnection *connection,
const char *connection_path,
const char *setting_name,
const char **hints,
- gboolean request_new,
+ guint32 flags,
NMSecretAgentGetSecretsFunc callback,
gpointer callback_data)
{
+ AppletAgentPrivate *priv = APPLET_AGENT_GET_PRIVATE (agent);
+ Request *r;
+ GError *error = NULL;
+ NMSettingConnection *s_con;
+ NMSetting *setting;
+ const char *id;
+ const char *ctype;
+ gboolean ask = FALSE;
+
+ setting = nm_connection_get_setting_by_name (connection, setting_name);
+ if (!setting) {
+ error = g_error_new (NM_SECRET_AGENT_ERROR,
+ NM_SECRET_AGENT_ERROR_INVALID_CONNECTION,
+ "%s.%d - Connection didn't have requested setting '%s'.",
+ __FILE__, __LINE__, setting_name);
+ callback (agent, connection, NULL, error, callback_data);
+ g_error_free (error);
+ return;
+ }
+
+ s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
+ g_assert (s_con);
+ id = nm_setting_connection_get_id (s_con);
+ ctype = nm_setting_connection_get_connection_type (s_con);
+
+ if (!s_con || !id || !strlen (id) || !ctype) {
+ error = g_error_new (NM_SECRET_AGENT_ERROR,
+ NM_SECRET_AGENT_ERROR_INVALID_CONNECTION,
+ "%s.%d - Connection didn't have required '"
+ NM_SETTING_CONNECTION_SETTING_NAME
+ "' setting , or the connection name was invalid.",
+ __FILE__, __LINE__);
+ callback (agent, connection, NULL, error, callback_data);
+ g_error_free (error);
+ return;
+ }
+
+ /* Track the secrets request */
+ r = request_new (agent, connection, connection_path, setting_name, hints, flags, callback, NULL, NULL, callback_data);
+ g_hash_table_insert (priv->requests, GUINT_TO_POINTER (r->id), r);
+
+ /* VPN passwords are handled by the VPN plugin's auth dialog */
+ if (!strcmp (ctype, NM_SETTING_VPN_SETTING_NAME))
+ ask = TRUE;
+ else if (flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW) {
+ ask = TRUE;
+ g_message ("New secrets for %s/%s requested; ask the user", id, setting_name);
+ } else if ((flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION) && is_otp_always_ask (connection))
+ ask = TRUE;
+
+ /* VPN passwords are handled by the VPN plugin's auth dialog; and we always
+ * get secrets for OTP connections marked as 'always ask'.
+ */
+ if (ask)
+ ask_for_secrets (r);
+ else {
+ r->keyring_id = gnome_keyring_find_itemsv (GNOME_KEYRING_ITEM_GENERIC_SECRET,
+ keyring_find_secrets_cb,
+ r,
+ NULL,
+ KEYRING_UUID_TAG,
+ GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
+ nm_setting_connection_get_uuid (s_con),
+ KEYRING_SN_TAG,
+ GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
+ setting_name,
+ NULL);
+ }
}
+/*******************************************************/
+
static void
cancel_get_secrets (NMSecretAgent *agent,
const char *connection_path,
const char *setting_name)
{
+ AppletAgentPrivate *priv = APPLET_AGENT_GET_PRIVATE (agent);
+ GHashTableIter iter;
+ gpointer data;
+ GError *error;
+
+ error = g_error_new_literal (NM_SECRET_AGENT_ERROR,
+ NM_SECRET_AGENT_ERROR_AGENT_CANCELED,
+ "Canceled by NetworkManager");
+
+ g_hash_table_iter_init (&iter, priv->requests);
+ while (g_hash_table_iter_next (&iter, NULL, &data)) {
+ Request *r = data;
+
+ if (r->get_callback == NULL)
+ continue;
+
+ /* Cancel any matching GetSecrets call */
+ if (!g_strcmp0 (r->path, connection_path) && !g_strcmp0 (r->setting_name, setting_name)) {
+ r->canceled = TRUE;
+ if (r->keyring_id) {
+ gnome_keyring_cancel_request (r->keyring_id);
+ r->keyring_id = NULL;
+ }
+ r->get_callback (NM_SECRET_AGENT (r->agent), r->connection, NULL, error, r->callback_data);
+ g_hash_table_remove (priv->requests, GUINT_TO_POINTER (r->id));
+ }
+ }
+
+ g_error_free (error);
+}
+
+/*******************************************************/
+
+static void
+save_secret_cb (GnomeKeyringResult result, guint val, gpointer user_data)
+{
+ Request *r = user_data;
+
+ /* Only call the SaveSecrets callback and free the request when all the
+ * secrets have been saved to the keyring.
+ */
+ r->op_count--;
+ if (r->op_count == 0) {
+ r->save_callback (NM_SECRET_AGENT (r->agent), r->connection, NULL, r->callback_data);
+ request_free (r);
+ }
+}
+
+static void
+write_one_secret_to_keyring (NMSetting *setting,
+ const char *key,
+ const GValue *value,
+ GParamFlags flags,
+ gpointer user_data)
+{
+ Request *r = user_data;
+ GType type = G_VALUE_TYPE (value);
+ const char *secret;
+ const char *setting_name;
+ GnomeKeyringAttributeList *attrs;
+ char *display_name = NULL;
+
+ /* non-secrets and private key paths don't get stored in the keyring */
+ if ( !(flags & NM_SETTING_PARAM_SECRET)
+ || (NM_IS_SETTING_802_1X (setting) && string_in_list (key, applet_8021x_cert_keys)))
+ return;
+
+ /* VPN secrets are handled by the VPN plugins */
+ if ( (type == DBUS_TYPE_G_MAP_OF_STRING)
+ && NM_IS_SETTING_VPN (setting)
+ && !strcmp (key, NM_SETTING_VPN_SECRETS))
+ return;
+
+ setting_name = nm_setting_get_name (setting);
+ if (type != G_TYPE_STRING) {
+ g_warning ("Unhandled setting secret type (write) '%s/%s' : '%s'",
+ setting_name, key, g_type_name (type));
+ return;
+ }
+
+ secret = g_value_get_string (value);
+ if (!secret || !strlen (secret))
+ return;
+
+ attrs = utils_create_keyring_add_attr_list (r->connection, NULL, NULL,
+ setting_name,
+ key,
+ &display_name);
+ g_assert (attrs);
+ r->keyring_id = gnome_keyring_item_create (NULL,
+ GNOME_KEYRING_ITEM_GENERIC_SECRET,
+ display_name,
+ attrs,
+ secret,
+ TRUE,
+ save_secret_cb,
+ r,
+ NULL);
+ r->op_count++;
+ gnome_keyring_attribute_list_free (attrs);
+ g_free (display_name);
+}
+
+static void
+save_delete_cb (NMSecretAgent *agent,
+ NMConnection *connection,
+ GError *error,
+ gpointer user_data)
+{
+ Request *r = user_data;
+
+ /* Ignore errors; now save all new secrets */
+ nm_connection_for_each_setting_value (connection, write_one_secret_to_keyring, r);
}
static void
@@ -66,6 +535,40 @@ save_secrets (NMSecretAgent *agent,
NMSecretAgentSaveSecretsFunc callback,
gpointer callback_data)
{
+ AppletAgentPrivate *priv = APPLET_AGENT_GET_PRIVATE (agent);
+ Request *r;
+
+ r = request_new (agent, connection, connection_path, NULL, NULL, FALSE, NULL, callback, NULL, callback_data);
+ g_hash_table_insert (priv->requests, GUINT_TO_POINTER (r->id), r);
+
+ /* First delete any existing items in the keyring */
+ nm_secret_agent_delete_secrets (agent, connection, save_delete_cb, r);
+}
+
+/*******************************************************/
+
+static void
+delete_find_items_cb (GnomeKeyringResult result, GList *list, gpointer data)
+{
+ Request *r = data;
+ GList *iter;
+ GError *error = NULL;
+
+ if (result == GNOME_KEYRING_RESULT_OK) {
+ for (iter = list; iter != NULL; iter = g_list_next (iter)) {
+ GnomeKeyringFound *found = (GnomeKeyringFound *) iter->data;
+
+ gnome_keyring_item_delete (found->keyring, found->item_id, NULL, NULL, NULL);
+ }
+ } else {
+ error = g_error_new (NM_SECRET_AGENT_ERROR,
+ NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
+ "The request could not be completed. Keyring result: %d",
+ result);
+ }
+
+ r->delete_callback (r->agent, r->connection, error, r->callback_data);
+ request_free (r);
}
static void
@@ -75,6 +578,27 @@ delete_secrets (NMSecretAgent *agent,
NMSecretAgentDeleteSecretsFunc callback,
gpointer callback_data)
{
+ AppletAgentPrivate *priv = APPLET_AGENT_GET_PRIVATE (agent);
+ Request *r;
+ NMSettingConnection *s_con;
+ const char *uuid;
+
+ r = request_new (agent, connection, connection_path, NULL, NULL, FALSE, NULL, NULL, callback, callback_data);
+ g_hash_table_insert (priv->requests, GUINT_TO_POINTER (r->id), r);
+
+ s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
+ g_assert (s_con);
+ uuid = nm_setting_connection_get_uuid (s_con);
+ g_assert (uuid);
+
+ r->keyring_id = gnome_keyring_find_itemsv (GNOME_KEYRING_ITEM_GENERIC_SECRET,
+ delete_find_items_cb,
+ r,
+ NULL,
+ KEYRING_UUID_TAG,
+ GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
+ uuid,
+ NULL);
}
/*******************************************************/
@@ -90,6 +614,9 @@ applet_agent_new (void)
static void
applet_agent_init (AppletAgent *self)
{
+ AppletAgentPrivate *priv = APPLET_AGENT_GET_PRIVATE (self);
+
+ priv->requests = g_hash_table_new (g_direct_hash, g_direct_equal);
}
static void
@@ -99,6 +626,18 @@ dispose (GObject *object)
AppletAgentPrivate *priv = APPLET_AGENT_GET_PRIVATE (self);
if (!priv->disposed) {
+ GHashTableIter iter;
+ gpointer data;
+
+ /* Mark any outstanding requests as canceled */
+ g_hash_table_iter_init (&iter, priv->requests);
+ while (g_hash_table_iter_next (&iter, NULL, &data)) {
+ Request *r = data;
+
+ r->canceled = TRUE;
+ }
+
+ g_hash_table_destroy (priv->requests);
priv->disposed = TRUE;
}
@@ -119,5 +658,25 @@ applet_agent_class_init (AppletAgentClass *agent_class)
parent_class->cancel_get_secrets = cancel_get_secrets;
parent_class->save_secrets = save_secrets;
parent_class->delete_secrets = delete_secrets;
+
+ /* Signals */
+ signals[GET_SECRETS] =
+ g_signal_new (APPLET_AGENT_GET_SECRETS,
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (AppletAgentClass, get_secrets),
+ NULL, NULL,
+ nma_marshal_VOID__POINTER_POINTER_STRING_POINTER_BOOLEAN_POINTER_POINTER,
+ G_TYPE_NONE, 7,
+ G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_BOOLEAN, G_TYPE_POINTER, G_TYPE_POINTER);
+
+ signals[CANCEL_SECRETS] =
+ g_signal_new (APPLET_AGENT_CANCEL_SECRETS,
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (AppletAgentClass, cancel_secrets),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1, G_TYPE_POINTER);
}
diff --git a/src/applet-agent.h b/src/applet-agent.h
index 5b29417..6e8af97 100644
--- a/src/applet-agent.h
+++ b/src/applet-agent.h
@@ -31,12 +31,32 @@
#define APPLET_IS_AGENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), APPLET_TYPE_AGENT))
#define APPLET_AGENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), APPLET_TYPE_AGENT, AppletAgentClass))
+#define APPLET_AGENT_GET_SECRETS "get-secrets"
+#define APPLET_AGENT_CANCEL_SECRETS "cancel-secrets"
+
typedef struct {
NMSecretAgent parent;
} AppletAgent;
+typedef void (*AppletAgentSecretsCallback) (AppletAgent *self,
+ GHashTable *secrets,
+ GError *error,
+ gpointer user_data);
+
typedef struct {
NMSecretAgentClass parent_class;
+
+ void (*get_secrets) (AppletAgent *self,
+ void *request_id,
+ NMConnection *connection,
+ const char *setting_name,
+ const char **hints,
+ guint32 flags,
+ AppletAgentSecretsCallback callback,
+ gpointer callback_data);
+
+ void (*cancel_secrets) (AppletAgent *self,
+ void *request_id);
} AppletAgentClass;
diff --git a/src/applet-device-bt.c b/src/applet-device-bt.c
index b5bbc5e..4e0caee 100644
--- a/src/applet-device-bt.c
+++ b/src/applet-device-bt.c
@@ -252,29 +252,22 @@ bt_get_icon (NMDevice *device,
}
typedef struct {
- NMANewSecretsRequestedFunc callback;
- gpointer callback_data;
- NMApplet *applet;
- NMRemoteConnection *connection;
- NMActiveConnection *active_connection;
+ SecretsRequest req;
GtkWidget *dialog;
GtkEntry *secret_entry;
char *secret_name;
- char *setting_name;
} NMBtSecretsInfo;
static void
-destroy_secrets_dialog (gpointer user_data, GObject *finalized)
+free_bt_secrets_info (SecretsRequest *req)
{
- NMBtSecretsInfo *info = user_data;
-
- gtk_widget_hide (info->dialog);
- gtk_widget_destroy (info->dialog);
+ NMBtSecretsInfo *info = (NMBtSecretsInfo *) req;
- g_object_unref (info->connection);
+ if (info->dialog) {
+ gtk_widget_hide (info->dialog);
+ gtk_widget_destroy (info->dialog);
+ }
g_free (info->secret_name);
- g_free (info->setting_name);
- g_free (info);
}
static void
@@ -282,92 +275,55 @@ get_bt_secrets_cb (GtkDialog *dialog,
gint response,
gpointer user_data)
{
- NMBtSecretsInfo *info = user_data;
+ SecretsRequest *req = user_data;
+ NMBtSecretsInfo *info = (NMBtSecretsInfo *) req;
NMSetting *setting;
- GHashTable *settings_hash = NULL;
- GHashTable *secrets;
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_secrets_dialog, info);
-
- if (response != GTK_RESPONSE_OK) {
+ if (response == GTK_RESPONSE_OK) {
+ setting = nm_connection_get_setting_by_name (req->connection, req->setting_name);
+ if (setting) {
+ /* Normally we'd want to get all the settings's secrets and return those
+ * to NM too (since NM wants them), but since the only other secrets for 3G
+ * connections are PINs, and since the phone obviously has to be unlocked
+ * to even make the Bluetooth connection, we can skip doing that here for
+ * Bluetooth devices.
+ */
+
+ /* Update the password */
+ g_object_set (G_OBJECT (setting),
+ info->secret_name, gtk_entry_get_text (info->secret_entry),
+ NULL);
+ } else {
+ g_set_error (&error,
+ NM_SECRET_AGENT_ERROR,
+ NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
+ "%s.%d (%s): unhandled setting '%s'",
+ __FILE__, __LINE__, __func__, req->setting_name);
+ }
+ } else {
g_set_error (&error,
NM_SECRET_AGENT_ERROR,
NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
"%s.%d (%s): canceled",
__FILE__, __LINE__, __func__);
- goto done;
- }
-
- setting = nm_connection_get_setting_by_name (NM_CONNECTION (info->connection), info->setting_name);
- if (!setting) {
- g_set_error (&error,
- NM_SECRET_AGENT_ERROR,
- NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
- "%s.%d (%s): unhandled setting '%s'",
- __FILE__, __LINE__, __func__, info->setting_name);
- goto done;
- }
-
- /* Normally we'd want to get all the settings's secrets and return those
- * to NM too (since NM wants them), but since the only other secrets for 3G
- * connections are PINs, and since the phone obviously has to be unlocked
- * to even make the Bluetooth connection, we can skip doing that here for
- * Bluetooth devices.
- */
-
- /* Update the password */
- g_object_set (G_OBJECT (setting),
- info->secret_name, gtk_entry_get_text (info->secret_entry),
- NULL);
-
- secrets = nm_setting_to_hash (NM_SETTING (setting));
- if (!secrets) {
- g_set_error (&error,
- NM_SECRET_AGENT_ERROR,
- NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
- "%s.%d (%s): failed to hash setting '%s'.",
- __FILE__, __LINE__, __func__,
- nm_setting_get_name (NM_SETTING (setting)));
- goto done;
}
- /* 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);
- g_hash_table_insert (settings_hash, g_strdup (nm_setting_get_name (NM_SETTING (setting))), secrets);
-
- done:
- info->callback (info->connection, settings_hash, error, info->callback_data);
- if (settings_hash)
- g_hash_table_destroy (settings_hash);
+ applet_secrets_request_complete_setting (req, req->setting_name, error);
+ applet_secrets_request_free (req);
g_clear_error (&error);
-
- nm_connection_clear_secrets (NM_CONNECTION (info->connection));
- destroy_secrets_dialog (info, NULL);
}
static gboolean
-bt_get_secrets (NMDevice *device,
- NMRemoteConnection *connection,
- NMActiveConnection *active_connection,
- const char *setting_name,
- const char **hints,
- NMANewSecretsRequestedFunc callback,
- gpointer callback_data,
- NMApplet *applet,
- GError **error)
+bt_get_secrets (SecretsRequest *req, GError **error)
{
- NMBtSecretsInfo *info;
+ NMBtSecretsInfo *info = (NMBtSecretsInfo *) req;
GtkWidget *widget;
GtkEntry *secret_entry = NULL;
- if (!hints || !g_strv_length ((char **) hints)) {
+ applet_secrets_request_set_free_func (req, free_bt_secrets_info);
+
+ if (!req->hints || !g_strv_length (req->hints)) {
g_set_error (error,
NM_SECRET_AGENT_ERROR,
NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
@@ -375,18 +331,21 @@ bt_get_secrets (NMDevice *device,
__FILE__, __LINE__, __func__);
return FALSE;
}
+ info->secret_name = g_strdup (req->hints[0]);
- if ( (!strcmp (setting_name, NM_SETTING_CDMA_SETTING_NAME) && !strcmp (hints[0], NM_SETTING_CDMA_PASSWORD))
- || (!strcmp (setting_name, NM_SETTING_GSM_SETTING_NAME) && !strcmp (hints[0], NM_SETTING_GSM_PASSWORD)))
- widget = applet_mobile_password_dialog_new (device, NM_CONNECTION (connection), &secret_entry);
+ if ( (!strcmp (req->setting_name, NM_SETTING_CDMA_SETTING_NAME) && !strcmp (info->secret_name, NM_SETTING_CDMA_PASSWORD))
+ || (!strcmp (req->setting_name, NM_SETTING_GSM_SETTING_NAME) && !strcmp (info->secret_name, NM_SETTING_GSM_PASSWORD)))
+ widget = applet_mobile_password_dialog_new (req->connection, &secret_entry);
else {
g_set_error (error,
NM_SECRET_AGENT_ERROR,
NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
"%s.%d (%s): unknown secrets hint '%s'.",
- __FILE__, __LINE__, __func__, hints[0]);
+ __FILE__, __LINE__, __func__, info->secret_name);
return FALSE;
}
+ info->dialog = widget;
+ info->secret_entry = secret_entry;
if (!widget || !secret_entry) {
g_set_error (error,
@@ -397,24 +356,8 @@ bt_get_secrets (NMDevice *device,
return FALSE;
}
- info = g_malloc0 (sizeof (NMBtSecretsInfo));
- info->callback = callback;
- info->callback_data = callback_data;
- info->applet = applet;
- info->active_connection = active_connection;
- info->connection = g_object_ref (connection);
- info->secret_name = g_strdup (hints[0]);
- info->setting_name = g_strdup (setting_name);
- info->dialog = widget;
- info->secret_entry = secret_entry;
-
g_signal_connect (widget, "response", G_CALLBACK (get_bt_secrets_cb), info);
- /* Attach a destroy notifier to the NMActiveConnection so we can destroy
- * the dialog when the active connection goes away.
- */
- g_object_weak_ref (G_OBJECT (active_connection), destroy_secrets_dialog, info);
-
gtk_window_set_position (GTK_WINDOW (widget), GTK_WIN_POS_CENTER_ALWAYS);
gtk_widget_realize (GTK_WIDGET (widget));
gtk_window_present (GTK_WINDOW (widget));
@@ -436,6 +379,7 @@ applet_device_bt_get_class (NMApplet *applet)
dclass->device_state_changed = bt_device_state_changed;
dclass->get_icon = bt_get_icon;
dclass->get_secrets = bt_get_secrets;
+ dclass->secrets_request_size = sizeof (NMBtSecretsInfo);
return dclass;
}
diff --git a/src/applet-device-cdma.c b/src/applet-device-cdma.c
index 7b9c7d7..a7256fb 100644
--- a/src/applet-device-cdma.c
+++ b/src/applet-device-cdma.c
@@ -450,27 +450,22 @@ cdma_get_icon (NMDevice *device,
}
typedef struct {
- NMANewSecretsRequestedFunc callback;
- gpointer callback_data;
- NMApplet *applet;
- NMRemoteConnection *connection;
- NMActiveConnection *active_connection;
+ SecretsRequest req;
GtkWidget *dialog;
GtkEntry *secret_entry;
char *secret_name;
-} NMCdmaInfo;
+} NMCdmaSecretsInfo;
static void
-destroy_cdma_dialog (gpointer user_data, GObject *finalized)
+free_cdma_secrets_info (SecretsRequest *req)
{
- NMCdmaInfo *info = user_data;
+ NMCdmaSecretsInfo *info = (NMCdmaSecretsInfo *) req;
- gtk_widget_hide (info->dialog);
- gtk_widget_destroy (info->dialog);
-
- g_object_unref (info->connection);
+ if (info->dialog) {
+ gtk_widget_hide (info->dialog);
+ gtk_widget_destroy (info->dialog);
+ }
g_free (info->secret_name);
- g_free (info);
}
static void
@@ -478,76 +473,45 @@ get_cdma_secrets_cb (GtkDialog *dialog,
gint response,
gpointer user_data)
{
- NMCdmaInfo *info = (NMCdmaInfo *) user_data;
- NMSettingCdma *setting;
- GHashTable *settings_hash = NULL;
- GHashTable *secrets;
+ SecretsRequest *req = user_data;
+ NMCdmaSecretsInfo *info = (NMCdmaSecretsInfo *) req;
+ NMSetting *setting;
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_cdma_dialog, info);
-
- if (response != GTK_RESPONSE_OK) {
- g_set_error (&error,
- NM_SECRET_AGENT_ERROR,
- NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
- "%s.%d (%s): canceled", __FILE__, __LINE__, __func__);
- goto done;
- }
-
- setting = NM_SETTING_CDMA (nm_connection_get_setting (NM_CONNECTION (info->connection), NM_TYPE_SETTING_CDMA));
-
- if (!strcmp (info->secret_name, NM_SETTING_CDMA_PASSWORD)) {
- g_object_set (setting,
- NM_SETTING_CDMA_PASSWORD, gtk_entry_get_text (info->secret_entry),
- NULL);
- }
-
- secrets = nm_setting_to_hash (NM_SETTING (setting));
- if (!secrets) {
- g_set_error (&error,
- NM_SECRET_AGENT_ERROR,
- NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
- "%s.%d (%s): failed to hash setting '%s'.",
- __FILE__, __LINE__, __func__, nm_setting_get_name (NM_SETTING (setting)));
- goto done;
+ if (response == GTK_RESPONSE_OK) {
+ setting = nm_connection_get_setting (req->connection, NM_TYPE_SETTING_CDMA);
+ if (setting) {
+ g_object_set (G_OBJECT (setting),
+ info->secret_name, gtk_entry_get_text (info->secret_entry),
+ NULL);
+ } else {
+ error = g_error_new (NM_SECRET_AGENT_ERROR,
+ NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
+ "%s.%d (%s): no GSM setting",
+ __FILE__, __LINE__, __func__);
+ }
+ } else {
+ error = g_error_new (NM_SECRET_AGENT_ERROR,
+ NM_SECRET_AGENT_ERROR_USER_CANCELED,
+ "%s.%d (%s): canceled",
+ __FILE__, __LINE__, __func__);
}
- /* 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);
- g_hash_table_insert (settings_hash, g_strdup (nm_setting_get_name (NM_SETTING (setting))), secrets);
-
- done:
- info->callback (info->connection, settings_hash, error, info->callback_data);
- if (settings_hash)
- g_hash_table_destroy (settings_hash);
+ applet_secrets_request_complete_setting (req, NM_SETTING_CDMA_SETTING_NAME, error);
+ applet_secrets_request_free (req);
g_clear_error (&error);
-
- nm_connection_clear_secrets (NM_CONNECTION (info->connection));
- destroy_cdma_dialog (info, NULL);
}
static gboolean
-cdma_get_secrets (NMDevice *device,
- NMRemoteConnection *connection,
- NMActiveConnection *active_connection,
- const char *setting_name,
- const char **hints,
- NMANewSecretsRequestedFunc callback,
- gpointer callback_data,
- NMApplet *applet,
- GError **error)
+cdma_get_secrets (SecretsRequest *req, GError **error)
{
- NMCdmaInfo *info;
+ NMCdmaSecretsInfo *info = (NMCdmaSecretsInfo *) req;
GtkWidget *widget;
GtkEntry *secret_entry = NULL;
- if (!hints || !g_strv_length ((char **) hints)) {
+ applet_secrets_request_set_free_func (req, free_cdma_secrets_info);
+
+ if (!req->hints || !g_strv_length (req->hints)) {
g_set_error (error,
NM_SECRET_AGENT_ERROR,
NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
@@ -555,17 +519,20 @@ cdma_get_secrets (NMDevice *device,
__FILE__, __LINE__, __func__);
return FALSE;
}
+ info->secret_name = g_strdup (req->hints[0]);
- if (!strcmp (hints[0], NM_SETTING_CDMA_PASSWORD))
- widget = applet_mobile_password_dialog_new (device, NM_CONNECTION (connection), &secret_entry);
+ if (!strcmp (info->secret_name, NM_SETTING_CDMA_PASSWORD))
+ widget = applet_mobile_password_dialog_new (req->connection, &secret_entry);
else {
g_set_error (error,
NM_SECRET_AGENT_ERROR,
NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
"%s.%d (%s): unknown secrets hint '%s'.",
- __FILE__, __LINE__, __func__, hints[0]);
+ __FILE__, __LINE__, __func__, info->secret_name);
return FALSE;
}
+ info->dialog = widget;
+ info->secret_entry = secret_entry;
if (!widget || !secret_entry) {
g_set_error (error,
@@ -576,23 +543,8 @@ cdma_get_secrets (NMDevice *device,
return FALSE;
}
- info = g_new (NMCdmaInfo, 1);
- info->callback = callback;
- info->callback_data = callback_data;
- info->applet = applet;
- info->active_connection = active_connection;
- info->connection = g_object_ref (connection);
- info->secret_name = g_strdup (hints[0]);
- info->dialog = widget;
- info->secret_entry = secret_entry;
-
g_signal_connect (widget, "response", G_CALLBACK (get_cdma_secrets_cb), info);
- /* Attach a destroy notifier to the NMActiveConnection so we can destroy
- * the dialog when the active connection goes away.
- */
- g_object_weak_ref (G_OBJECT (active_connection), destroy_cdma_dialog, info);
-
gtk_window_set_position (GTK_WINDOW (widget), GTK_WIN_POS_CENTER_ALWAYS);
gtk_widget_realize (GTK_WIDGET (widget));
gtk_window_present (GTK_WINDOW (widget));
@@ -969,6 +921,7 @@ applet_device_cdma_get_class (NMApplet *applet)
dclass->device_state_changed = cdma_device_state_changed;
dclass->get_icon = cdma_get_icon;
dclass->get_secrets = cdma_get_secrets;
+ dclass->secrets_request_size = sizeof (NMCdmaSecretsInfo);
dclass->device_added = cdma_device_added;
return dclass;
diff --git a/src/applet-device-gsm.c b/src/applet-device-gsm.c
index 33b4746..51a62a3 100644
--- a/src/applet-device-gsm.c
+++ b/src/applet-device-gsm.c
@@ -493,122 +493,24 @@ gsm_get_icon (NMDevice *device,
}
typedef struct {
- /* General stuff */
+ SecretsRequest req;
+
GtkWidget *dialog;
GtkEntry *secret_entry;
char *secret_name;
- NMApplet *applet;
- NMANewSecretsRequestedFunc callback;
- gpointer callback_data;
- NMActiveConnection *active_connection;
- NMRemoteConnection *connection;
} NMGsmSecretsInfo;
-
-static void
-secrets_dialog_destroy (gpointer user_data, GObject *finalized)
-{
- NMGsmSecretsInfo *info = user_data;
-
- gtk_widget_hide (info->dialog);
- gtk_widget_destroy (info->dialog);
-
- g_object_unref (info->connection);
- g_free (info->secret_name);
- g_free (info);
-}
-
static void
-get_existing_secrets_cb (NMSecretAgent *agent,
- NMConnection *connection,
- GHashTable *existing_secrets,
- GError *secrets_error,
- gpointer user_data)
+free_gsm_secrets_info (SecretsRequest *req)
{
- NMGsmSecretsInfo *info = (NMGsmSecretsInfo *) user_data;
- GHashTable *settings_hash = NULL;
- GError *error = NULL;
- gboolean save_secret = FALSE;
- const char *new_secret = NULL;
-
- if (secrets_error) {
- error = g_error_copy (secrets_error);
- goto done;
- }
-
- /* Be a bit paranoid */
- if (NM_REMOTE_CONNECTION (connection) != info->connection) {
- g_set_error (&error,
- NM_SECRET_AGENT_ERROR,
- NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
- "%s.%d (%s): unexpected reply for wrong connection.",
- __FILE__, __LINE__, __func__);
- goto done;
- }
-
- /* 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 originally 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;
- }
-
- 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);
- }
- }
- }
-
- /* 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;
+ NMGsmSecretsInfo *info = (NMGsmSecretsInfo *) req;
- 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);
- }
- }
-
- settings_hash = nm_connection_to_hash (NM_CONNECTION (info->connection));
-
- done:
- info->callback (info->connection, settings_hash, error, info->callback_data);
- if (settings_hash)
- g_hash_table_destroy (settings_hash);
- g_clear_error (&error);
-
- /* 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 (new_secret && save_secret) {
- /* FIXME: save secret back to the keyring */
+ if (info->dialog) {
+ gtk_widget_hide (info->dialog);
+ gtk_widget_destroy (info->dialog);
}
- nm_connection_clear_secrets (NM_CONNECTION (info->connection));
- secrets_dialog_destroy (info, NULL);
+ g_free (info->secret_name);
}
static void
@@ -616,39 +518,33 @@ get_gsm_secrets_cb (GtkDialog *dialog,
gint response,
gpointer user_data)
{
- NMGsmSecretsInfo *info = (NMGsmSecretsInfo *) user_data;
+ SecretsRequest *req = user_data;
+ NMGsmSecretsInfo *info = (NMGsmSecretsInfo *) req;
+ NMSetting *setting;
GError *error = NULL;
- const char *hints[2] = { info->secret_name, 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), secrets_dialog_destroy, info);
-
- if (response != GTK_RESPONSE_OK) {
- g_set_error (&error,
- NM_SECRET_AGENT_ERROR,
- NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
- "%s.%d (%s): canceled",
- __FILE__, __LINE__, __func__);
- 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));
- secrets_dialog_destroy (info, NULL);
- return;
+ if (response == GTK_RESPONSE_OK) {
+ setting = nm_connection_get_setting (req->connection, NM_TYPE_SETTING_GSM);
+ if (setting) {
+ g_object_set (G_OBJECT (setting),
+ info->secret_name, gtk_entry_get_text (info->secret_entry),
+ NULL);
+ } else {
+ error = g_error_new (NM_SECRET_AGENT_ERROR,
+ NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
+ "%s.%d (%s): no GSM setting",
+ __FILE__, __LINE__, __func__);
+ }
+ } else {
+ error = g_error_new (NM_SECRET_AGENT_ERROR,
+ NM_SECRET_AGENT_ERROR_USER_CANCELED,
+ "%s.%d (%s): canceled",
+ __FILE__, __LINE__, __func__);
}
- /* Get existing connection secrets since NM will want those too */
- nm_secret_agent_get_secrets (NM_SECRET_AGENT (info->applet->agent),
- NM_CONNECTION (info->connection),
- NM_SETTING_GSM_SETTING_NAME,
- (const char **) &hints,
- FALSE,
- get_existing_secrets_cb,
- info);
+ applet_secrets_request_complete_setting (req, NM_SETTING_GSM_SETTING_NAME, error);
+ applet_secrets_request_free (req);
+ g_clear_error (&error);
}
static void
@@ -678,12 +574,11 @@ pin_entry_changed (GtkEditable *editable, gpointer user_data)
}
static GtkWidget *
-ask_for_pin (NMDevice *device, GtkEntry **out_secret_entry)
+ask_for_pin (GtkEntry **out_secret_entry)
{
GtkDialog *dialog;
GtkWidget *w = NULL, *ok_button = NULL;
GtkBox *box = NULL, *vbox = NULL;
- char *dev_str;
dialog = GTK_DIALOG (gtk_dialog_new ());
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
@@ -698,12 +593,6 @@ ask_for_pin (NMDevice *device, GtkEntry **out_secret_entry)
w = gtk_label_new (_("PIN code is needed for the mobile broadband device"));
gtk_box_pack_start (vbox, w, TRUE, TRUE, 0);
- dev_str = g_strdup_printf ("<b>%s</b>", utils_get_device_description (device));
- w = gtk_label_new (NULL);
- gtk_label_set_markup (GTK_LABEL (w), dev_str);
- g_free (dev_str);
- gtk_box_pack_start (vbox, w, TRUE, TRUE, 0);
-
w = gtk_alignment_new (0.5, 0.5, 0, 1.0);
gtk_box_pack_start (vbox, w, TRUE, TRUE, 0);
@@ -728,21 +617,15 @@ ask_for_pin (NMDevice *device, GtkEntry **out_secret_entry)
}
static gboolean
-gsm_get_secrets (NMDevice *device,
- NMRemoteConnection *connection,
- NMActiveConnection *active_connection,
- const char *setting_name,
- const char **hints,
- NMANewSecretsRequestedFunc callback,
- gpointer callback_data,
- NMApplet *applet,
- GError **error)
+gsm_get_secrets (SecretsRequest *req, GError **error)
{
- NMGsmSecretsInfo *secrets_info;
+ NMGsmSecretsInfo *info = (NMGsmSecretsInfo *) req;
GtkWidget *widget;
GtkEntry *secret_entry = NULL;
- if (!hints || !g_strv_length ((char **) hints)) {
+ applet_secrets_request_set_free_func (req, free_gsm_secrets_info);
+
+ if (!req->hints || !g_strv_length (req->hints)) {
g_set_error (error,
NM_SECRET_AGENT_ERROR,
NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
@@ -750,26 +633,42 @@ gsm_get_secrets (NMDevice *device,
__FILE__, __LINE__, __func__);
return FALSE;
}
+ info->secret_name = g_strdup (req->hints[0]);
+
+ if (!strcmp (info->secret_name, NM_SETTING_GSM_PIN)) {
+ NMDevice *device;
+ GsmDeviceInfo *devinfo;
+
+ device = applet_get_device_for_connection (req->applet, req->connection);
+ if (!device) {
+ g_set_error (error,
+ NM_SECRET_AGENT_ERROR,
+ NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
+ "%s.%d (%s): failed to find device for active connection.",
+ __FILE__, __LINE__, __func__);
+ return FALSE;
+ }
- if (!strcmp (hints[0], NM_SETTING_GSM_PIN)) {
- GsmDeviceInfo *info = g_object_get_data (G_OBJECT (device), "devinfo");
+ devinfo = g_object_get_data (G_OBJECT (device), "devinfo");
+ g_assert (devinfo);
- g_assert (info);
/* A GetSecrets PIN dialog overrides the initial unlock dialog */
- if (info->dialog)
- unlock_dialog_destroy (info);
+ if (devinfo->dialog)
+ unlock_dialog_destroy (devinfo);
- widget = ask_for_pin (device, &secret_entry);
- } else if (!strcmp (hints[0], NM_SETTING_GSM_PASSWORD))
- widget = applet_mobile_password_dialog_new (device, NM_CONNECTION (connection), &secret_entry);
+ widget = ask_for_pin (&secret_entry);
+ } else if (!strcmp (info->secret_name, NM_SETTING_GSM_PASSWORD))
+ widget = applet_mobile_password_dialog_new (req->connection, &secret_entry);
else {
g_set_error (error,
NM_SECRET_AGENT_ERROR,
NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
"%s.%d (%s): unknown secrets hint '%s'.",
- __FILE__, __LINE__, __func__, hints[0]);
+ __FILE__, __LINE__, __func__, info->secret_name);
return FALSE;
}
+ info->dialog = widget;
+ info->secret_entry = secret_entry;
if (!widget || !secret_entry) {
g_set_error (error,
@@ -780,22 +679,7 @@ gsm_get_secrets (NMDevice *device,
return FALSE;
}
- secrets_info = g_malloc0 (sizeof (NMGsmSecretsInfo));
- secrets_info->callback = callback;
- secrets_info->callback_data = callback_data;
- secrets_info->applet = applet;
- secrets_info->active_connection = active_connection;
- secrets_info->connection = g_object_ref (connection);
- secrets_info->secret_name = g_strdup (hints[0]);
- secrets_info->dialog = widget;
- secrets_info->secret_entry = secret_entry;
-
- g_signal_connect (widget, "response", G_CALLBACK (get_gsm_secrets_cb), secrets_info);
-
- /* Attach a destroy notifier to the NMActiveConnection so we can destroy
- * the dialog when the active connection goes away.
- */
- g_object_weak_ref (G_OBJECT (active_connection), secrets_dialog_destroy, secrets_info);
+ g_signal_connect (widget, "response", G_CALLBACK (get_gsm_secrets_cb), info);
gtk_window_set_position (GTK_WINDOW (widget), GTK_WIN_POS_CENTER_ALWAYS);
gtk_widget_realize (GTK_WIDGET (widget));
@@ -1516,6 +1400,7 @@ applet_device_gsm_get_class (NMApplet *applet)
dclass->device_state_changed = gsm_device_state_changed;
dclass->get_icon = gsm_get_icon;
dclass->get_secrets = gsm_get_secrets;
+ dclass->secrets_request_size = sizeof (NMGsmSecretsInfo);
dclass->device_added = gsm_device_added;
return dclass;
diff --git a/src/applet-device-wifi.c b/src/applet-device-wifi.c
index d2028f9..449f02e 100644
--- a/src/applet-device-wifi.c
+++ b/src/applet-device-wifi.c
@@ -1504,24 +1504,21 @@ add_one_setting (GHashTable *settings,
}
typedef struct {
- NMApplet *applet;
- NMActiveConnection *active_connection;
+ SecretsRequest req;
+
GtkWidget *dialog;
GtkWidget *nag_dialog;
- NMANewSecretsRequestedFunc callback;
- gpointer callback_data;
- char *setting_name;
} NMWifiInfo;
static void
-destroy_wifi_dialog (gpointer user_data, GObject *finalized)
+free_wifi_info (SecretsRequest *req)
{
- NMWifiInfo *info = user_data;
+ NMWifiInfo *info = (NMWifiInfo *) req;
- gtk_widget_hide (info->dialog);
- gtk_widget_destroy (info->dialog);
- g_free (info->setting_name);
- g_free (info);
+ if (info->dialog) {
+ gtk_widget_hide (info->dialog);
+ gtk_widget_destroy (info->dialog);
+ }
}
static void
@@ -1529,11 +1526,11 @@ get_secrets_dialog_response_cb (GtkDialog *foo,
gint response,
gpointer user_data)
{
- NMWifiInfo *info = user_data;
+ SecretsRequest *req = user_data;
+ NMWifiInfo *info = (NMWifiInfo *) req;
NMAWirelessDialog *dialog = NMA_WIRELESS_DIALOG (info->dialog);
NMConnection *connection = NULL;
NMSettingWirelessSecurity *s_wireless_sec;
- NMDevice *device = NULL;
GHashTable *settings = NULL;
const char *key_mgmt, *auth_alg;
GError *error = NULL;
@@ -1557,11 +1554,6 @@ get_secrets_dialog_response_cb (GtkDialog *foo,
}
}
- /* 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_wifi_dialog, info);
-
if (response != GTK_RESPONSE_OK) {
g_set_error (&error,
NM_SECRET_AGENT_ERROR,
@@ -1571,7 +1563,7 @@ get_secrets_dialog_response_cb (GtkDialog *foo,
goto done;
}
- connection = nma_wireless_dialog_get_connection (dialog, &device, NULL);
+ connection = nma_wireless_dialog_get_connection (dialog, NULL, NULL);
if (!connection) {
g_set_error (&error,
NM_SECRET_AGENT_ERROR,
@@ -1638,91 +1630,38 @@ get_secrets_dialog_response_cb (GtkDialog *foo,
}
/* Add the 802-11-wireless-security setting no matter what */
- if (!add_one_setting (settings, connection, NM_SETTING (s_wireless_sec), &error))
- goto done;
-
- info->callback (NM_REMOTE_CONNECTION (connection), settings, NULL, info->callback_data);
+ add_one_setting (settings, connection, NM_SETTING (s_wireless_sec), &error);
done:
+ applet_secrets_request_complete (req, settings, error);
+ applet_secrets_request_free (req);
+
if (settings)
g_hash_table_destroy (settings);
-
- if (error) {
- g_warning ("%s", error->message);
- info->callback (NM_REMOTE_CONNECTION (connection), NULL, error, info->callback_data);
- g_error_free (error);
- }
-
if (connection)
nm_connection_clear_secrets (connection);
-
- destroy_wifi_dialog (info, NULL);
}
static gboolean
-wireless_get_secrets (NMDevice *device,
- NMRemoteConnection *connection,
- NMActiveConnection *active_connection,
- const char *setting_name,
- const char **hints,
- NMANewSecretsRequestedFunc callback,
- gpointer callback_data,
- NMApplet *applet,
- GError **error)
+wireless_get_secrets (SecretsRequest *req, GError **error)
{
- NMWifiInfo *info;
- NMAccessPoint *ap;
- const char *specific_object;
+ NMWifiInfo *info = (NMWifiInfo *) req;
- if (!setting_name || !active_connection) {
- g_set_error (error,
- NM_SECRET_AGENT_ERROR,
- NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
- "%s.%d (%s): setting name and active connection object required",
- __FILE__, __LINE__, __func__);
- return FALSE;
- }
-
- specific_object = nm_active_connection_get_specific_object (active_connection);
- if (!specific_object) {
- g_set_error (error,
- NM_SECRET_AGENT_ERROR,
- NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
- "%s.%d (%s): could not determine AP for specific object",
- __FILE__, __LINE__, __func__);
- return FALSE;
- }
+ applet_secrets_request_set_free_func (req, free_wifi_info);
- info = g_malloc0 (sizeof (NMWifiInfo));
-
- ap = nm_device_wifi_get_access_point_by_path (NM_DEVICE_WIFI (device), specific_object);
- info->dialog = nma_wireless_dialog_new (applet, NM_CONNECTION (connection), device, ap);
+ info->dialog = nma_wireless_dialog_new (req->applet, req->connection, NULL, NULL);
if (!info->dialog) {
g_set_error (error,
NM_SECRET_AGENT_ERROR,
NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
"%s.%d (%s): couldn't display secrets UI",
__FILE__, __LINE__, __func__);
- g_free (info);
return FALSE;
}
- info->applet = applet;
- info->active_connection = active_connection;
- info->callback = callback;
- info->callback_data = callback_data;
- info->setting_name = g_strdup (setting_name);
-
- g_signal_connect (info->dialog, "response",
- G_CALLBACK (get_secrets_dialog_response_cb),
- info);
-
- /* Attach a destroy notifier to the NMActiveConnection so we can destroy
- * the dialog when the active connection goes away.
- */
- g_object_weak_ref (G_OBJECT (active_connection), destroy_wifi_dialog, info);
-
+ g_signal_connect (info->dialog, "response", G_CALLBACK (get_secrets_dialog_response_cb), info);
show_ignore_focus_stealing_prevention (info->dialog);
+
return TRUE;
}
@@ -1742,6 +1681,7 @@ applet_device_wifi_get_class (NMApplet *applet)
dclass->get_icon = wireless_get_icon;
dclass->get_more_info = wireless_get_more_info;
dclass->get_secrets = wireless_get_secrets;
+ dclass->secrets_request_size = sizeof (NMWifiInfo);
return dclass;
}
diff --git a/src/applet-device-wired.c b/src/applet-device-wired.c
index 31f0c95..43ca50b 100644
--- a/src/applet-device-wired.c
+++ b/src/applet-device-wired.c
@@ -17,7 +17,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
- * (C) Copyright 2008 Red Hat, Inc.
+ * (C) Copyright 2008 - 2011 Red Hat, Inc.
* (C) Copyright 2008 Novell, Inc.
*/
@@ -323,18 +323,13 @@ wired_get_icon (NMDevice *device,
/* PPPoE */
typedef struct {
+ SecretsRequest req;
+
+ GtkWidget *dialog;
GtkEntry *username_entry;
GtkEntry *service_entry;
GtkEntry *password_entry;
GtkWidget *ok_button;
-
- NMApplet *applet;
- NMRemoteConnection *connection;
- NMANewSecretsRequestedFunc callback;
- gpointer callback_data;
-
- GtkWidget *dialog;
- NMActiveConnection *active_connection;
} NMPppoeInfo;
static void
@@ -398,129 +393,60 @@ pppoe_update_ui (NMConnection *connection, NMPppoeInfo *info)
gtk_entry_set_text (info->password_entry, s);
}
-static NMPppoeInfo *
-pppoe_info_new (GtkBuilder *builder,
- NMApplet *applet,
- NMANewSecretsRequestedFunc callback,
- gpointer callback_data,
- NMRemoteConnection *connection,
- NMActiveConnection *active_connection)
-{
- NMPppoeInfo *info;
-
- info = g_new0 (NMPppoeInfo, 1);
-
- info->username_entry = GTK_ENTRY (GTK_WIDGET (gtk_builder_get_object (builder, "dsl_username")));
- g_signal_connect (info->username_entry, "changed", G_CALLBACK (pppoe_verify), info);
-
- info->service_entry = GTK_ENTRY (GTK_WIDGET (gtk_builder_get_object (builder, "dsl_service")));
-
- info->password_entry = GTK_ENTRY (GTK_WIDGET (gtk_builder_get_object (builder, "dsl_password")));
- g_signal_connect (info->password_entry, "changed", G_CALLBACK (pppoe_verify), info);
-
- info->applet = applet;
- info->callback = callback;
- info->callback_data = callback_data;
- info->connection = g_object_ref (connection);
- info->active_connection = active_connection;
-
- return info;
-}
-
-static void
-pppoe_info_destroy (gpointer data, GObject *destroyed_object)
-{
- NMPppoeInfo *info = (NMPppoeInfo *) data;
-
- g_object_unref (info->connection);
- g_free (info);
-}
-
static void
-destroy_pppoe_dialog (gpointer data, GObject *finalized)
+free_pppoe_info (SecretsRequest *req)
{
- NMPppoeInfo *info = data;
-
- /* When the active connection object is destroyed, try to destroy the
- * dialog too, if it's still around.
- */
- gtk_widget_hide (info->dialog);
- gtk_widget_destroy (info->dialog);
- pppoe_info_destroy (info, NULL);
-}
+ NMPppoeInfo *info = (NMPppoeInfo *) req;
-static void
-update_cb (NMRemoteConnection *connection,
- GError *error,
- gpointer user_data)
-{
- if (error)
- g_warning ("Error saving connection secrets: (%d) %s", error->code, error->message);
+ if (info->dialog) {
+ gtk_widget_hide (info->dialog);
+ gtk_widget_destroy (info->dialog);
+ }
}
static void
-get_pppoe_secrets_cb (GtkDialog *dialog,
- gint response,
- gpointer user_data)
+get_pppoe_secrets_cb (GtkDialog *dialog, gint response, gpointer user_data)
{
- NMPppoeInfo *info = (NMPppoeInfo *) user_data;
+ SecretsRequest *req = user_data;
+ NMPppoeInfo *info = (NMPppoeInfo *) req;
NMSetting *setting;
- GHashTable *settings_hash;
+ GHashTable *settings = NULL;
GHashTable *secrets;
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_pppoe_dialog, info);
-
if (response != GTK_RESPONSE_OK) {
g_set_error (&error,
- 0,
- 0,
+ NM_SECRET_AGENT_ERROR,
+ NM_SECRET_AGENT_ERROR_USER_CANCELED,
"%s.%d (%s): canceled",
__FILE__, __LINE__, __func__);
goto done;
}
- setting = nm_connection_get_setting (NM_CONNECTION (info->connection), NM_TYPE_SETTING_PPPOE);
+ setting = nm_connection_get_setting (req->connection, NM_TYPE_SETTING_PPPOE);
pppoe_update_setting (NM_SETTING_PPPOE (setting), info);
secrets = nm_setting_to_hash (setting);
if (!secrets) {
g_set_error (&error,
- 0,
- 0,
- "%s.%d (%s): failed to hash setting '%s'.",
- __FILE__, __LINE__, __func__, nm_setting_get_name (setting));
- goto done;
+ NM_SECRET_AGENT_ERROR,
+ NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
+ "%s.%d (%s): failed to hash setting " NM_SETTING_PPPOE_SETTING_NAME,
+ __FILE__, __LINE__, __func__);
+ } else {
+ /* Returned secrets are a{sa{sv}}; this is the outer a{s...} hash that
+ * will contain all the individual settings hashes.
+ */
+ settings = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) g_hash_table_destroy);
+ g_hash_table_insert (settings, NM_SETTING_PPPOE_SETTING_NAME, secrets);
}
- /* 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);
-
- g_hash_table_insert (settings_hash, g_strdup (nm_setting_get_name (setting)), secrets);
- info->callback (info->connection, settings_hash, NULL, info->callback_data);
- g_hash_table_destroy (settings_hash);
-
- /* 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.
- */
- nm_remote_connection_commit_changes (info->connection, update_cb, NULL);
-
done:
- if (error) {
- g_warning ("%s", error->message);
- info->callback (info->connection, NULL, error, info->callback_data);
- g_error_free (error);
- }
+ applet_secrets_request_complete (req, settings, error);
+ applet_secrets_request_free (req);
- nm_connection_clear_secrets (NM_CONNECTION (info->connection));
- destroy_pppoe_dialog (info, NULL);
+ if (settings)
+ g_hash_table_destroy (settings);
}
static void
@@ -535,33 +461,34 @@ show_password_toggled (GtkToggleButton *button, gpointer user_data)
}
static gboolean
-pppoe_get_secrets (NMDevice *device,
- NMRemoteConnection *connection,
- NMActiveConnection *active_connection,
- const char *setting_name,
- NMANewSecretsRequestedFunc callback,
- gpointer callback_data,
- NMApplet *applet,
- GError **error)
+pppoe_get_secrets (SecretsRequest *req, GError **error)
{
- NMPppoeInfo *info;
+ NMPppoeInfo *info = (NMPppoeInfo *) req;
GtkWidget *w;
GtkBuilder* builder;
+ GError *tmp_error = NULL;
builder = gtk_builder_new ();
- if (!gtk_builder_add_from_file (builder, UIDIR "/ce-page-dsl.ui", error))
- {
- g_warning ("Couldn't load builder file: %s", (*error)->message);
+ if (!gtk_builder_add_from_file (builder, UIDIR "/ce-page-dsl.ui", &tmp_error)) {
g_set_error (error,
- 0,
- 0,
- "%s.%d (%s): couldn't display secrets UI",
- __FILE__, __LINE__, __func__);
+ NM_SECRET_AGENT_ERROR,
+ NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
+ "%s.%d (%s): couldn't display secrets UI: %s",
+ __FILE__, __LINE__, __func__, tmp_error->message);
+ g_error_free (tmp_error);
return FALSE;
}
- info = pppoe_info_new (builder, applet, callback, callback_data, connection, active_connection);
+ applet_secrets_request_set_free_func (req, free_pppoe_info);
+
+ info->username_entry = GTK_ENTRY (gtk_builder_get_object (builder, "dsl_username"));
+ g_signal_connect (info->username_entry, "changed", G_CALLBACK (pppoe_verify), info);
+
+ info->service_entry = GTK_ENTRY (gtk_builder_get_object (builder, "dsl_service"));
+
+ info->password_entry = GTK_ENTRY (gtk_builder_get_object (builder, "dsl_password"));
+ g_signal_connect (info->password_entry, "changed", G_CALLBACK (pppoe_verify), info);
/* Create the dialog */
info->dialog = gtk_dialog_new ();
@@ -576,19 +503,12 @@ pppoe_get_secrets (NMDevice *device,
GTK_WIDGET (gtk_builder_get_object (builder, "DslPage")),
TRUE, TRUE, 0);
- pppoe_update_ui (NM_CONNECTION (connection), info);
+ pppoe_update_ui (req->connection, info);
w = GTK_WIDGET (gtk_builder_get_object (builder, "dsl_show_password"));
- g_signal_connect (G_OBJECT (w), "toggled", G_CALLBACK (show_password_toggled), info);
+ g_signal_connect (w, "toggled", G_CALLBACK (show_password_toggled), info);
- g_signal_connect (info->dialog, "response",
- G_CALLBACK (get_pppoe_secrets_cb),
- info);
-
- /* Attach a destroy notifier to the NMActiveConnection so we can destroy
- * the dialog when the active connection goes away.
- */
- g_object_weak_ref (G_OBJECT (active_connection), destroy_pppoe_dialog, info);
+ g_signal_connect (info->dialog, "response", G_CALLBACK (get_pppoe_secrets_cb), info);
gtk_window_set_position (GTK_WINDOW (info->dialog), GTK_WIN_POS_CENTER_ALWAYS);
gtk_widget_realize (info->dialog);
@@ -600,44 +520,34 @@ pppoe_get_secrets (NMDevice *device,
/* 802.1x */
typedef struct {
- NMApplet *applet;
- NMActiveConnection *active_connection;
+ SecretsRequest req;
GtkWidget *dialog;
- NMANewSecretsRequestedFunc callback;
- gpointer callback_data;
} NM8021xInfo;
static void
-destroy_8021x_dialog (gpointer user_data, GObject *finalized)
+free_8021x_info (SecretsRequest *req)
{
- NM8021xInfo *info = user_data;
+ NM8021xInfo *info = (NM8021xInfo *) req;
- gtk_widget_hide (info->dialog);
- gtk_widget_destroy (info->dialog);
- g_free (info);
+ if (info->dialog) {
+ gtk_widget_hide (info->dialog);
+ gtk_widget_destroy (info->dialog);
+ }
}
static void
-get_8021x_secrets_cb (GtkDialog *dialog,
- gint response,
- gpointer user_data)
+get_8021x_secrets_cb (GtkDialog *dialog, gint response, gpointer user_data)
{
- NM8021xInfo *info = user_data;
- NMRemoteConnection *connection = NULL;
+ SecretsRequest *req = user_data;
+ NM8021xInfo *info = (NM8021xInfo *) req;
+ NMConnection *connection = NULL;
NMSetting *setting;
- GHashTable *settings_hash;
- GHashTable *secrets;
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_8021x_dialog, info);
-
if (response != GTK_RESPONSE_OK) {
g_set_error (&error,
- 0,
- 0,
+ NM_SECRET_AGENT_ERROR,
+ NM_SECRET_AGENT_ERROR_USER_CANCELED,
"%s.%d (%s): canceled",
__FILE__, __LINE__, __func__);
goto done;
@@ -646,157 +556,87 @@ get_8021x_secrets_cb (GtkDialog *dialog,
connection = nma_wired_dialog_get_connection (info->dialog);
if (!connection) {
g_set_error (&error,
- 0,
- 0,
+ NM_SECRET_AGENT_ERROR,
+ NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
"%s.%d (%s): couldn't get connection from wired dialog.",
__FILE__, __LINE__, __func__);
goto done;
}
- setting = nm_connection_get_setting (NM_CONNECTION (connection), NM_TYPE_SETTING_802_1X);
- if (!setting) {
+ setting = nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X);
+ if (setting) {
+ nm_connection_add_setting (req->connection, g_object_ref (setting));
+ } else {
g_set_error (&error,
- 0,
- 0,
+ NM_SECRET_AGENT_ERROR,
+ NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
"%s.%d (%s): requested setting '802-1x' didn't"
" exist in the connection.",
__FILE__, __LINE__, __func__);
- goto done;
- }
-
- secrets = nm_setting_to_hash (setting);
- if (!secrets) {
- g_set_error (&error,
- 0,
- 0,
- "%s.%d (%s): failed to hash setting '%s'.",
- __FILE__, __LINE__, __func__, nm_setting_get_name (setting));
- goto done;
}
- /* 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);
-
- g_hash_table_insert (settings_hash, g_strdup (nm_setting_get_name (setting)), secrets);
- info->callback (connection, settings_hash, NULL, info->callback_data);
- g_hash_table_destroy (settings_hash);
-
- /* 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.
- */
- nm_remote_connection_commit_changes (connection, update_cb, NULL);
-
done:
- if (error) {
- g_warning ("%s", error->message);
- info->callback (connection, NULL, error, info->callback_data);
- g_error_free (error);
- }
-
- if (connection)
- nm_connection_clear_secrets (NM_CONNECTION (connection));
-
- destroy_8021x_dialog (info, NULL);
+ applet_secrets_request_complete_setting (req, NM_SETTING_802_1X_SETTING_NAME, error);
+ applet_secrets_request_free (req);
+ g_clear_error (&error);
}
static gboolean
-nm_8021x_get_secrets (NMDevice *device,
- NMRemoteConnection *connection,
- NMActiveConnection *active_connection,
- const char *setting_name,
- NMANewSecretsRequestedFunc callback,
- gpointer callback_data,
- NMApplet *applet,
- GError **error)
+nm_8021x_get_secrets (SecretsRequest *req, const char *ui_file, GError **error)
{
- GtkWidget *dialog;
- NM8021xInfo *info;
+ NM8021xInfo *info = (NM8021xInfo *) req;
+
+ applet_secrets_request_set_free_func (req, free_8021x_info);
- dialog = nma_wired_dialog_new (applet->ui_file,
- applet->nm_client,
- g_object_ref (connection),
- device);
- if (!dialog) {
+ info->dialog = nma_wired_dialog_new (ui_file, g_object_ref (req->connection));
+ if (!info->dialog) {
g_set_error (error,
- 0,
- 0,
+ NM_SECRET_AGENT_ERROR,
+ NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
"%s.%d (%s): couldn't display secrets UI",
__FILE__, __LINE__, __func__);
return FALSE;
}
- info = g_malloc0 (sizeof (NM8021xInfo));
- info->applet = applet;
- info->active_connection = active_connection;
- info->dialog = dialog;
- info->callback = callback;
- info->callback_data = callback_data;
-
- g_signal_connect (dialog, "response", G_CALLBACK (get_8021x_secrets_cb), info);
-
- /* Attach a destroy notifier to the NMActiveConnection so we can destroy
- * the dialog when the active connection goes away.
- */
- g_object_weak_ref (G_OBJECT (active_connection), destroy_8021x_dialog, info);
+ g_signal_connect (info->dialog, "response", G_CALLBACK (get_8021x_secrets_cb), info);
- gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER_ALWAYS);
- gtk_widget_realize (dialog);
- gtk_window_present (GTK_WINDOW (dialog));
+ gtk_window_set_position (GTK_WINDOW (info->dialog), GTK_WIN_POS_CENTER_ALWAYS);
+ gtk_widget_realize (info->dialog);
+ gtk_window_present (GTK_WINDOW (info->dialog));
return TRUE;
}
static gboolean
-wired_get_secrets (NMDevice *device,
- NMRemoteConnection *connection,
- NMActiveConnection *active_connection,
- const char *setting_name,
- const char **hints,
- NMANewSecretsRequestedFunc callback,
- gpointer callback_data,
- NMApplet *applet,
- GError **error)
+wired_get_secrets (SecretsRequest *req, GError **error)
{
NMSettingConnection *s_con;
- const char *connection_type;
- gboolean success = FALSE;
+ const char *ctype;
- s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (NM_CONNECTION (connection), NM_TYPE_SETTING_CONNECTION));
+ s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (req->connection, NM_TYPE_SETTING_CONNECTION));
if (!s_con) {
g_set_error (error,
- 0,
- 0,
+ NM_SECRET_AGENT_ERROR,
+ NM_SECRET_AGENT_ERROR_INVALID_CONNECTION,
"%s.%d (%s): Invalid connection",
__FILE__, __LINE__, __func__);
return FALSE;
}
- connection_type = nm_setting_connection_get_connection_type (s_con);
- if (!strcmp (connection_type, NM_SETTING_WIRED_SETTING_NAME)) {
- success = nm_8021x_get_secrets (device,
- connection,
- active_connection,
- setting_name,
- callback,
- callback_data,
- applet,
- error);
- } else if (!strcmp (connection_type, NM_SETTING_PPPOE_SETTING_NAME)) {
- success = pppoe_get_secrets (device,
- connection,
- active_connection,
- setting_name,
- callback,
- callback_data,
- applet,
- error);
+ ctype = nm_setting_connection_get_connection_type (s_con);
+ if (!strcmp (ctype, NM_SETTING_WIRED_SETTING_NAME))
+ return nm_8021x_get_secrets (req, req->applet->ui_file, error);
+ else if (!strcmp (ctype, NM_SETTING_PPPOE_SETTING_NAME))
+ return pppoe_get_secrets (req, error);
+ else {
+ g_set_error (error,
+ NM_SECRET_AGENT_ERROR,
+ NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
+ "%s.%d (%s): unhandled wired connection type '%s'",
+ __FILE__, __LINE__, __func__, ctype);
}
- return success;
+ return FALSE;
}
NMADeviceClass *
@@ -813,6 +653,7 @@ applet_device_wired_get_class (NMApplet *applet)
dclass->device_state_changed = wired_device_state_changed;
dclass->get_icon = wired_get_icon;
dclass->get_secrets = wired_get_secrets;
+ dclass->secrets_request_size = MAX (sizeof (NM8021xInfo), sizeof (NMPppoeInfo));
return dclass;
}
diff --git a/src/applet-dialogs.c b/src/applet-dialogs.c
index 4fe0a89..d2bcf51 100644
--- a/src/applet-dialogs.c
+++ b/src/applet-dialogs.c
@@ -728,14 +728,12 @@ applet_warning_dialog_show (const char *message)
}
GtkWidget *
-applet_mobile_password_dialog_new (NMDevice *device,
- NMConnection *connection,
+applet_mobile_password_dialog_new (NMConnection *connection,
GtkEntry **out_secret_entry)
{
GtkDialog *dialog;
GtkWidget *w;
GtkBox *box = NULL, *vbox = NULL;
- char *dev_str;
NMSettingConnection *s_con;
char *tmp;
const char *id;
@@ -759,12 +757,6 @@ applet_mobile_password_dialog_new (NMDevice *device,
gtk_box_pack_start (vbox, w, TRUE, TRUE, 0);
- dev_str = g_strdup_printf ("<b>%s</b>", utils_get_device_description (device));
- w = gtk_label_new (NULL);
- gtk_label_set_markup (GTK_LABEL (w), dev_str);
- g_free (dev_str);
- gtk_box_pack_start (vbox, w, TRUE, TRUE, 0);
-
w = gtk_alignment_new (0.5, 0.5, 0, 1.0);
gtk_box_pack_start (vbox, w, TRUE, TRUE, 0);
diff --git a/src/applet-dialogs.h b/src/applet-dialogs.h
index 6f22ba2..c3dbcca 100644
--- a/src/applet-dialogs.h
+++ b/src/applet-dialogs.h
@@ -33,8 +33,7 @@ void applet_about_dialog_show (NMApplet *applet);
GtkWidget *applet_warning_dialog_show (const char *message);
-GtkWidget *applet_mobile_password_dialog_new (NMDevice *device,
- NMConnection *connection,
+GtkWidget *applet_mobile_password_dialog_new (NMConnection *connection,
GtkEntry **out_secret_entry);
/******** Mobile PIN dialog ********/
diff --git a/src/applet-vpn-request.c b/src/applet-vpn-request.c
new file mode 100644
index 0000000..dbc4f94
--- /dev/null
+++ b/src/applet-vpn-request.c
@@ -0,0 +1,377 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Wireless Applet -- Display wireless access points and allow user control
+ *
+ * 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 2004 - 2011 Red Hat, Inc.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <glib.h>
+#include <unistd.h>
+
+#include "applet-vpn-request.h"
+#include "nma-marshal.h"
+#include <nm-connection.h>
+#include <nm-setting-connection.h>
+#include <nm-setting-vpn.h>
+#include <nm-secret-agent.h>
+
+G_DEFINE_TYPE (AppletVpnRequest, applet_vpn_request, G_TYPE_OBJECT)
+
+#define APPLET_VPN_REQUEST_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
+ APPLET_TYPE_VPN_REQUEST, \
+ AppletVpnRequestPrivate))
+
+typedef struct {
+ gboolean disposed;
+
+ char *bin_path;
+ char *uuid;
+ char *id;
+ char *service_type;
+
+ guint watch_id;
+ GPid pid;
+
+ GSList *lines;
+ int child_stdin;
+ int child_stdout;
+ int num_newlines;
+ GIOChannel *channel;
+ guint channel_eventid;
+} AppletVpnRequestPrivate;
+
+enum {
+ DONE,
+ LAST_SIGNAL
+};
+static guint signals[LAST_SIGNAL] = { 0 };
+
+/****************************************************************/
+
+static void
+destroy_gvalue (gpointer data)
+{
+ GValue *value = (GValue *) data;
+
+ g_value_unset (value);
+ g_slice_free (GValue, value);
+}
+
+static void
+child_finished_cb (GPid pid, gint status, gpointer user_data)
+{
+ AppletVpnRequest *self = APPLET_VPN_REQUEST (user_data);
+ AppletVpnRequestPrivate *priv = APPLET_VPN_REQUEST_GET_PRIVATE (self);
+ GError *error = NULL;
+ GHashTable *settings = NULL;
+
+ if (status == 0) {
+ GHashTable *secrets;
+ GSList *iter;
+
+ secrets = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, destroy_gvalue);
+
+ /* The length of 'lines' must be divisible by 2 since it must contain
+ * key:secret pairs with the key on one line and the associated secret
+ * on the next line.
+ */
+ for (iter = priv->lines; iter; iter = g_slist_next (iter)) {
+ GValue *val;
+
+ if (!iter->next)
+ break;
+
+ val = g_slice_new0 (GValue);
+ g_value_init (val, G_TYPE_STRING);
+ g_value_set_string (val, iter->next->data);
+
+ g_hash_table_insert (secrets, g_strdup (iter->data), val);
+ iter = iter->next;
+ }
+
+ settings = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) g_hash_table_destroy);
+ g_hash_table_insert (settings, NM_SETTING_VPN_SETTING_NAME, secrets);
+ } else {
+ error = g_error_new (NM_SECRET_AGENT_ERROR,
+ NM_SECRET_AGENT_ERROR_USER_CANCELED,
+ "%s.%d (%s): canceled", __FILE__, __LINE__, __func__);
+ }
+
+ /* Send secrets back to listeners */
+ g_signal_emit (self, signals[DONE], 0, error ? NULL : settings, error);
+
+ if (settings)
+ g_hash_table_destroy (settings);
+}
+
+static gboolean
+child_stdout_data_cb (GIOChannel *source, GIOCondition condition, gpointer user_data)
+{
+ AppletVpnRequest *self = APPLET_VPN_REQUEST (user_data);
+ AppletVpnRequestPrivate *priv = APPLET_VPN_REQUEST_GET_PRIVATE (self);
+ const char buf[1] = { 0x01 };
+ char *str;
+ int len;
+
+ if (!(condition & G_IO_IN))
+ return TRUE;
+
+ if (g_io_channel_read_line (source, &str, NULL, NULL, NULL) == G_IO_STATUS_NORMAL) {
+ len = strlen (str);
+ if (len == 1 && str[0] == '\n') {
+ /* on second line with a newline newline */
+ if (++priv->num_newlines == 2) {
+ /* terminate the child */
+ if (write (priv->child_stdin, buf, sizeof (buf)) == -1)
+ return TRUE;
+ }
+ } else if (len > 0) {
+ /* remove terminating newline */
+ str[len - 1] = '\0';
+ priv->lines = g_slist_append (priv->lines, str);
+ }
+ }
+ return TRUE;
+}
+
+static char *
+find_auth_dialog_binary (const char *service, GError **error)
+{
+ GDir *dir;
+ char *prog = NULL;
+ const char *f;
+
+ dir = g_dir_open (VPN_NAME_FILES_DIR, 0, NULL);
+ if (!dir) {
+ g_set_error (error,
+ NM_SECRET_AGENT_ERROR,
+ NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
+ "Failed to open VPN plugin file configuration directory " VPN_NAME_FILES_DIR);
+ return NULL;
+ }
+
+ while (prog == NULL && (f = g_dir_read_name (dir)) != NULL) {
+ char *path;
+ GKeyFile *keyfile;
+
+ if (!g_str_has_suffix (f, ".name"))
+ continue;
+
+ path = g_strdup_printf ("%s/%s", VPN_NAME_FILES_DIR, f);
+
+ keyfile = g_key_file_new ();
+ if (g_key_file_load_from_file (keyfile, path, 0, NULL)) {
+ char *thisservice;
+
+ thisservice = g_key_file_get_string (keyfile, "VPN Connection", "service", NULL);
+ if (g_strcmp0 (thisservice, service) == 0)
+ prog = g_key_file_get_string (keyfile, "GNOME", "auth-dialog", NULL);
+ g_free (thisservice);
+ }
+ g_key_file_free (keyfile);
+ g_free (path);
+ }
+ g_dir_close (dir);
+
+ if (prog == NULL) {
+ g_set_error (error,
+ NM_SECRET_AGENT_ERROR,
+ NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
+ "Could not find the authentication dialog for VPN connection type '%s'",
+ service);
+ } else {
+ char *prog_basename;
+
+ /* Remove any path component, then reconstruct path to the auth
+ * dialog in LIBEXECDIR.
+ */
+ prog_basename = g_path_get_basename (prog);
+ g_free (prog);
+ prog = g_strdup_printf ("%s/%s", LIBEXECDIR, prog_basename);
+ g_free (prog_basename);
+ }
+
+ return prog;
+}
+
+AppletVpnRequest *
+applet_vpn_request_new (NMConnection *connection, GError **error)
+{
+ AppletVpnRequest *self;
+ AppletVpnRequestPrivate *priv;
+ NMSettingConnection *s_con;
+ NMSettingVPN *s_vpn;
+ const char *connection_type;
+ const char *service_type;
+ char *bin_path;
+
+ s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
+ g_return_val_if_fail (s_con != NULL, FALSE);
+
+ connection_type = nm_setting_connection_get_connection_type (s_con);
+ g_return_val_if_fail (connection_type != NULL, FALSE);
+ g_return_val_if_fail (strcmp (connection_type, NM_SETTING_VPN_SETTING_NAME) == 0, FALSE);
+
+ s_vpn = NM_SETTING_VPN (nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN));
+ g_return_val_if_fail (s_vpn != NULL, FALSE);
+
+ service_type = nm_setting_vpn_get_service_type (s_vpn);
+ g_return_val_if_fail (service_type != NULL, FALSE);
+
+ /* find the auth-dialog binary */
+ bin_path = find_auth_dialog_binary (service_type, error);
+ if (!bin_path)
+ return NULL;
+
+ self = (AppletVpnRequest *) g_object_new (APPLET_TYPE_VPN_REQUEST, NULL);
+ if (self) {
+ priv = APPLET_VPN_REQUEST_GET_PRIVATE (self);
+ priv->bin_path = g_strdup (bin_path);
+ priv->uuid = g_strdup (nm_setting_connection_get_uuid (s_con));
+ priv->id = g_strdup (nm_setting_connection_get_id (s_con));
+ priv->service_type = g_strdup (service_type);
+ }
+ g_free (bin_path);
+
+ return self;
+}
+
+gboolean
+applet_vpn_request_get_secrets (AppletVpnRequest *self,
+ gboolean retry,
+ GError **error)
+{
+ AppletVpnRequestPrivate *priv = APPLET_VPN_REQUEST_GET_PRIVATE (self);
+ gboolean success;
+ const char *argv[] =
+ { priv->bin_path /*"/usr/libexec/nm-vpnc-auth-dialog"*/,
+ "-u", priv->uuid /*"2a5d52b5-95b4-4431-b96e-3dd46128f9a7"*/,
+ "-n", priv->id /*"davidznet42"*/,
+ "-s", priv->service_type /*"org.freedesktop.vpnc"*/,
+ "-r",
+ NULL
+ };
+
+ if (!retry)
+ argv[7] = NULL;
+
+ success = g_spawn_async_with_pipes (NULL, /* working_directory */
+ (gchar **) argv, /* argv */
+ NULL, /* envp */
+ G_SPAWN_DO_NOT_REAP_CHILD, /* flags */
+ NULL, /* child_setup */
+ NULL, /* user_data */
+ &priv->pid, /* child_pid */
+ &priv->child_stdin, /* standard_input */
+ &priv->child_stdout, /* standard_output */
+ NULL, /* standard_error */
+ error); /* error */
+ if (success) {
+ /* catch when child is reaped */
+ priv->watch_id = g_child_watch_add (priv->pid, child_finished_cb, self);
+
+ /* listen to what child has to say */
+ priv->channel = g_io_channel_unix_new (priv->child_stdout);
+ priv->channel_eventid = g_io_add_watch (priv->channel, G_IO_IN, child_stdout_data_cb, self);
+ g_io_channel_set_encoding (priv->channel, NULL, NULL);
+ }
+
+ return success;
+}
+
+static void
+applet_vpn_request_init (AppletVpnRequest *self)
+{
+}
+
+static gboolean
+ensure_killed (gpointer data)
+{
+ pid_t pid = GPOINTER_TO_INT (data);
+
+ if (kill (pid, 0) == 0)
+ kill (pid, SIGKILL);
+ /* ensure the child is reaped */
+ waitpid (pid, NULL, 0);
+ return FALSE;
+}
+
+static void
+dispose (GObject *object)
+{
+ AppletVpnRequest *self = APPLET_VPN_REQUEST (object);
+ AppletVpnRequestPrivate *priv = APPLET_VPN_REQUEST_GET_PRIVATE (self);
+
+ if (!priv->disposed) {
+ priv->disposed = TRUE;
+
+ g_free (priv->bin_path);
+ g_free (priv->uuid);
+ g_free (priv->id);
+ g_free (priv->service_type);
+
+ if (priv->watch_id)
+ g_source_remove (priv->watch_id);
+
+ if (priv->channel_eventid)
+ g_source_remove (priv->channel_eventid);
+ if (priv->channel)
+ g_io_channel_unref (priv->channel);
+
+ if (priv->pid) {
+ g_spawn_close_pid (priv->pid);
+ if (kill (priv->pid, SIGTERM) == 0)
+ g_timeout_add_seconds (2, ensure_killed, GINT_TO_POINTER (priv->pid));
+ else {
+ kill (priv->pid, SIGKILL);
+ /* ensure the child is reaped */
+ waitpid (priv->pid, NULL, 0);
+ }
+ }
+
+ g_slist_foreach (priv->lines, (GFunc) g_free, NULL);
+ g_slist_free (priv->lines);
+ }
+
+ G_OBJECT_CLASS (applet_vpn_request_parent_class)->dispose (object);
+}
+
+static void
+applet_vpn_request_class_init (AppletVpnRequestClass *req_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (req_class);
+
+ g_type_class_add_private (req_class, sizeof (AppletVpnRequestPrivate));
+
+ /* virtual methods */
+ object_class->dispose = dispose;
+
+ signals[DONE] =
+ g_signal_new ("done",
+ G_OBJECT_CLASS_TYPE (req_class),
+ G_SIGNAL_RUN_FIRST, 0, NULL, NULL,
+ nma_marshal_VOID__POINTER_POINTER,
+ G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER);
+}
+
diff --git a/src/applet-vpn-request.h b/src/applet-vpn-request.h
new file mode 100644
index 0000000..cf81ed7
--- /dev/null
+++ b/src/applet-vpn-request.h
@@ -0,0 +1,58 @@
+/* NetworkManager Wireless Applet -- Display wireless access points and allow user control
+ *
+ * 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 2004 - 2011 Red Hat, Inc.
+ */
+
+#ifndef APPLET_VPN_REQEUST_H
+#define APPLET_VPN_REQUEST_H
+
+#include <glib-object.h>
+
+#include <nm-connection.h>
+
+#define APPLET_TYPE_VPN_REQUEST (applet_vpn_request_get_type ())
+#define APPLET_VPN_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), APPLET_TYPE_VPN_REQUEST, AppletVpnRequest))
+#define APPLET_VPN_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), APPLET_TYPE_VPN_REQUEST, AppletVpnRequestClass))
+#define APPLET_IS_VPN_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), APPLET_TYPE_VPN_REQUEST))
+#define APPLET_IS_VPN_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), APPLET_TYPE_VPN_REQUEST))
+#define APPLET_VPN_REQUEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), APPLET_TYPE_VPN_REQUEST, AppletVpnRequestClass))
+
+typedef struct {
+ GObject parent;
+} AppletVpnRequest;
+
+typedef struct {
+ GObjectClass parent;
+
+ /* Signals */
+ void (*done) (AppletVpnRequest *self,
+ GHashTable *secrets,
+ GError *error);
+} AppletVpnRequestClass;
+
+GType applet_vpn_request_get_type (void);
+
+AppletVpnRequest *applet_vpn_request_new (NMConnection *connection, GError **error);
+
+gboolean applet_vpn_request_get_secrets (AppletVpnRequest *req,
+ gboolean retry,
+ GError **error);
+
+#endif /* APPLET_VPN_REQUEST_H */
+
diff --git a/src/applet.c b/src/applet.c
index 65f4230..1167282 100644
--- a/src/applet.c
+++ b/src/applet.c
@@ -52,6 +52,12 @@
#include <nm-connection.h>
#include <nm-vpn-connection.h>
#include <nm-setting-connection.h>
+#include <nm-setting-wired.h>
+#include <nm-setting-wireless.h>
+#include <nm-setting-pppoe.h>
+#include <nm-setting-gsm.h>
+#include <nm-setting-cdma.h>
+#include <nm-setting-bluetooth.h>
#include <nm-setting-vpn.h>
#include <nm-active-connection.h>
#include <nm-setting-wireless.h>
@@ -68,7 +74,7 @@
#include "applet-device-cdma.h"
#include "applet-device-bt.h"
#include "applet-dialogs.h"
-#include "vpn-password-dialog.h"
+#include "applet-vpn-request.h"
#include "utils.h"
#include "gconf-helpers.h"
@@ -235,6 +241,26 @@ applet_get_active_for_connection (NMApplet *applet, NMConnection *connection)
return NULL;
}
+NMDevice *
+applet_get_device_for_connection (NMApplet *applet, NMConnection *connection)
+{
+ const GPtrArray *active_list;
+ const char *cpath;
+ int i;
+
+ cpath = nm_connection_get_path (connection);
+ g_return_val_if_fail (cpath != NULL, NULL);
+
+ active_list = nm_client_get_active_connections (applet->nm_client);
+ for (i = 0; active_list && (i < active_list->len); i++) {
+ NMActiveConnection *active = NM_ACTIVE_CONNECTION (g_ptr_array_index (active_list, i));
+
+ if (!g_strcmp0 (nm_active_connection_get_connection (active), cpath))
+ return g_ptr_array_index (nm_active_connection_get_devices (active), 0);
+ }
+ return NULL;
+}
+
static inline NMADeviceClass *
get_device_class (NMDevice *device, NMApplet *applet)
{
@@ -256,6 +282,36 @@ get_device_class (NMDevice *device, NMApplet *applet)
return NULL;
}
+static inline NMADeviceClass *
+get_device_class_from_connection (NMConnection *connection, NMApplet *applet)
+{
+ NMSettingConnection *s_con;
+ const char *ctype;
+
+ g_return_val_if_fail (connection != NULL, NULL);
+ g_return_val_if_fail (applet != NULL, NULL);
+
+ s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
+ g_return_val_if_fail (s_con != NULL, NULL);
+
+ ctype = nm_setting_connection_get_connection_type (s_con);
+ g_return_val_if_fail (ctype != NULL, NULL);
+
+ if (!strcmp (ctype, NM_SETTING_WIRED_SETTING_NAME) || !strcmp (ctype, NM_SETTING_PPPOE_SETTING_NAME))
+ return applet->wired_class;
+ else if (!strcmp (ctype, NM_SETTING_WIRELESS_SETTING_NAME))
+ return applet->wifi_class;
+ else if (!strcmp (ctype, NM_SETTING_GSM_SETTING_NAME))
+ return applet->gsm_class;
+ else if (!strcmp (ctype, NM_SETTING_CDMA_SETTING_NAME))
+ return applet->cdma_class;
+ else if (!strcmp (ctype, NM_SETTING_BLUETOOTH_SETTING_NAME))
+ return applet->bt_class;
+ else
+ g_warning ("%s: unhandled connection type '%s'", __func__, ctype);
+ return NULL;
+}
+
typedef struct {
NMApplet *applet;
NMDevice *device;
@@ -2449,120 +2505,271 @@ applet_schedule_update_icon (NMApplet *applet)
applet->update_icon_id = g_idle_add (applet_update_icon, applet);
}
-#if 0
-static NMDevice *
-find_active_device (NMRemoteConnection *connection,
- NMApplet *applet,
- NMActiveConnection **out_active_connection)
+/*****************************************************************************/
+
+static SecretsRequest *
+applet_secrets_request_new (size_t totsize,
+ NMConnection *connection,
+ gpointer request_id,
+ const char *setting_name,
+ const char **hints,
+ AppletAgentSecretsCallback callback,
+ gpointer callback_data,
+ NMApplet *applet)
{
- const GPtrArray *active_connections;
- int i;
+ SecretsRequest *req;
+ g_return_val_if_fail (totsize >= sizeof (SecretsRequest), NULL);
g_return_val_if_fail (connection != NULL, NULL);
- g_return_val_if_fail (applet != NULL, NULL);
- g_return_val_if_fail (out_active_connection != NULL, NULL);
- g_return_val_if_fail (*out_active_connection == NULL, NULL);
- /* Look through the active connection list trying to find the D-Bus
- * object path of applet_connection.
- */
- active_connections = nm_client_get_active_connections (applet->nm_client);
- for (i = 0; active_connections && (i < active_connections->len); i++) {
- NMActiveConnection *active;
- const char *connection_path;
- const GPtrArray *devices;
+ req = g_malloc0 (totsize);
+ req->totsize = totsize;
+ req->connection = g_object_ref (connection);
+ req->reqid = request_id;
+ req->setting_name = g_strdup (setting_name);
+ req->hints = g_strdupv ((char **) hints);
+ req->callback = callback;
+ req->callback_data = callback_data;
+ req->applet = applet;
+ return req;
+}
- active = NM_ACTIVE_CONNECTION (g_ptr_array_index (active_connections, i));
+void
+applet_secrets_request_set_free_func (SecretsRequest *req,
+ SecretsRequestFreeFunc free_func)
+{
+ req->free_func = free_func;
+}
- connection_path = nm_active_connection_get_connection (active);
- if (!connection_path) {
- /* Shouldn't happen; but we shouldn't crash either */
- g_warning ("%s: couldn't get connection path for active connection!", __func__);
- continue;
- }
+void
+applet_secrets_request_complete (SecretsRequest *req,
+ GHashTable *settings,
+ GError *error)
+{
+ req->callback (req->applet->agent, error ? NULL : settings, error, req->callback_data);
+}
- if (!strcmp (connection_path, nm_connection_get_path (NM_CONNECTION (connection)))) {
- devices = nm_active_connection_get_devices (active);
- if (devices)
- *out_active_connection = active;
- return devices ? NM_DEVICE (g_ptr_array_index (devices, 0)) : NULL;
+void
+applet_secrets_request_complete_setting (SecretsRequest *req,
+ const char *setting_name,
+ GError *error)
+{
+ NMSetting *setting;
+ GHashTable *settings = NULL, *secrets;
+
+ if (setting_name && !error) {
+ setting = nm_connection_get_setting_by_name (req->connection, setting_name);
+ if (setting) {
+ secrets = nm_setting_to_hash (NM_SETTING (setting));
+ if (secrets) {
+ /* Returned secrets are a{sa{sv}}; this is the outer a{s...} hash that
+ * will contain all the individual settings hashes.
+ */
+ settings = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ (GDestroyNotify) g_hash_table_destroy);
+ g_hash_table_insert (settings, g_strdup (setting_name), secrets);
+ } else {
+ g_set_error (&error,
+ NM_SECRET_AGENT_ERROR,
+ NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
+ "%s.%d (%s): failed to hash setting '%s'.",
+ __FILE__, __LINE__, __func__, setting_name);
+ }
+ } else {
+ g_set_error (&error,
+ NM_SECRET_AGENT_ERROR,
+ NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
+ "%s.%d (%s): unhandled setting '%s'",
+ __FILE__, __LINE__, __func__, setting_name);
}
}
- return NULL;
+ req->callback (req->applet->agent, settings, error, req->callback_data);
+}
+
+void
+applet_secrets_request_free (SecretsRequest *req)
+{
+ g_return_if_fail (req != NULL);
+
+ if (req->free_func)
+ req->free_func (req);
+
+ req->applet->secrets_reqs = g_slist_remove (req->applet->secrets_reqs, req);
+
+ g_object_unref (req->connection);
+ g_free (req->setting_name);
+ g_strfreev (req->hints);
+ memset (req, 0, req->totsize);
+ g_free (req);
+}
+
+typedef struct {
+ SecretsRequest req;
+ AppletVpnRequest *vpn;
+} VpnSecretsRequest;
+
+static void
+vpn_request_done_cb (AppletVpnRequest *foo,
+ GHashTable *settings,
+ GError *error,
+ gpointer user_data)
+{
+ SecretsRequest *req = user_data;
+
+ applet_secrets_request_complete (req, settings, error);
+ applet_secrets_request_free (req);
+}
+
+static void
+vpn_request_free_cb (SecretsRequest *req)
+{
+ VpnSecretsRequest *vpn_req = (VpnSecretsRequest *) req;
+
+ if (vpn_req->vpn)
+ g_object_unref (vpn_req->vpn);
}
static void
-applet_settings_new_secrets_requested_cb (NMRemoteSettings *settings,
- NMRemoteConnection *connection,
- const char *setting_name,
- const char **hints,
- gboolean ask_user,
- NMANewSecretsRequestedFunc callback,
- gpointer callback_data,
- gpointer user_data)
+get_existing_secrets_cb (NMSecretAgent *agent,
+ NMConnection *connection,
+ GHashTable *secrets,
+ GError *secrets_error,
+ gpointer user_data)
+{
+ SecretsRequest *req = user_data;
+ NMADeviceClass *dclass;
+ GError *error = NULL;
+
+ /* Merge existing secrets into connection; ignore errors */
+ nm_connection_update_secrets (connection, req->setting_name, secrets, NULL);
+
+ dclass = get_device_class_from_connection (connection, req->applet);
+ g_assert (dclass);
+
+ /* Let the device class handle secrets */
+ if (!dclass->get_secrets (req, &error)) {
+ g_warning ("%s:%d - %s", __func__, __LINE__, error ? error->message : "(unknown)");
+ applet_secrets_request_complete (req, NULL, error);
+ applet_secrets_request_free (req);
+ g_error_free (error);
+ }
+ /* Otherwise success; wait for the secrets callback */
+}
+
+static void
+applet_agent_get_secrets_cb (AppletAgent *agent,
+ void *request_id,
+ NMConnection *connection,
+ const char *setting_name,
+ const char **hints,
+ guint32 flags,
+ AppletAgentSecretsCallback callback,
+ gpointer callback_data,
+ gpointer user_data)
{
NMApplet *applet = NM_APPLET (user_data);
- NMActiveConnection *active_connection = NULL;
NMSettingConnection *s_con;
- NMDevice *device;
NMADeviceClass *dclass;
GError *error = NULL;
+ SecretsRequest *req = NULL;
- s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (connection), NM_TYPE_SETTING_CONNECTION);
+ s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
g_return_if_fail (s_con != NULL);
/* VPN secrets get handled a bit differently */
if (!strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_VPN_SETTING_NAME)) {
- nma_vpn_request_password (connection, ask_user, callback, callback_data);
+ VpnSecretsRequest *vpnreq;
+
+ req = applet_secrets_request_new (sizeof (VpnSecretsRequest),
+ connection,
+ request_id,
+ setting_name,
+ hints,
+ callback,
+ callback_data,
+ applet);
+ applet_secrets_request_set_free_func (req, vpn_request_free_cb);
+
+ vpnreq = (VpnSecretsRequest *) req;
+ vpnreq->vpn = applet_vpn_request_new (connection, &error);
+ if (!vpnreq->vpn)
+ goto error;
+ if (!applet_vpn_request_get_secrets (vpnreq->vpn, !!flags, &error))
+ goto error;
+
+ /* Track this VPN password request */
+ g_signal_connect (vpnreq->vpn, "done", G_CALLBACK (vpn_request_done_cb), vpnreq);
+ applet->secrets_reqs = g_slist_prepend (applet->secrets_reqs, vpnreq);
return;
}
- /* Find the active device for this connection */
- device = find_active_device (connection, applet, &active_connection);
- if (!device || !active_connection) {
- g_set_error (&error,
- 0,
- 0,
- "%s.%d (%s): couldn't find details for connection",
- __FILE__, __LINE__, __func__);
- goto error;
- }
-
- dclass = get_device_class (device, applet);
+ dclass = get_device_class_from_connection (connection, applet);
if (!dclass) {
- g_set_error (&error,
- 0,
- 0,
- "%s.%d (%s): device type unknown",
- __FILE__, __LINE__, __func__);
+ error = g_error_new (NM_SECRET_AGENT_ERROR,
+ NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
+ "%s.%d (%s): device type unknown",
+ __FILE__, __LINE__, __func__);
goto error;
}
if (!dclass->get_secrets) {
- g_set_error (&error,
- 0,
- 0,
- "%s.%d (%s): no secrets found",
- __FILE__, __LINE__, __func__);
+ error = g_error_new (NM_SECRET_AGENT_ERROR,
+ NM_SECRET_AGENT_ERROR_NO_SECRETS,
+ "%s.%d (%s): no secrets found",
+ __FILE__, __LINE__, __func__);
goto error;
}
- // FIXME: get secrets locally and populate connection with previous secrets
- // before asking user for other secrets
-
- /* Let the device class handle secrets */
- if (dclass->get_secrets (device, connection,
- active_connection, setting_name, hints, callback,
- callback_data, applet, &error))
- return; /* success */
+ g_assert (dclass->secrets_request_size);
+ req = applet_secrets_request_new (dclass->secrets_request_size,
+ connection,
+ request_id,
+ setting_name,
+ hints,
+ callback,
+ callback_data,
+ applet);
+ applet->secrets_reqs = g_slist_prepend (applet->secrets_reqs, req);
+
+ /* Get existing secrets, if any */
+ nm_secret_agent_get_secrets (NM_SECRET_AGENT (applet->agent),
+ connection,
+ setting_name,
+ hints,
+ FALSE,
+ get_existing_secrets_cb,
+ req);
+ return;
error:
g_warning ("%s", error->message);
- callback (connection, NULL, error, callback_data);
+ callback (agent, NULL, error, callback_data);
g_error_free (error);
+
+ if (req)
+ applet_secrets_request_free (req);
+}
+
+static void
+applet_agent_cancel_secrets_cb (AppletAgent *agent,
+ void *request_id,
+ gpointer user_data)
+{
+ NMApplet *applet = NM_APPLET (user_data);
+ GSList *iter;
+
+ for (iter = applet->secrets_reqs; iter; iter = g_slist_next (iter)) {
+ SecretsRequest *req = iter->data;
+
+ if (req->reqid == request_id) {
+ /* cancel and free this password request */
+ applet_secrets_request_free (req);
+ }
+ }
}
-#endif
/*****************************************************************************/
@@ -2926,6 +3133,10 @@ constructor (GType type,
applet->agent = applet_agent_new ();
g_assert (applet->agent);
+ g_signal_connect (applet->agent, APPLET_AGENT_GET_SECRETS,
+ G_CALLBACK (applet_agent_get_secrets_cb), applet);
+ g_signal_connect (applet->agent, APPLET_AGENT_CANCEL_SECRETS,
+ G_CALLBACK (applet_agent_cancel_secrets_cb), applet);
/* Initialize device classes */
applet->wired_class = applet_device_wired_get_class (applet);
@@ -2981,6 +3192,9 @@ static void finalize (GObject *object)
g_free (applet->tip);
+ g_slist_foreach (applet->secrets_reqs, (GFunc) g_object_unref, NULL);
+ g_slist_free (applet->secrets_reqs);
+
if (applet->notification) {
notify_notification_close (applet->notification, NULL);
g_object_unref (applet->notification);
diff --git a/src/applet.h b/src/applet.h
index 87c762e..569cd72 100644
--- a/src/applet.h
+++ b/src/applet.h
@@ -163,6 +163,9 @@ typedef struct
GtkBuilder * info_dialog_ui;
NotifyNotification* notification;
gboolean notify_actions;
+
+ /* Tracker objects for secrets requests */
+ GSList * secrets_reqs;
} NMApplet;
typedef void (*AppletNewAutoConnectionCallback) (NMConnection *connection,
@@ -170,10 +173,33 @@ typedef void (*AppletNewAutoConnectionCallback) (NMConnection *connection,
gboolean canceled,
gpointer user_data);
-typedef void (*NMANewSecretsRequestedFunc) (NMRemoteConnection *connection,
- GHashTable *settings,
- GError *error,
- gpointer user_data);
+typedef struct _SecretsRequest SecretsRequest;
+typedef void (*SecretsRequestFreeFunc) (SecretsRequest *req);
+
+struct _SecretsRequest {
+ size_t totsize;
+ gpointer reqid;
+ char *setting_name;
+ char **hints;
+ NMApplet *applet;
+ AppletAgentSecretsCallback callback;
+ gpointer callback_data;
+
+ NMConnection *connection;
+
+ /* Class-specific stuff */
+ SecretsRequestFreeFunc free_func;
+};
+
+void applet_secrets_request_set_free_func (SecretsRequest *req,
+ SecretsRequestFreeFunc free_func);
+void applet_secrets_request_complete (SecretsRequest *req,
+ GHashTable *settings,
+ GError *error);
+void applet_secrets_request_complete_setting (SecretsRequest *req,
+ const char *setting_name,
+ GError *error);
+void applet_secrets_request_free (SecretsRequest *req);
struct NMADeviceClass {
gboolean (*new_auto_connection) (NMDevice *device,
@@ -206,14 +232,8 @@ struct NMADeviceClass {
NMApplet *applet,
gpointer user_data);
- gboolean (*get_secrets) (NMDevice *device,
- NMRemoteConnection *connection,
- NMActiveConnection *active_connection,
- const char *setting_name,
- const char **hints,
- NMANewSecretsRequestedFunc callback,
- gpointer callback_data,
- NMApplet *applet,
+ size_t secrets_request_size;
+ gboolean (*get_secrets) (SecretsRequest *req,
GError **error);
};
@@ -254,6 +274,8 @@ applet_menu_item_create_device_item_helper (NMDevice *device,
NMRemoteConnection *applet_get_exported_connection_for_device (NMDevice *device, NMApplet *applet);
+NMDevice *applet_get_device_for_connection (NMApplet *applet, NMConnection *connection);
+
void applet_do_notify (NMApplet *applet,
NotifyUrgency urgency,
const char *summary,
diff --git a/src/gconf-helpers/gconf-helpers.c b/src/gconf-helpers/gconf-helpers.c
index b0865e0..1db2d7a 100644
--- a/src/gconf-helpers/gconf-helpers.c
+++ b/src/gconf-helpers/gconf-helpers.c
@@ -1989,24 +1989,15 @@ nm_gconf_add_keyring_item (const char *connection_uuid,
g_return_if_fail (setting_key != NULL);
g_return_if_fail (secret != NULL);
- display_name = g_strdup_printf ("Network secret for %s/%s/%s",
- connection_name,
- setting_name,
- setting_key);
-
- attrs = gnome_keyring_attribute_list_new ();
- gnome_keyring_attribute_list_append_string (attrs,
- KEYRING_UUID_TAG,
- connection_uuid);
- gnome_keyring_attribute_list_append_string (attrs,
- KEYRING_SN_TAG,
- setting_name);
- gnome_keyring_attribute_list_append_string (attrs,
- KEYRING_SK_TAG,
- setting_key);
-
pre_keyring_callback ();
+ attrs = utils_create_keyring_add_attr_list (NULL,
+ connection_uuid,
+ connection_name,
+ setting_name,
+ setting_key,
+ &display_name);
+ g_assert (attrs);
ret = gnome_keyring_item_create_sync (NULL,
GNOME_KEYRING_ITEM_GENERIC_SECRET,
display_name,
@@ -2014,7 +2005,6 @@ nm_gconf_add_keyring_item (const char *connection_uuid,
secret,
TRUE,
&id);
-
gnome_keyring_attribute_list_free (attrs);
g_free (display_name);
}
diff --git a/src/marshallers/nma-marshal.list b/src/marshallers/nma-marshal.list
index 5aef346..33cbac8 100644
--- a/src/marshallers/nma-marshal.list
+++ b/src/marshallers/nma-marshal.list
@@ -1,7 +1,6 @@
VOID:POINTER
VOID:STRING,STRING,STRING
-VOID:STRING,POINTER,BOOLEAN,POINTER,POINTER
-VOID:OBJECT,STRING,POINTER,BOOLEAN,POINTER,POINTER
+VOID:POINTER,POINTER,STRING,POINTER,BOOLEAN,POINTER,POINTER
VOID:POINTER,POINTER
VOID:INT,POINTER
VOID:STRING,BOXED
diff --git a/src/utils/utils.c b/src/utils/utils.c
index de99a2a..7b1642d 100644
--- a/src/utils/utils.c
+++ b/src/utils/utils.c
@@ -17,7 +17,7 @@
* 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.
+ * (C) Copyright 2007 - 2011 Red Hat, Inc.
*/
#include <config.h>
@@ -761,3 +761,46 @@ utils_escape_notify_message (const char *src)
return g_string_free (escaped, FALSE);
}
+GnomeKeyringAttributeList *
+utils_create_keyring_add_attr_list (NMConnection *connection,
+ const char *connection_uuid,
+ const char *connection_id,
+ const char *setting_name,
+ const char *setting_key,
+ char **out_display_name)
+{
+ GnomeKeyringAttributeList *attrs = NULL;
+ NMSettingConnection *s_con;
+
+ if (connection) {
+ s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
+ g_return_val_if_fail (s_con != NULL, NULL);
+ connection_uuid = nm_setting_connection_get_uuid (s_con);
+ connection_id = nm_setting_connection_get_id (s_con);
+ }
+
+ g_return_val_if_fail (connection_uuid != NULL, NULL);
+ g_return_val_if_fail (connection_id != NULL, NULL);
+ g_return_val_if_fail (setting_name != NULL, NULL);
+ g_return_val_if_fail (setting_key != NULL, NULL);
+
+ if (out_display_name) {
+ *out_display_name = g_strdup_printf ("Network secret for %s/%s/%s",
+ connection_id,
+ setting_name,
+ setting_key);
+ }
+
+ attrs = gnome_keyring_attribute_list_new ();
+ gnome_keyring_attribute_list_append_string (attrs,
+ KEYRING_UUID_TAG,
+ connection_uuid);
+ gnome_keyring_attribute_list_append_string (attrs,
+ KEYRING_SN_TAG,
+ setting_name);
+ gnome_keyring_attribute_list_append_string (attrs,
+ KEYRING_SK_TAG,
+ setting_key);
+ return attrs;
+}
+
diff --git a/src/utils/utils.h b/src/utils/utils.h
index 07d29d8..052bb3f 100644
--- a/src/utils/utils.h
+++ b/src/utils/utils.h
@@ -17,7 +17,7 @@
* 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 Red Hat, Inc.
+ * (C) Copyright 2007 - 2011 Red Hat, Inc.
*/
#ifndef UTILS_H
@@ -28,6 +28,7 @@
#include <nm-device.h>
#include <net/ethernet.h>
#include <nm-access-point.h>
+#include <gnome-keyring.h>
const char *utils_get_device_description (NMDevice *device);
@@ -57,5 +58,16 @@ char *utils_hash_ap (const GByteArray *ssid,
char *utils_escape_notify_message (const char *src);
+#define KEYRING_UUID_TAG "connection-uuid"
+#define KEYRING_SN_TAG "setting-name"
+#define KEYRING_SK_TAG "setting-key"
+
+GnomeKeyringAttributeList *utils_create_keyring_add_attr_list (NMConnection *connection,
+ const char *connection_uuid,
+ const char *connection_id,
+ const char *setting_name,
+ const char *setting_key,
+ char **out_display_name);
+
#endif /* UTILS_H */
diff --git a/src/wired-dialog.c b/src/wired-dialog.c
index 9a8efae..502fbdf 100644
--- a/src/wired-dialog.c
+++ b/src/wired-dialog.c
@@ -18,7 +18,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* (C) Copyright 2008 Novell, Inc.
- * (C) Copyright 2008 - 2010 Red Hat, Inc.
+ * (C) Copyright 2008 - 2011 Red Hat, Inc.
*/
#ifdef HAVE_CONFIG_H
@@ -79,7 +79,6 @@ dialog_set_security (NMConnection *connection,
static gboolean
dialog_init (GtkWidget *dialog,
GtkBuilder *builder,
- NMClient *nm_client,
NMConnection *connection)
{
WirelessSecurity *security;
@@ -114,10 +113,7 @@ dialog_init (GtkWidget *dialog,
}
GtkWidget *
-nma_wired_dialog_new (const char *ui_file,
- NMClient *nm_client,
- NMRemoteConnection *connection,
- NMDevice *device)
+nma_wired_dialog_new (const char *ui_file, NMConnection *connection)
{
GtkBuilder *builder;
GtkWidget *dialog;
@@ -141,7 +137,7 @@ nma_wired_dialog_new (const char *ui_file,
return NULL;
}
- success = dialog_init (dialog, builder, nm_client, NM_CONNECTION (connection));
+ success = dialog_init (dialog, builder, connection);
if (!success) {
nm_warning ("Couldn't create wired security dialog.");
gtk_widget_destroy (dialog);
@@ -161,12 +157,11 @@ nma_wired_dialog_new (const char *ui_file,
return dialog;
}
-NMRemoteConnection *
+NMConnection *
nma_wired_dialog_get_connection (GtkWidget *dialog)
{
- NMRemoteConnection *connection;
+ NMConnection *connection, *tmp_connection;
WirelessSecurity *security;
- NMConnection *tmp_connection;
NMSetting *s_8021x, *s_con;
g_return_val_if_fail (dialog != NULL, NULL);
@@ -180,7 +175,7 @@ nma_wired_dialog_get_connection (GtkWidget *dialog)
tmp_connection = nm_connection_new ();
/* Add the fake connection setting (mainly for the UUID for cert ignore checking) */
- s_con = nm_connection_get_setting (NM_CONNECTION (connection), NM_TYPE_SETTING_CONNECTION);
+ s_con = nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
g_assert (s_con);
nm_connection_add_setting (tmp_connection, NM_SETTING (g_object_ref (s_con)));
@@ -192,7 +187,7 @@ nma_wired_dialog_get_connection (GtkWidget *dialog)
/* Grab it and add it to our original connection */
s_8021x = nm_connection_get_setting (tmp_connection, NM_TYPE_SETTING_802_1X);
- nm_connection_add_setting (NM_CONNECTION (connection), NM_SETTING (g_object_ref (s_8021x)));
+ nm_connection_add_setting (connection, NM_SETTING (g_object_ref (s_8021x)));
g_object_unref (tmp_connection);
diff --git a/src/wired-dialog.h b/src/wired-dialog.h
index 954b11a..81a84dd 100644
--- a/src/wired-dialog.h
+++ b/src/wired-dialog.h
@@ -18,23 +18,17 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* (C) Copyright 2008 Novell, Inc.
- * (C) Copyright 2008 Red Hat, Inc.
+ * (C) Copyright 2008 - 2011 Red Hat, Inc.
*/
#ifndef WIRED_DIALOG_H
#define WIRED_DIALOG_H
#include <gtk/gtk.h>
-#include <nm-client.h>
#include <nm-connection.h>
-#include <nm-device.h>
-#include <nm-remote-connection.h>
-GtkWidget *nma_wired_dialog_new (const char *ui_file,
- NMClient *nm_client,
- NMRemoteConnection *connection,
- NMDevice *device);
+GtkWidget *nma_wired_dialog_new (const char *ui_file, NMConnection *connection);
-NMRemoteConnection *nma_wired_dialog_get_connection (GtkWidget *dialog);
+NMConnection *nma_wired_dialog_get_connection (GtkWidget *dialog);
#endif /* WIRED_DIALOG_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]