From b1bd00af0708d9e84e348f994bdbad3c55fd35a8 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 27 Sep 2007 04:52:03 +0000 Subject: [PATCH] 2007-09-26 Dan Williams * src/nm-manager.c src/nm-manager.h src/nm-activation-request.c src/nm-activation-request.h - Move the GetSecrets stuff out of the NMManager instance because it doesn't really need to be there and complicates things * src/nm-device.c - (connection_secrets_failed_cb, device_activation_go): connect to the connection-secrets-failed signal and deactivate the device if the GetSecrets call fails * src/nm-device-802-11-wireless.c - (link_timeout_cb, supplicant_connection_timeout_cb, real_act_stage2_config, real_act_stage4_ip_config_timeout): request secrets and give correct hints about whether new secrets should be asked for by the client or not git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@2899 4912f4e0-d625-0410-9fb7-b9a5a253dbdc --- ChangeLog | 20 ++++ src/nm-activation-request.c | 168 +++++++++++++++++++++++++------- src/nm-activation-request.h | 6 ++ src/nm-device-802-11-wireless.c | 16 +++ src/nm-device.c | 24 +++++ src/nm-manager.c | 157 ----------------------------- src/nm-manager.h | 3 - 7 files changed, 199 insertions(+), 195 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2e6d2fb967..b7d6a99c37 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2007-09-26 Dan Williams + + * src/nm-manager.c + src/nm-manager.h + src/nm-activation-request.c + src/nm-activation-request.h + - Move the GetSecrets stuff out of the NMManager instance because it + doesn't really need to be there and complicates things + + * src/nm-device.c + - (connection_secrets_failed_cb, device_activation_go): connect to the + connection-secrets-failed signal and deactivate the device if + the GetSecrets call fails + + * src/nm-device-802-11-wireless.c + - (link_timeout_cb, supplicant_connection_timeout_cb, + real_act_stage2_config, real_act_stage4_ip_config_timeout): request + secrets and give correct hints about whether new secrets should be + asked for by the client or not + 2007-09-26 Dan Williams * src/vpn-manager/nm-vpn-connection.c diff --git a/src/nm-activation-request.c b/src/nm-activation-request.c index 57e786f2b0..f9c416bb48 100644 --- a/src/nm-activation-request.c +++ b/src/nm-activation-request.c @@ -25,12 +25,15 @@ #include "nm-manager.h" #include "nm-utils.h" +#define CONNECTION_GET_SECRETS_CALL_TAG "get-secrets-call" + G_DEFINE_TYPE (NMActRequest, nm_act_request, G_TYPE_OBJECT) #define NM_ACT_REQUEST_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_ACT_REQUEST, NMActRequestPrivate)) enum { CONNECTION_SECRETS_UPDATED, + CONNECTION_SECRETS_FAILED, DEFERRED_ACTIVATION_TIMEOUT, DEFERRED_ACTIVATION_START, @@ -40,10 +43,6 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; -static void connection_secrets_updated_cb (NMConnection *connection, - const char *setting_name, - NMActRequest *self); - typedef struct { char *deferred_service_name; char *deferred_connection_path; @@ -53,8 +52,6 @@ typedef struct { NMConnection *connection; char *specific_object; gboolean user_requested; - - gulong secrets_updated_id; } NMActRequestPrivate; static void @@ -92,18 +89,20 @@ dispose (GObject *object) clear_deferred_stuff (NM_ACT_REQUEST (object)); - if (priv->secrets_updated_id) { - g_signal_handler_disconnect (priv->connection, - priv->secrets_updated_id); - priv->secrets_updated_id = 0; - } - if (priv->connection) { - NMManager *manager = nm_manager_get (); + DBusGProxy *proxy; + DBusGProxyCall *call; - nm_manager_cancel_get_connection_secrets (manager, priv->connection); - g_object_unref (manager); + proxy = g_object_get_data (G_OBJECT (priv->connection), + NM_MANAGER_CONNECTION_PROXY_TAG); + call = g_object_get_data (G_OBJECT (priv->connection), + CONNECTION_GET_SECRETS_CALL_TAG); + if (proxy && call) + dbus_g_proxy_cancel_call (proxy, call); + + g_object_set_data (G_OBJECT (priv->connection), + CONNECTION_GET_SECRETS_CALL_TAG, NULL); g_object_unref (priv->connection); } } @@ -141,6 +140,16 @@ nm_act_request_class_init (NMActRequestClass *req_class) G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_STRING); + signals[CONNECTION_SECRETS_FAILED] = + g_signal_new ("connection-secrets-failed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMActRequestClass, connection_secrets_failed), + NULL, NULL, + nm_marshal_VOID__OBJECT_STRING, + G_TYPE_NONE, 2, + G_TYPE_OBJECT, G_TYPE_STRING); + signals[DEFERRED_ACTIVATION_TIMEOUT] = g_signal_new ("deferred-activation-timeout", G_OBJECT_CLASS_TYPE (object_class), @@ -184,12 +193,6 @@ nm_act_request_new (NMConnection *connection, if (specific_object) priv->specific_object = g_strdup (specific_object); - id = g_signal_connect (priv->connection, - "secrets-updated", - G_CALLBACK (connection_secrets_updated_cb), - NM_ACT_REQUEST (obj)); - priv->secrets_updated_id = id; - return NM_ACT_REQUEST (obj); } @@ -237,13 +240,7 @@ connection_added_cb (NMManager *manager, return; clear_deferred_stuff (self); - priv->connection = g_object_ref (connection); - id = g_signal_connect (priv->connection, - "secrets-updated", - G_CALLBACK (connection_secrets_updated_cb), - self); - priv->secrets_updated_id = id; g_signal_emit (self, signals[DEFERRED_ACTIVATION_START], 0); } @@ -300,15 +297,116 @@ nm_act_request_is_deferred (NMActRequest *req) return priv->deferred_connection_path ? TRUE : FALSE; } -static void -connection_secrets_updated_cb (NMConnection *connection, - const char *setting_name, - NMActRequest *self) -{ - g_return_if_fail (setting_name != NULL); - g_return_if_fail (self != NULL); +typedef struct GetSecretsInfo { + NMActRequest *req; + char *setting_name; +} GetSecretsInfo; - g_signal_emit (self, signals[CONNECTION_SECRETS_UPDATED], 0, connection, setting_name); +static void +free_get_secrets_info (gpointer data) +{ + GetSecretsInfo *info = (GetSecretsInfo *) data; + + g_free (info->setting_name); + g_slice_free (GetSecretsInfo, info); +} + +static void +get_secrets_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +{ + GetSecretsInfo *info = (GetSecretsInfo *) user_data; + GError *err = NULL; + GHashTable *secrets = NULL; + NMActRequestPrivate *priv = NULL; + + g_return_if_fail (info != NULL); + g_return_if_fail (info->req); + g_return_if_fail (info->setting_name); + + priv = NM_ACT_REQUEST_GET_PRIVATE (info->req); + g_object_set_data (G_OBJECT (priv->connection), CONNECTION_GET_SECRETS_CALL_TAG, NULL); + + if (!dbus_g_proxy_end_call (proxy, call, &err, + dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), &secrets, + G_TYPE_INVALID)) { + nm_warning ("Couldn't get connection secrets: %s.", err->message); + g_error_free (err); + g_signal_emit (info->req, + signals[CONNECTION_SECRETS_FAILED], + 0, + priv->connection, + info->setting_name); + return; + } + + if (g_hash_table_size (secrets) > 0) { + nm_connection_update_secrets (priv->connection, info->setting_name, secrets); + g_signal_emit (info->req, + signals[CONNECTION_SECRETS_UPDATED], + 0, + priv->connection, + info->setting_name); + } else { + // FIXME: some better way to handle invalid message? + nm_warning ("GetSecrets call returned but no secrets were found."); + } + + g_hash_table_destroy (secrets); +} + +gboolean +nm_act_request_request_connection_secrets (NMActRequest *req, + const char *setting_name, + gboolean request_new) +{ + DBusGProxy *proxy; + DBusGProxyCall *call; + GetSecretsInfo *info = NULL; + NMActRequestPrivate *priv = NULL; + + g_return_val_if_fail (NM_IS_ACT_REQUEST (req), FALSE); + g_return_val_if_fail (setting_name != NULL, FALSE); + + priv = NM_ACT_REQUEST_GET_PRIVATE (req); + proxy = g_object_get_data (G_OBJECT (priv->connection), NM_MANAGER_CONNECTION_PROXY_TAG); + if (!DBUS_IS_G_PROXY (proxy)) { + nm_warning ("Couldn't get dbus proxy for connection."); + goto error; + } + + info = g_slice_new0 (GetSecretsInfo); + if (!info) { + nm_warning ("Not enough memory to get secrets"); + goto error; + } + + info->setting_name = g_strdup (setting_name); + if (!info->setting_name) { + nm_warning ("Not enough memory to get secrets"); + goto error; + } + + info->req = req; + call = dbus_g_proxy_begin_call_with_timeout (proxy, "GetSecrets", + get_secrets_cb, + info, + free_get_secrets_info, + G_MAXINT32, + G_TYPE_STRING, setting_name, + G_TYPE_BOOLEAN, request_new, + G_TYPE_INVALID); + if (!call) { + nm_warning ("Could not call GetSecrets"); + goto error; + } + + g_object_set_data (G_OBJECT (priv->connection), CONNECTION_GET_SECRETS_CALL_TAG, call); + return TRUE; + +error: + if (info) + free_get_secrets_info (info); + return FALSE; } NMConnection * diff --git a/src/nm-activation-request.h b/src/nm-activation-request.h index 4e211d262a..60ccc14a54 100644 --- a/src/nm-activation-request.h +++ b/src/nm-activation-request.h @@ -44,6 +44,9 @@ typedef struct { void (*connection_secrets_updated) (NMActRequest *req, NMConnection *connection, const char * setting); + void (*connection_secrets_failed) (NMActRequest *req, + NMConnection *connection, + const char * setting); void (*deferred_activation_timeout) (NMActRequest *req); void (*deferred_activation_start) (NMActRequest *req); } NMActRequestClass; @@ -62,6 +65,9 @@ NMActRequest *nm_act_request_new_deferred (const char *service_name, gboolean nm_act_request_is_deferred (NMActRequest *req); NMConnection *nm_act_request_get_connection (NMActRequest *req); +gboolean nm_act_request_request_connection_secrets (NMActRequest *req, + const char *setting_name, + gboolean request_new); const char * nm_act_request_get_specific_object(NMActRequest *req); gboolean nm_act_request_get_user_requested (NMActRequest *req); diff --git a/src/nm-device-802-11-wireless.c b/src/nm-device-802-11-wireless.c index 686af1d893..452157fa0a 100644 --- a/src/nm-device-802-11-wireless.c +++ b/src/nm-device-802-11-wireless.c @@ -1954,6 +1954,7 @@ link_timeout_cb (gpointer user_data) " asking for new key.", nm_device_get_iface (dev)); cleanup_association_attempt (self, TRUE); nm_device_state_changed (dev, NM_DEVICE_STATE_NEED_AUTH); + nm_act_request_request_connection_secrets (req, setting_name, TRUE); return FALSE; @@ -2340,12 +2341,19 @@ supplicant_connection_timeout_cb (gpointer user_data) nm_device_get_iface (dev)); nm_device_state_changed (dev, NM_DEVICE_STATE_FAILED); } else { + const char *setting_name; + /* Authentication failed, encryption key is probably bad */ nm_info ("Activation (%s/wireless): association took too long, " "asking for new key.", nm_device_get_iface (dev)); nm_device_state_changed (dev, NM_DEVICE_STATE_NEED_AUTH); + + nm_connection_clear_secrets (connection); + setting_name = nm_connection_need_secrets (connection); + if (setting_name) + nm_act_request_request_connection_secrets (req, setting_name, TRUE); } return FALSE; @@ -2532,6 +2540,7 @@ real_act_stage2_config (NMDevice *dev) iface, s_connection->name); nm_device_state_changed (dev, NM_DEVICE_STATE_NEED_AUTH); + nm_act_request_request_connection_secrets (req, setting_name, FALSE); return NM_ACT_STAGE_RETURN_POSTPONE; } else { NMSettingWireless *s_wireless = (NMSettingWireless *) nm_connection_get_setting (connection, NM_SETTING_WIRELESS); @@ -2677,6 +2686,7 @@ real_act_stage4_ip_config_timeout (NMDevice *dev, auth_enforced = ap_auth_enforced (connection, ap, &encrypted); if (encrypted && !auth_enforced) { const GByteArray * ssid = nm_ap_get_ssid (ap); + const char *setting_name; /* Activation failed, we must have bad encryption key */ nm_debug ("Activation (%s/wireless): could not get IP configuration " @@ -2684,6 +2694,12 @@ real_act_stage4_ip_config_timeout (NMDevice *dev, nm_device_get_iface (dev), ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)"); nm_device_state_changed (dev, NM_DEVICE_STATE_NEED_AUTH); + + nm_connection_clear_secrets (connection); + setting_name = nm_connection_need_secrets (connection); + if (setting_name) + nm_act_request_request_connection_secrets (req, setting_name, TRUE); + ret = NM_ACT_STAGE_RETURN_POSTPONE; } else if (nm_ap_get_mode (ap) == IW_MODE_ADHOC) { NMDevice80211WirelessClass * klass; diff --git a/src/nm-device.c b/src/nm-device.c index 5076bf51df..1eb458e6ad 100644 --- a/src/nm-device.c +++ b/src/nm-device.c @@ -73,6 +73,7 @@ struct _NMDevicePrivate gulong act_deferred_start_id; guint act_source_id; gulong secrets_updated_id; + gulong secrets_failed_id; /* IP configuration info */ void * system_config_data; /* Distro-specific config data (parsed config file, etc) */ @@ -977,6 +978,12 @@ clear_act_request (NMDevice *self) priv->secrets_updated_id = 0; } + if (priv->secrets_failed_id) { + g_signal_handler_disconnect (priv->act_request, + priv->secrets_failed_id); + priv->secrets_failed_id = 0; + } + g_object_unref (priv->act_request); priv->act_request = NULL; } @@ -1114,6 +1121,17 @@ connection_secrets_updated_cb (NMActRequest *req, NM_DEVICE_GET_CLASS (self)->connection_secrets_updated (self, connection, setting_name); } +static void +connection_secrets_failed_cb (NMActRequest *req, + NMConnection *connection, + const char *setting_name, + gpointer user_data) +{ + NMDevice *self = NM_DEVICE (user_data); + + nm_device_interface_deactivate (NM_DEVICE_INTERFACE (self)); +} + static void deferred_activation_timeout_cb (NMActRequest *req, gpointer user_data) { @@ -1168,6 +1186,12 @@ device_activation_go (NMDevice *self) self); priv->secrets_updated_id = id; + id = g_signal_connect (priv->act_request, + "connection-secrets-failed", + G_CALLBACK (connection_secrets_failed_cb), + self); + priv->secrets_failed_id = id; + /* HACK: update the state a bit early to avoid a race between the * scheduled stage1 handler and nm_policy_device_change_check() thinking * that the activation request isn't deferred because the deferred bit diff --git a/src/nm-manager.c b/src/nm-manager.c index 56545b73e1..5fcb36b840 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -22,11 +22,6 @@ static gboolean impl_manager_legacy_state (NMManager *manager, guint32 *state, G static void nm_manager_connections_destroy (NMManager *manager, NMConnectionType type); static void manager_set_wireless_enabled (NMManager *manager, gboolean enabled); -static gboolean get_connection_secrets (NMManager *manager, - NMDeviceInterface *device, - NMConnection *connection, - const char *setting_name, - gboolean request_new); typedef struct { GSList *devices; @@ -66,8 +61,6 @@ enum { LAST_PROP }; -#define CONNECTION_GET_SECRETS_CALL_TAG "get-secrets-call" - static void nm_manager_init (NMManager *manager) { @@ -669,21 +662,6 @@ manager_device_state_changed (NMDeviceInterface *device, NMDeviceState state, gp NMManager *manager = NM_MANAGER (user_data); nm_manager_update_state (manager); - - if (state == NM_DEVICE_STATE_NEED_AUTH) { - NMActRequest *req; - NMConnection *connection; - - req = nm_device_get_act_request (NM_DEVICE (device)); - /* When device needs an auth it must be activating and thus have an act request. */ - g_assert (req); - connection = nm_act_request_get_connection (req); - - get_connection_secrets (manager, device, - connection, - nm_connection_need_secrets (connection), - TRUE); - } } void @@ -1019,138 +997,3 @@ nm_manager_update_connections (NMManager *manager, nm_manager_connections_destroy (manager, type); } -typedef struct GetSecretsInfo { - NMManager *manager; - NMConnection *connection; - NMDeviceInterface *device; - char *setting_name; -} GetSecretsInfo; - -static void -free_get_secrets_info (gpointer data) -{ - GetSecretsInfo * info = (GetSecretsInfo *) data; - - g_free (info->setting_name); - if (info->connection) - g_object_unref (info->connection); - if (info->device) - g_object_unref (info->device); - g_slice_free (GetSecretsInfo, info); -} - -static void -get_secrets_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) -{ - GetSecretsInfo *info = (GetSecretsInfo *) user_data; - GError *err = NULL; - GHashTable *secrets = NULL; - - g_return_if_fail (info != NULL); - g_return_if_fail (info->manager); - g_return_if_fail (info->connection); - g_return_if_fail (info->setting_name); - g_return_if_fail (info->device); - - g_object_set_data (G_OBJECT (info->connection), CONNECTION_GET_SECRETS_CALL_TAG, NULL); - - if (!dbus_g_proxy_end_call (proxy, call, &err, - dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), &secrets, - G_TYPE_INVALID)) { - nm_warning ("Couldn't get connection secrets: %s.", err->message); - g_error_free (err); - nm_device_interface_deactivate (info->device); - return; - } - - if (g_hash_table_size (secrets) > 0) { - nm_connection_update_secrets (info->connection, info->setting_name, secrets); - // FIXME: some better way to handle invalid message? - } else { - nm_warning ("GetSecrets call returned but no secrets were found."); - } - - g_hash_table_destroy (secrets); -} - -static gboolean -get_connection_secrets (NMManager *manager, - NMDeviceInterface *device, - NMConnection *connection, - const char *setting_name, - gboolean request_new) -{ - DBusGProxy *proxy; - GetSecretsInfo *info = NULL; - DBusGProxyCall *call; - - g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE); - g_return_val_if_fail (NM_IS_DEVICE_INTERFACE (device), FALSE); - g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); - - proxy = g_object_get_data (G_OBJECT (connection), NM_MANAGER_CONNECTION_PROXY_TAG); - if (!DBUS_IS_G_PROXY (proxy)) { - nm_warning ("Couldn't get dbus proxy for connection."); - goto error; - } - - info = g_slice_new0 (GetSecretsInfo); - if (!info) { - nm_warning ("Not enough memory to get secrets"); - goto error; - } - - info->setting_name = g_strdup (setting_name); - if (!info->setting_name) { - nm_warning ("Not enough memory to get secrets"); - goto error; - } - - info->connection = g_object_ref (connection); - info->manager = manager; - info->device = g_object_ref (device); - - call = dbus_g_proxy_begin_call_with_timeout (proxy, "GetSecrets", - get_secrets_cb, - info, - free_get_secrets_info, - G_MAXINT32, - G_TYPE_STRING, setting_name, - G_TYPE_BOOLEAN, request_new, - G_TYPE_INVALID); - if (!call) { - nm_warning ("Could not call GetSecrets"); - goto error; - } - - g_object_set_data (G_OBJECT (connection), CONNECTION_GET_SECRETS_CALL_TAG, call); - return TRUE; - -error: - if (info) - free_get_secrets_info (info); - return FALSE; -} - -void -nm_manager_cancel_get_connection_secrets (NMManager *manager, - NMConnection *connection) -{ - DBusGProxyCall *call; - DBusGProxy *proxy; - - g_return_if_fail (NM_IS_MANAGER (manager)); - g_return_if_fail (NM_IS_CONNECTION (connection)); - - proxy = g_object_get_data (G_OBJECT (connection), NM_MANAGER_CONNECTION_PROXY_TAG); - if (!DBUS_IS_G_PROXY (proxy)) - return; - - call = g_object_get_data (G_OBJECT (connection), CONNECTION_GET_SECRETS_CALL_TAG); - if (!call) - return; - - dbus_g_proxy_cancel_call (proxy, call); - g_object_set_data (G_OBJECT (connection), CONNECTION_GET_SECRETS_CALL_TAG, NULL); -} - diff --git a/src/nm-manager.h b/src/nm-manager.h index bf510ac27c..80f912c99c 100644 --- a/src/nm-manager.h +++ b/src/nm-manager.h @@ -79,7 +79,4 @@ const char * nm_manager_get_connection_service_name (NMManager *manager, const char * nm_manager_get_connection_dbus_path (NMManager *manager, NMConnection *connection); -void nm_manager_cancel_get_connection_secrets (NMManager *manager, - NMConnection *connection); - #endif /* NM_MANAGER_H */