2006-08-10 Dan Williams <dcbw@redhat.com>

Patch from Valentine Sinitsyn <e_val@inbox.ru>
	* src/nm-ap-security.c
	  src/nm-ap-security.h
		- Add authentication_required bits for subclasses to specify whether
		or not real authentication is required for connections, i.e. whether
		the AP rejects us when an encryption key is wrong or not.

	* src/nm-ap-security-wep.c
	  src/nm-ap-security-wpa-eap.c
	  src/nm-ap-security-wpa-psk.c
	  src/nm-ap-security-leap.c
		- Implement authentication_required appropriately for each method

	* src/nm-device-802-11-wireless.c
		- Be smarter about when to request a key; for example, using a wrong key
		in WEP shared key mode previously just timed out and did not request
		a new key


git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@1954 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
This commit is contained in:
Dan Williams
2006-08-14 03:11:03 +00:00
parent f8a6ec456c
commit b86656efb7
8 changed files with 186 additions and 12 deletions

View File

@@ -1,3 +1,23 @@
2006-08-10 Dan Williams <dcbw@redhat.com>
Patch from Valentine Sinitsyn <e_val@inbox.ru>
* src/nm-ap-security.c
src/nm-ap-security.h
- Add authentication_required bits for subclasses to specify whether
or not real authentication is required for connections, i.e. whether
the AP rejects us when an encryption key is wrong or not.
* src/nm-ap-security-wep.c
src/nm-ap-security-wpa-eap.c
src/nm-ap-security-wpa-psk.c
src/nm-ap-security-leap.c
- Implement authentication_required appropriately for each method
* src/nm-device-802-11-wireless.c
- Be smarter about when to request a key; for example, using a wrong key
in WEP shared key mode previously just timed out and did not request
a new key
2006-08-13 Dan Williams <dcbw@redhat.com>
* gnome/libnm_glib/libnm_glib.c

View File

@@ -152,6 +152,13 @@ real_get_default_capabilities (NMAPSecurity *instance)
return caps;
}
static gboolean
real_get_authentication_required (NMAPSecurity *instance)
{
/* LEAP always requires authentication. */
return TRUE;
}
static NMAPSecurity *
real_copy_constructor (NMAPSecurity *instance)
{
@@ -186,6 +193,7 @@ nm_ap_security_leap_class_init (NMAPSecurityLEAPClass *klass)
par_class->serialize_func = real_serialize;
par_class->write_supplicant_config_func = real_write_supplicant_config;
par_class->get_default_capabilities_func = real_get_default_capabilities;
par_class->get_authentication_required_func = real_get_authentication_required;
g_type_class_add_private (object_class, sizeof (NMAPSecurityLEAPPrivate));
}

View File

@@ -174,6 +174,13 @@ real_get_default_capabilities (NMAPSecurity *instance)
return caps;
}
static gboolean
real_get_authentication_required (NMAPSecurity *instance)
{
/* WEP really requires authentication in Shared mode only */
return (get_auth_algorithm (NM_AP_SECURITY_WEP (instance)) == IW_AUTH_ALG_SHARED_KEY);
}
static NMAPSecurity *
real_copy_constructor (NMAPSecurity *instance)
{
@@ -202,6 +209,7 @@ nm_ap_security_wep_class_init (NMAPSecurityWEPClass *klass)
par_class->serialize_func = real_serialize;
par_class->write_supplicant_config_func = real_write_supplicant_config;
par_class->get_default_capabilities_func = real_get_default_capabilities;
par_class->get_authentication_required_func = real_get_authentication_required;
g_type_class_add_private (object_class, sizeof (NMAPSecurityWEPPrivate));
}

View File

@@ -321,6 +321,13 @@ real_get_default_capabilities (NMAPSecurity *instance)
return caps;
}
static gboolean
real_get_authentication_required (NMAPSecurity *instance)
{
/* WPA Enterprise is all about strong security */
return TRUE;
}
static NMAPSecurity *
real_copy_constructor (NMAPSecurity *instance)
{
@@ -372,6 +379,7 @@ nm_ap_security_wpa_eap_class_init (NMAPSecurityWPA_EAPClass *klass)
par_class->serialize_func = real_serialize;
par_class->write_supplicant_config_func = real_write_supplicant_config;
par_class->get_default_capabilities_func = real_get_default_capabilities;
par_class->get_authentication_required_func = real_get_authentication_required;
g_type_class_add_private (object_class, sizeof (NMAPSecurityWPA_EAPPrivate));
}

View File

@@ -234,6 +234,13 @@ real_get_default_capabilities (NMAPSecurity *instance)
return caps;
}
static gboolean
real_get_authentication_required (NMAPSecurity *instance)
{
/* WPA Personal always requires authentication in the infrastructure mode. */
return TRUE;
}
static NMAPSecurity *
real_copy_constructor (NMAPSecurity *instance)
{
@@ -264,6 +271,7 @@ nm_ap_security_wpa_psk_class_init (NMAPSecurityWPA_PSKClass *klass)
par_class->serialize_func = real_serialize;
par_class->write_supplicant_config_func = real_write_supplicant_config;
par_class->get_default_capabilities_func = real_get_default_capabilities;
par_class->get_authentication_required_func = real_get_authentication_required;
g_type_class_add_private (object_class, sizeof (NMAPSecurityWPA_PSKPrivate));
}

View File

@@ -158,6 +158,14 @@ nm_ap_security_get_default_capabilities (NMAPSecurity *self)
return NM_AP_SECURITY_GET_CLASS (self)->get_default_capabilities_func (self);
}
gboolean
nm_ap_security_get_authentication_required (NMAPSecurity *self)
{
g_return_val_if_fail (self != NULL, FALSE);
return NM_AP_SECURITY_GET_CLASS (self)->get_authentication_required_func (self);
}
gboolean
nm_ap_security_write_supplicant_config (NMAPSecurity *self,

View File

@@ -70,6 +70,7 @@ struct _NMAPSecurityClass
gboolean adhoc);
guint32 (*get_default_capabilities_func)(NMAPSecurity *self);
gboolean (*get_authentication_required_func)(NMAPSecurity *self);
};
@@ -99,6 +100,8 @@ const char * nm_ap_security_get_description (NMAPSecurity *self);
guint32 nm_ap_security_get_default_capabilities (NMAPSecurity *self);
gboolean nm_ap_security_get_authentication_required (NMAPSecurity *self);
G_END_DECLS
#endif /* NM_AP_SECURITY_H */

View File

@@ -2333,6 +2333,62 @@ ap_need_key (NMDevice80211Wireless *self,
}
/*
* ap_is_auth_required
*
* Checks whether or not there is an encryption key present for
* this connection, and whether or not the authentication method
* in use will result in an authentication rejection if the key
* is wrong. For example, Ad Hoc mode networks don't have a
* master node and therefore nothing exists to reject the station.
* Similarly, Open System WEP access points don't reject a station
* when the key is wrong. Shared Key WEP access points will.
*
* Theory of operation here is that if:
* (a) the NMAPSecurity object specifies that authentication is
* required, and the AP rejects our authentication attempt during
* connection (which shows up as a wpa_supplicant disconnection
* event); or
* (b) the NMAPSecurity object specifies that no authentiation is
* required, and either DHCP times out or wpa_supplicant times out;
*
* then we need a new key from the user because our currenty key
* and/or authentication method is likely wrong.
*
*/
static gboolean
ap_is_auth_required (NMAccessPoint *ap, gboolean *has_key)
{
NMAPSecurity *security;
int we_cipher;
gboolean auth_required = FALSE;
g_return_val_if_fail (ap != NULL, FALSE);
g_return_val_if_fail (has_key != NULL, FALSE);
*has_key = FALSE;
/* Ad Hoc mode doesn't have any master station to validate
* security credentials, so no auth can possibly be required.
*/
if (nm_ap_get_mode(ap) == IW_MODE_ADHOC)
return FALSE;
/* No encryption obviously means no possiblity of auth
* rejection due to a wrong encryption key.
*/
security = nm_ap_get_security (ap);
we_cipher = nm_ap_security_get_we_cipher (security);
if (we_cipher == IW_AUTH_CIPHER_NONE)
return FALSE;
auth_required = nm_ap_security_get_authentication_required (security);
*has_key = TRUE;
return auth_required;
}
/****************************************************************************/
/* WPA Supplicant control stuff
*
@@ -2459,15 +2515,42 @@ supplicant_watch_cb (GPid pid,
}
/*
* link_timeout_cb
*
* Called when the link to the access point has been down for a specified
* period of time.
*/
static gboolean
link_timeout_cb (gpointer user_data)
{
NMDevice * dev = NM_DEVICE (user_data);
NMDevice * dev = NM_DEVICE (user_data);
NMDevice80211Wireless * self = NM_DEVICE_802_11_WIRELESS (user_data);
NMActRequest * req = nm_device_get_act_request (dev);
NMAccessPoint * ap = nm_act_request_get_ap (req);
NMData * data = nm_device_get_app_data (dev);
gboolean has_key;
g_assert (dev);
nm_info ("%s: link timed out.", nm_device_get_iface (dev));
nm_device_set_active_link (dev, FALSE);
/* Disconnect event during initial authentication and credentials
* ARE checked - we are likely to have wrong key. Ask the user for
* another one.
*/
if ( (nm_act_request_get_stage (req) == NM_ACT_STAGE_DEVICE_CONFIG)
&& (ap_is_auth_required (ap, &has_key) && has_key))
{
/* Association/authentication failed, we must have bad encryption key */
nm_info ("Activation (%s/wireless): disconnected during association,"
" asking for new key.", nm_device_get_iface (dev));
supplicant_remove_timeout(self);
nm_dbus_get_user_key_for_network (data->dbus_connection, req, TRUE);
}
else
{
nm_info ("%s: link timed out.", nm_device_get_iface (dev));
nm_device_set_active_link (dev, FALSE);
}
return FALSE;
}
@@ -2561,19 +2644,43 @@ get_supplicant_timeout (NMDevice80211Wireless *self)
}
/*
* supplicant_timeout_cb
*
* Called when the supplicant has been unable to connect to an access point
* within a specified period of time.
*/
static gboolean
supplicant_timeout_cb (gpointer user_data)
{
NMDevice * dev = NM_DEVICE (user_data);
NMDevice80211Wireless * self = NM_DEVICE_802_11_WIRELESS (user_data);
NMActRequest * req = nm_device_get_act_request (dev);
NMAccessPoint * ap = nm_act_request_get_ap (req);
NMData * data = nm_device_get_app_data (dev);
gboolean has_key;
g_assert (self);
nm_info ("Activation (%s/wireless): association took too long (>%us), failing activation.",
nm_device_get_iface (dev), get_supplicant_timeout (self));
if (nm_device_is_activating (dev))
nm_policy_schedule_activation_failed (nm_device_get_act_request (dev));
/* Timed out waiting for authentication success; if the security method
* in use does not require access point side authentication (Open System
* WEP, for example) then we are likely using the wrong authentication
* algorithm or key. Request new one from the user.
*/
if (!ap_is_auth_required (ap, &has_key) && has_key)
{
/* Activation failed, we must have bad encryption key */
nm_info ("Activation (%s/wireless): association took too long (>%us), asking for new key.",
nm_device_get_iface (dev), get_supplicant_timeout (self));
nm_dbus_get_user_key_for_network (data->dbus_connection, req, TRUE);
}
else
{
nm_info ("Activation (%s/wireless): association took too long (>%us), failing activation.",
nm_device_get_iface (dev), get_supplicant_timeout (self));
if (nm_device_is_activating (dev))
nm_policy_schedule_activation_failed (nm_device_get_act_request (dev));
}
return FALSE;
}
@@ -3034,6 +3141,7 @@ real_act_stage4_ip_config_timeout (NMDevice *dev,
NMIP4Config * real_config = NULL;
NMAPSecurity * security;
NMData * data;
gboolean has_key;
g_return_val_if_fail (config != NULL, NM_ACT_STAGE_RETURN_FAILURE);
g_return_val_if_fail (*config == NULL, NM_ACT_STAGE_RETURN_FAILURE);
@@ -3046,10 +3154,13 @@ real_act_stage4_ip_config_timeout (NMDevice *dev,
security = nm_ap_get_security (ap);
g_assert (security);
/* FIXME: should we only ask for a new key if the activation request is user-requested? */
if (nm_ap_security_get_we_cipher (security) != IW_AUTH_CIPHER_NONE)
/* If the security credentials' validity was not checked by any
* peer during authentication process, and DHCP times out, then
* the encryption key is likely wrong. Ask the user for a new one.
*/
if (!ap_is_auth_required (ap, &has_key) && has_key)
{
/* Activation failed, we must have bad WEP key */
/* Activation failed, we must have bad encryption key */
nm_debug ("Activation (%s/wireless): could not get IP configuration info for '%s', asking for new key.",
nm_device_get_iface (dev), nm_ap_get_essid (ap) ? nm_ap_get_essid (ap) : "(none)");
nm_dbus_get_user_key_for_network (data->dbus_connection, req, TRUE);