[network-manager-netbook] Hook up wireless authentication



commit 317a140e378afcc5a6239e1acfa814fe29195f91
Author: Tambet Ingo <tambet gmail com>
Date:   Thu Jan 28 15:31:25 2010 -0400

    Hook up wireless authentication
    
    Can't believe nobody noticed it didn't work.

 libnm-gtk/nm-connection-item.c  |   36 ++++++++
 libnm-gtk/nm-connection-item.h  |    8 ++
 libnm-gtk/nm-gconf-connection.h |    3 +-
 libnm-gtk/nm-wifi-item.c        |  169 ++++++++++++++++++++++++++++++++-------
 4 files changed, 187 insertions(+), 29 deletions(-)
---
diff --git a/libnm-gtk/nm-connection-item.c b/libnm-gtk/nm-connection-item.c
index 9c99b68..0b73b4c 100644
--- a/libnm-gtk/nm-connection-item.c
+++ b/libnm-gtk/nm-connection-item.c
@@ -18,6 +18,7 @@
  */
 
 #include <string.h>
+#include <nm-settings-interface.h>
 #include <nm-setting-connection.h>
 #include <nm-settings-connection-interface.h>
 #include <nm-active-connection.h>
@@ -45,6 +46,7 @@ typedef struct {
     gboolean delete_allowed;
     gboolean connect_pending;
 
+    gulong secrets_requested_id;
     gulong removed_id;
     gulong updated_id;
     gulong acs_changed_id;
@@ -70,6 +72,32 @@ nm_connection_item_get_connection (NMConnectionItem *self)
 }
 
 static void
+secrets_requested (NMGConfConnection *connection,
+                   const char *setting_name,
+                   const char **hints,
+                   gboolean ask_user,
+                   NMNewSecretsRequestedFunc callback,
+                   gpointer callback_data,
+                   gpointer user_data)
+{
+    NMConnectionItem *self = NM_CONNECTION_ITEM (user_data);
+
+    if (NM_CONNECTION_ITEM_GET_CLASS (self)->secrets_requested)
+        NM_CONNECTION_ITEM_GET_CLASS (self)->secrets_requested (self, setting_name, hints,
+                                                                ask_user, callback, callback_data);
+    else {
+        GError *error;
+
+        error = g_error_new_literal (NM_SETTINGS_INTERFACE_ERROR,
+                                     NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR,
+                                     "No secrets providers registered");
+
+        callback (NM_SETTINGS_CONNECTION_INTERFACE (connection), NULL, error, callback_data);
+        g_error_free (error);
+    }
+}
+
+static void
 connection_removed (NMSettingsConnectionInterface *connection,
                     gpointer data)
 {
@@ -212,6 +240,7 @@ nm_connection_item_set_connection (NMConnectionItem *self,
 
     if (priv->connection) {
         set_active_connection (self, NULL);
+        g_signal_handler_disconnect (priv->connection, priv->secrets_requested_id);
         g_signal_handler_disconnect (priv->connection, priv->removed_id);
         g_signal_handler_disconnect (priv->connection, priv->updated_id);
         g_signal_handler_disconnect (priv->client, priv->acs_changed_id);
@@ -221,6 +250,12 @@ nm_connection_item_set_connection (NMConnectionItem *self,
     if (connection) {
         priv->connection = g_object_ref (connection);
 
+        if (NM_IS_GCONF_CONNECTION (connection))
+            priv->secrets_requested_id = g_signal_connect (connection,
+                                                           "new-secrets-requested",
+                                                           G_CALLBACK (secrets_requested),
+                                                           self);
+
         priv->removed_id = g_signal_connect (connection, "removed", G_CALLBACK (connection_removed), self);
         priv->updated_id = g_signal_connect (connection, "updated", G_CALLBACK (connection_updated), self);
         connection_update_id (self);
@@ -229,6 +264,7 @@ nm_connection_item_set_connection (NMConnectionItem *self,
                                                  G_CALLBACK (active_connections_changed), self);
         active_connections_changed (priv->client, NULL, self);
     } else {
+        priv->secrets_requested_id = 0;
         priv->removed_id = 0;
         priv->updated_id = 0;
         priv->acs_changed_id = 0;
diff --git a/libnm-gtk/nm-connection-item.h b/libnm-gtk/nm-connection-item.h
index d2b1279..f2760b1 100644
--- a/libnm-gtk/nm-connection-item.h
+++ b/libnm-gtk/nm-connection-item.h
@@ -24,6 +24,7 @@
 #include <nm-client.h>
 #include <nm-settings-connection-interface.h>
 #include <nm-list-item.h>
+#include <nm-gconf-connection.h>
 
 G_BEGIN_DECLS
 
@@ -45,6 +46,13 @@ typedef struct {
 typedef struct {
     NMListItemClass parent_class;
 
+    void (*secrets_requested) (NMConnectionItem *self,
+                               const char *setting_name,
+                               const char **hints,
+                               gboolean ask_user,
+                               NMNewSecretsRequestedFunc callback,
+                               gpointer callback_data);
+
     NMConnection *(*create_connection) (NMConnectionItem *self);
 } NMConnectionItemClass;
 
diff --git a/libnm-gtk/nm-gconf-connection.h b/libnm-gtk/nm-gconf-connection.h
index 00a3883..f6583e0 100644
--- a/libnm-gtk/nm-gconf-connection.h
+++ b/libnm-gtk/nm-gconf-connection.h
@@ -57,7 +57,8 @@ typedef struct {
 	                                const char *setting_name,
 	                                const char **hints,
 	                                gboolean ask_user,
-	                                DBusGMethodInvocation *context);
+	                                NMNewSecretsRequestedFunc callback,
+									gpointer callback_data);
 } NMGConfConnectionClass;
 
 GType nm_gconf_connection_get_type (void);
diff --git a/libnm-gtk/nm-wifi-item.c b/libnm-gtk/nm-wifi-item.c
index c8f9005..7f93cf0 100644
--- a/libnm-gtk/nm-wifi-item.c
+++ b/libnm-gtk/nm-wifi-item.c
@@ -22,6 +22,7 @@
 #include <nm-setting-wireless.h>
 #include <nm-setting-wireless-security.h>
 #include <nm-setting-8021x.h>
+#include <nm-settings-interface.h>
 #include <nm-utils.h>
 #include "nm-wifi-item.h"
 #include "wireless-dialog.h"
@@ -429,21 +430,6 @@ create_connection (NMConnectionItem *item)
 }
 
 static void
-wireless_dialog_response_cb (NMAWirelessDialog *dialog,
-                             gint response,
-                             gpointer user_data)
-{
-    gtk_widget_hide (GTK_WIDGET (dialog));
-
-    if (response == GTK_RESPONSE_OK)
-        nm_connection_item_new_connection (NM_CONNECTION_ITEM (user_data),
-                                           nma_wireless_dialog_get_connection (dialog),
-                                           TRUE);
-
-    gtk_widget_destroy (GTK_WIDGET (dialog));
-}
-
-static void
 connect (NMListItem *item)
 {
     NMConnectionItem *connection_item = NM_CONNECTION_ITEM (item);
@@ -457,25 +443,151 @@ connect (NMListItem *item)
 
     /* We don't have a connection yet, so create one */
     connection = nm_connection_item_create_connection (connection_item);
-    if (!connection) {
+    if (connection) {
+        nm_connection_item_new_connection (connection_item, connection, TRUE);
+        g_object_unref (connection);
+    } else
         g_warning ("Could not create a new WiFi connection");
-        return;
+}
+
+static void
+update_cb (NMSettingsConnectionInterface *connection,
+           GError *error,
+           gpointer user_data)
+{
+    if (error) {
+        g_warning ("%s: failed to update connection: (%d) %s",
+                   __func__, error->code, error->message);
     }
+}
 
-    if (nm_connection_need_secrets (connection, NULL)) {
-        GtkWidget *dialog;
+typedef struct {
+    NMNewSecretsRequestedFunc callback;
+    gpointer callback_data;
+} SecretsRequestInfo;
 
-        dialog = nma_wireless_dialog_new (nm_connection_item_get_client (connection_item),
-                                          connection,
-                                          nm_device_item_get_device (NM_DEVICE_ITEM (item)),
-                                          nm_wifi_item_get_ap (NM_WIFI_ITEM (item)));
+static void
+connection_secrets_response_cb (NMAWirelessDialog *dialog,
+                                gint response,
+                                gpointer user_data)
+{
+    SecretsRequestInfo *info = user_data;
+    NMConnection *connection;
+    GHashTable *settings = NULL;
+    NMSetting *s_wireless_sec;
+    const char *key_mgmt;
+    GError *error = NULL;
 
-        g_signal_connect (dialog, "done", G_CALLBACK (wireless_dialog_response_cb), item);
-        nma_wireless_dialog_show (NMA_WIRELESS_DIALOG (dialog));
-    } else
-        nm_connection_item_new_connection (connection_item, connection, TRUE);
+    gtk_widget_hide (GTK_WIDGET (dialog));
+
+	connection = nma_wireless_dialog_get_connection (dialog);
+
+    if (response != GTK_RESPONSE_OK) {
+        error = g_error_new (NM_SETTINGS_INTERFACE_ERROR,
+                             NM_SETTINGS_INTERFACE_ERROR_SECRETS_REQUEST_CANCELED,
+                             "%s.%d (%s): canceled",
+                             __FILE__, __LINE__, __func__);
+
+        goto done;
+    }
+
+	/* 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);
+
+	/* If the user chose an 802.1x-based auth method, return 802.1x secrets,
+	 * not wireless secrets.  Can happen with Dynamic WEP, because NM doesn't
+	 * know the capabilities of the AP (since Dynamic WEP APs don't broadcast
+	 * beacons), and therefore defaults to requesting WEP secrets from the
+	 * wireless-security setting, not the 802.1x setting.
+	 */
+
+    s_wireless_sec = nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS_SECURITY);
+	key_mgmt = nm_setting_wireless_security_get_key_mgmt (NM_SETTING_WIRELESS_SECURITY (s_wireless_sec));
+	if (!strcmp (key_mgmt, "ieee8021x") || !strcmp (key_mgmt, "wpa-eap")) {
+        const char *auth_alg;
+
+		/* LEAP secrets aren't in the 802.1x setting */
+		auth_alg = nm_setting_wireless_security_get_auth_alg (NM_SETTING_WIRELESS_SECURITY (s_wireless_sec));
+		if (!auth_alg || strcmp (auth_alg, "leap")) {
+			NMSetting *s_8021x;
+
+			s_8021x = nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X);
+			if (!s_8021x) {
+				error = g_error_new (NM_SETTINGS_INTERFACE_ERROR,
+                                     NM_SETTINGS_INTERFACE_ERROR_INVALID_CONNECTION,
+                                     "%s.%d (%s): requested setting '802-1x' didn't"
+                                     " exist in the connection.",
+                                     __FILE__, __LINE__, __func__);
+				goto done;
+			}
+
+			/* Add the 802.1x setting */
+            g_hash_table_insert (settings,
+                                 g_strdup (nm_setting_get_name (s_8021x)),
+                                 nm_setting_to_hash (s_8021x));
+		}
+	}
+
+	/* Add the 802-11-wireless-security setting no matter what */
+    g_hash_table_insert (settings,
+                         g_strdup (nm_setting_get_name (s_wireless_sec)),
+                         nm_setting_to_hash (s_wireless_sec));
+
+	info->callback (NM_SETTINGS_CONNECTION_INTERFACE (connection), settings, NULL, info->callback_data);
+
+	/* 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.
+	 */
+	if (NM_IS_GCONF_CONNECTION (connection)) {
+		nm_settings_connection_interface_update (NM_SETTINGS_CONNECTION_INTERFACE (connection),
+		                                         update_cb,
+		                                         NULL);
+	}
+
+done:
+	if (settings)
+		g_hash_table_destroy (settings);
+
+	if (error) {
+		g_warning ("%s", error->message);
+		info->callback (NM_SETTINGS_CONNECTION_INTERFACE (connection), NULL, error, info->callback_data);
+		g_error_free (error);
+	}
+
+    g_free (info);
+
+	if (connection)
+		nm_connection_clear_secrets (connection);
+
+    gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
+static void
+secrets_requested (NMConnectionItem *item,
+                   const char *setting_name,
+                   const char **hints,
+                   gboolean ask_user,
+                   NMNewSecretsRequestedFunc callback,
+                   gpointer callback_data)
+{
+    GtkWidget *dialog;
+    SecretsRequestInfo *info;
+
+    dialog = nma_wireless_dialog_new (nm_connection_item_get_client (item),
+                                      (NMConnection *) nm_connection_item_get_connection (item),
+                                      nm_device_item_get_device (NM_DEVICE_ITEM (item)),
+                                      nm_wifi_item_get_ap (NM_WIFI_ITEM (item)));
+
+    info = g_new (SecretsRequestInfo, 1);
+    info->callback = callback;
+    info->callback_data = callback_data;
 
-    g_object_unref (connection);
+    g_signal_connect (dialog, "done", G_CALLBACK (connection_secrets_response_cb), info);
+    nma_wireless_dialog_show (NMA_WIRELESS_DIALOG (dialog));
 }
 
 /*****************************************************************************/
@@ -595,6 +707,7 @@ nm_wifi_item_class_init (NMWifiItemClass *klass)
     list_class->priority = priority;
     list_class->connect = connect;
 
+    connection_class->secrets_requested = secrets_requested;
     connection_class->create_connection = create_connection;
 
     device_class->get_specific_object = wifi_get_specific_object;



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