[Dextrose] [PATCH sucrose-0.94][RFC] Add capability to connect to WPA/WPA2-Enterprise networks
Anish Mangal
anish at activitycentral.org
Fri Dec 2 05:10:49 EST 2011
From: Ajay Garg <ajay at sugarlabs.org>
As per user-workflow, there is no difference :-
---------------------------------------------------------------
1a. The (WPA/WPA2-Enterprise) network-icon is available on the
neighbourhood-view.
1b. Upon clicking the network-icon, a popup dialog appears, asking for
parameters.
1c. Upon clicking ok, the connection is made (shown by the
'Network-Connected'-icon in the tray).
2. If the connection is made successfully, the network-profile is saved
in "connections.cfg". From next reboot onwards, the connection is made
automatically.
Configurations :-
------------------------
Following configurations have been tested to work :
1. Tunnelled TLS (TTLS)
2. Protected EAP (PEAP)
Following configurations are still to be tested :
1. LEAP (seems that it requires support from the access-point).
2. TLS (the testing couldn't be done, even with nm-applet. Would
like to hear if anyone gets it working with nm-applet, since the
sugar-parameters-UI is modelled on nm-applet-UI.)
The patch contains the UI-frontend code for entering all 4
configuration parameters (modelled on nm-applet's "Connect
to Hidden Wireless Network" -> "WPA/WPA2 Enterprise".
Signed-off-by: Ajay Garg <ajay at activitycentral.com>
Tested-by: Anish Mangal <anish at activitycentral.com>
---
src/jarabe/desktop/keydialog.py | 174 +++++++++++++++++++++++++-
src/jarabe/desktop/networkviews.py | 248 +++++++++++++++++++++++++++++++++++-
src/jarabe/model/network.py | 22 +++-
3 files changed, 437 insertions(+), 7 deletions(-)
diff --git a/src/jarabe/desktop/keydialog.py b/src/jarabe/desktop/keydialog.py
index c72f498..9a1675c 100644
--- a/src/jarabe/desktop/keydialog.py
+++ b/src/jarabe/desktop/keydialog.py
@@ -32,6 +32,10 @@ WEP_PASSPHRASE = 1
WEP_HEX = 2
WEP_ASCII = 3
+SETTING_TYPE_STRING = 1
+SETTING_TYPE_LIST = 2
+
+
def string_is_hex(key):
is_hex = True
@@ -120,6 +124,158 @@ class KeyDialog(gtk.Dialog):
return self._response
+# Plain Old Python Object (POPO)
+class NetworkParametersPOPO(gtk.HBox):
+ def __init__(self, auth_param):
+ gtk.HBox.__init__(self, homogeneous=True)
+ self._key = auth_param._key_name
+ self._label = gtk.Label(_(auth_param._key_label))
+ self._key_type = auth_param._key_type
+
+ # Decide, if we need to show a 'entry',
+ # or a 'list-store'
+ if len(auth_param._options) == 0:
+ self._show_entry = True
+ else:
+ self._show_entry = False
+
+ self.pack_start(self._label)
+ self._label.show()
+
+ if self._show_entry:
+ self._entry = gtk.Entry()
+ self.pack_start(self._entry)
+ self._entry.show()
+ else:
+ self._option_store = gtk.ListStore(str, str)
+ for option in auth_param._options:
+ self._option_store.append(option)
+
+ self._list_store_entry = auth_param._options[0][1]
+ self._option_combo = gtk.ComboBox(self._option_store)
+ cell = gtk.CellRendererText()
+ self._option_combo.pack_start(cell, True)
+ self._option_combo.add_attribute(cell, 'text', 0)
+ self._option_combo.set_active(0)
+ self._option_combo.connect('changed',
+ self._option_combo_changed_cb)
+ self.pack_start(self._option_combo)
+ self.show()
+ self._option_combo.show()
+
+ def _option_combo_changed_cb(self, widget):
+ it = self._option_combo.get_active_iter()
+ (value, ) = self._option_store.get(it, 1)
+ self._list_store_entry = value
+
+ def _get_key(self):
+ return self._key
+
+ def _get_value(self):
+ if self._show_entry:
+ return self._entry.get_text()
+ else:
+ return self._list_store_entry
+
+
+class KeyValuesDialog(gtk.Dialog):
+ def __init__(self, auth_lists, final_callback, uuid, settings):
+ gtk.Dialog.__init__(self, flags=gtk.DIALOG_MODAL)
+ self.set_title(_('Wireless Parameters required'))
+
+ self._auth_lists = auth_lists
+ self._final_callback = final_callback
+ self._uuid = uuid
+ self._settings = settings
+
+ label = gtk.Label(_("Please enter parameters\n"))
+ self.vbox.pack_start(label)
+
+ self._auth_type_store = gtk.ListStore(str, str)
+ for auth_list in self._auth_lists:
+ self._auth_type_store.append([auth_list._auth_label,
+ auth_list._auth_type])
+
+ self._auth_type_combo = gtk.ComboBox(self._auth_type_store)
+ cell = gtk.CellRendererText()
+ self._auth_type_combo.pack_start(cell, True)
+ self._auth_type_combo.add_attribute(cell, 'text', 0)
+ self._auth_type_combo.set_active(0)
+ self._auth_type_combo.connect('changed',
+ self._auth_type_combo_changed_cb)
+ self._auth_type_box = gtk.HBox(homogeneous=True)
+ self._auth_label = gtk.Label(_('Authentication'))
+ self._auth_type_box.pack_start(self._auth_label, expand=False)
+ self._auth_type_box.pack_start(self._auth_type_combo,
+ expand=False)
+ self.vbox.pack_start(self._auth_type_box)
+ self._auth_label.show()
+ self._auth_type_combo.show()
+
+ self.add_buttons(gtk.STOCK_OK, gtk.RESPONSE_OK)
+ self.set_default_response(gtk.RESPONSE_OK)
+ self.set_has_separator(True)
+
+ self.connect('response', self._fetch_values)
+
+ auth_type = self._auth_lists[0]._auth_type
+ self._selected_auth_list = self._select_auth_list(auth_type)
+ self._add_key_value('eap', auth_type)
+ self._add_container_box()
+
+ def _auth_type_combo_changed_cb(self, widget):
+ it = self._auth_type_combo.get_active_iter()
+ (auth_type, ) = self._auth_type_store.get(it, 1)
+ self._selected_auth_list = self._select_auth_list(auth_type)
+ self._add_key_value('eap', auth_type)
+ self._reset()
+
+ def _select_auth_list(self, auth_type):
+ for auth_list in self._auth_lists:
+ if auth_list._params_list[0]._options[0][1] == auth_type:
+ return auth_list
+
+ def _populate_auth_params(self, auth_list):
+ for auth_param in auth_list._params_list[1:]:
+ obj = NetworkParametersPOPO(auth_param)
+ self._key_values_box.pack_start(obj)
+ obj.show()
+
+ def _reset(self):
+ self.vbox.remove(self._key_values_box)
+ self._add_container_box()
+
+ def _add_container_box(self):
+ self._key_values_box = gtk.VBox()
+ self.vbox.pack_start(self._key_values_box)
+ self._key_values_box.show()
+ self._populate_auth_params(self._selected_auth_list)
+
+ def _remove_all_params(self):
+ self._key_values_box.remove_all()
+
+ def _fetch_values(self, key_dialog, response_id):
+ if response_id == gtk.RESPONSE_OK:
+ for child in self._key_values_box.get_children():
+ key = child._get_key()
+ value = child._get_value()
+ self._add_key_value(key, value)
+
+ key_dialog.destroy()
+ self._final_callback(self._uuid, self._settings,
+ self._selected_auth_list)
+
+ def _add_key_value(self, key, value):
+ for auth_param in self._selected_auth_list._params_list:
+ if auth_param._key_name == key:
+ if auth_param._key_type == SETTING_TYPE_STRING:
+ auth_param._value = value
+ elif auth_param._key_type == SETTING_TYPE_LIST:
+ values = []
+ values.append(value)
+ auth_param._value = values
+
+
class WEPKeyDialog(KeyDialog):
def __init__(self, ssid, flags, wpa_flags, rsn_flags, dev_caps, settings,
response):
@@ -218,7 +374,7 @@ class WEPKeyDialog(KeyDialog):
self.set_response_sensitive(gtk.RESPONSE_OK, valid)
-class WPAKeyDialog(KeyDialog):
+class WPAPersonalKeyDialog(KeyDialog):
def __init__(self, ssid, flags, wpa_flags, rsn_flags, dev_caps, settings,
response):
KeyDialog.__init__(self, ssid, flags, wpa_flags, rsn_flags,
@@ -296,14 +452,26 @@ def create(ssid, flags, wpa_flags, rsn_flags, dev_caps, settings, response):
rsn_flags == network.NM_802_11_AP_SEC_NONE:
key_dialog = WEPKeyDialog(ssid, flags, wpa_flags, rsn_flags,
dev_caps, settings, response)
- else:
- key_dialog = WPAKeyDialog(ssid, flags, wpa_flags, rsn_flags,
+ elif (wpa_flags & network.NM_802_11_AP_SEC_KEY_MGMT_PSK) or \
+ (rsn_flags & network.NM_802_11_AP_SEC_KEY_MGMT_PSK):
+ key_dialog = WPAPersonalKeyDialog(ssid, flags, wpa_flags, rsn_flags,
dev_caps, settings, response)
+ elif (wpa_flags & network.NM_802_11_AP_SEC_KEY_MGMT_802_1X) or \
+ (rsn_flags & network.NM_802_11_AP_SEC_KEY_MGMT_802_1X):
+ # nothing. All details are asked for WPA/WPA2-Enterprise
+ # networks, before the conneection-activation is done.
+ pass
key_dialog.connect('response', _key_dialog_response_cb)
key_dialog.show_all()
+def get_key_values(key_list, final_callback, uuid, settings):
+ key_dialog = KeyValuesDialog(key_list, final_callback,
+ uuid, settings)
+ key_dialog.show_all()
+
+
def _key_dialog_response_cb(key_dialog, response_id):
response = key_dialog.get_response_object()
secrets = None
diff --git a/src/jarabe/desktop/networkviews.py b/src/jarabe/desktop/networkviews.py
index 2fb8593..738a142 100644
--- a/src/jarabe/desktop/networkviews.py
+++ b/src/jarabe/desktop/networkviews.py
@@ -22,6 +22,7 @@ import hashlib
import dbus
import glib
+import string
from sugar.graphics.icon import Icon
from sugar.graphics.xocolor import XoColor
@@ -56,6 +57,189 @@ _OLPC_MESH_ICON_NAME = 'network-mesh'
_FILTERED_ALPHA = 0.33
+SETTING_TYPE_STRING = 1
+SETTING_TYPE_LIST = 2
+
+
+class AuthenticationType:
+ def __init__(self, auth_label, auth_type, params_list):
+ self._auth_label = auth_label
+ self._auth_type = auth_type
+ self._params_list = params_list
+
+
+class AuthenticationParameter:
+ def __init__(self, key_name, key_label, key_type,
+ options):
+ self._key_name = key_name
+ self._key_label = key_label
+ self._key_type = key_type
+ self._options = options
+ self._value = None
+
+AUTHENTICATION_LIST = \
+ [
+ AuthenticationType('TLS',
+ 'tls',
+ [
+ AuthenticationParameter(
+ 'eap',
+ 'Authentication',
+ SETTING_TYPE_LIST,
+ [['TLS', 'tls']]
+ ),
+ AuthenticationParameter(
+ 'identity',
+ 'Identity',
+ SETTING_TYPE_STRING,
+ []
+ ),
+ AuthenticationParameter(
+ 'client_cert',
+ 'User certificate',
+ SETTING_TYPE_STRING,
+ []
+ ),
+ AuthenticationParameter(
+ 'ca_cert',
+ 'CA certificate',
+ SETTING_TYPE_STRING,
+ []
+ ),
+ AuthenticationParameter(
+ 'private_key',
+ 'Private key',
+ SETTING_TYPE_STRING,
+ []
+ ),
+ AuthenticationParameter(
+ 'private_key_password',
+ 'Private Key password',
+ SETTING_TYPE_STRING,
+ []
+ )
+ ]
+ ),
+ AuthenticationType('LEAP',
+ 'leap',
+ [
+ AuthenticationParameter(
+ 'eap',
+ 'Authentication',
+ SETTING_TYPE_LIST,
+ [['LEAP', 'leap']]
+ ),
+ AuthenticationParameter(
+ 'identity',
+ 'Username',
+ SETTING_TYPE_STRING,
+ []
+ ),
+ AuthenticationParameter(
+ 'password',
+ 'Password',
+ SETTING_TYPE_STRING,
+ []
+ )
+ ]
+ ),
+ AuthenticationType('Tunnelled TLS',
+ 'ttls',
+ [
+ AuthenticationParameter(
+ 'eap',
+ 'Authentication',
+ SETTING_TYPE_LIST,
+ [['Tunnelled TLS', 'ttls']]
+ ),
+ AuthenticationParameter(
+ 'anonymous_identity',
+ 'Anonymous identity',
+ SETTING_TYPE_STRING,
+ []
+ ),
+ AuthenticationParameter(
+ 'ca_cert',
+ 'CA certificate',
+ SETTING_TYPE_STRING,
+ []
+ ),
+ AuthenticationParameter(
+ 'phase2_auth',
+ 'Inner Authentication',
+ SETTING_TYPE_STRING,
+ [['PAP', 'pap'],
+ ['MSCHAP', 'mschap'],
+ ['MSCHAPv2', 'mschapv2'],
+ ['CHAP', 'chap']]
+ ),
+ AuthenticationParameter(
+ 'identity',
+ 'Username',
+ SETTING_TYPE_STRING,
+ []
+ ),
+ AuthenticationParameter(
+ 'password',
+ 'Password',
+ SETTING_TYPE_STRING,
+ []
+ )
+ ]
+ ),
+ AuthenticationType('Protected EAP (PEAP)',
+ 'peap',
+ [
+ AuthenticationParameter(
+ 'eap',
+ 'Authentication',
+ SETTING_TYPE_LIST,
+ [['Protected EAP (PEAP)', 'peap']]
+ ),
+ AuthenticationParameter(
+ 'anonymous_identity',
+ 'Anonymous identity',
+ SETTING_TYPE_STRING,
+ []
+ ),
+ AuthenticationParameter(
+ 'ca_cert',
+ 'CA certificate',
+ SETTING_TYPE_STRING,
+ []
+ ),
+ AuthenticationParameter(
+ 'peap_version',
+ 'PEAP version',
+ SETTING_TYPE_STRING,
+ [['Automatic', ''],
+ ['Version 0', '0'],
+ ['Version 1', '1']]
+ ),
+ AuthenticationParameter(
+ 'phase2_auth',
+ 'Inner Authentication',
+ SETTING_TYPE_STRING,
+ [['MSCHAPv2', 'mschapv2'],
+ ['MD5', 'md5'],
+ ['GTC', 'gtc']]
+ ),
+ AuthenticationParameter(
+ 'identity',
+ 'Username',
+ SETTING_TYPE_STRING,
+ []
+ ),
+ AuthenticationParameter(
+ 'password',
+ 'Password',
+ SETTING_TYPE_STRING,
+ []
+ )
+ ]
+ )
+ ]
+
class WirelessNetworkView(CanvasPulsingIcon):
def __init__(self, initial_ap):
@@ -340,6 +524,62 @@ class WirelessNetworkView(CanvasPulsingIcon):
wireless_security.group = group
return wireless_security
+ if (self._rsn_flags & network.NM_802_11_AP_SEC_KEY_MGMT_802_1X) and \
+ (self._device_caps & network.NM_802_11_DEVICE_CAP_RSN):
+ # WPA2 Enterprise
+ pairwise = self._add_ciphers_from_flags(self._rsn_flags, True)
+ group = self._add_ciphers_from_flags(self._rsn_flags, False)
+ wireless_security = WirelessSecurity()
+ wireless_security.key_mgmt = 'wpa-eap'
+ wireless_security.proto = 'rsn'
+ wireless_security.pairwise = pairwise
+ wireless_security.group = group
+ return wireless_security
+
+ if (self._wpa_flags & network.NM_802_11_AP_SEC_KEY_MGMT_802_1X) and \
+ (self._device_caps & network.NM_802_11_DEVICE_CAP_WPA):
+ # WPA Enterprise
+ pairwise = self._add_ciphers_from_flags(self._wpa_flags, True)
+ group = self._add_ciphers_from_flags(self._wpa_flags, False)
+ wireless_security = WirelessSecurity()
+ wireless_security.key_mgmt = 'wpa-eap'
+ wireless_security.proto = 'wpa'
+ wireless_security.pairwise = pairwise
+ wireless_security.group = group
+ return wireless_security
+
+ def _enter_additional_settings_and_secrets_and_then_activate(self,
+ uuid, settings, wireless_security):
+ # this is valid, only for "ieee8021x" or "wpa-eap" key
+ # management.
+ if (wireless_security.key_mgmt == 'ieee8021x') or \
+ (wireless_security.key_mgmt == 'wpa-eap'):
+ keydialog.get_key_values(AUTHENTICATION_LIST,
+ self.__add_and_activate_connection,
+ uuid, settings)
+ else:
+ self.__add_and_activate_connection(uuid, settings)
+
+ def __add_and_activate_connection(self, uuid, settings,
+ additional_settings=None):
+
+ if additional_settings is not None:
+ key_value_dict = {}
+ auth_params_list = additional_settings._params_list
+
+ for auth_param in auth_params_list:
+ key = auth_param._key_name
+ value = auth_param._value
+ print 'key == ' + key
+ print 'value == '
+ print value
+ key_value_dict[key] = value
+
+ settings.wpa_eap_setting = key_value_dict
+
+ connection = network.add_connection(uuid, settings)
+ self._activate_connection(connection)
+
def __connect_activate_cb(self, icon):
self._connect()
@@ -350,8 +590,10 @@ class WirelessNetworkView(CanvasPulsingIcon):
connection = network.find_connection_by_ssid(self._name)
if connection is None:
settings = Settings()
+ self._settings = settings
settings.connection.id = 'Auto ' + self._name
uuid = settings.connection.uuid = unique_id()
+ self._uuid = uuid
settings.connection.type = '802-11-wireless'
settings.wireless.ssid = self._name
@@ -370,8 +612,12 @@ class WirelessNetworkView(CanvasPulsingIcon):
if wireless_security is not None:
settings.wireless.security = '802-11-wireless-security'
- connection = network.add_connection(uuid, settings)
+ self._enter_additional_settings_and_secrets_and_then_activate(uuid,
+ settings, wireless_security)
+ else:
+ self._activate_connection(connection)
+ def _activate_connection(self, connection):
obj = self._bus.get_object(_NM_SERVICE, _NM_PATH)
netmgr = dbus.Interface(obj, _NM_IFACE)
diff --git a/src/jarabe/model/network.py b/src/jarabe/model/network.py
index f265ae4..2f8295e 100644
--- a/src/jarabe/model/network.py
+++ b/src/jarabe/model/network.py
@@ -418,6 +418,7 @@ class Settings(object):
self.connection = Connection()
self.ip4_config = None
self.wireless_security = None
+ self.wpa_eap_setting = None
if wireless_cfg is not None:
self.wireless = wireless_cfg
@@ -433,6 +434,10 @@ class Settings(object):
self.wireless_security.get_dict()
if self.ip4_config is not None:
settings['ipv4'] = self.ip4_config.get_dict()
+ if self.wpa_eap_setting is not None:
+ settings['802-1x'] = self.wpa_eap_setting
+
+
return settings
@@ -653,6 +658,9 @@ class NMSettingsConnection(dbus.service.Object):
if self._settings.wireless.security is not None:
config.set(identifier, 'security',
self._settings.wireless.security)
+ if self._settings.wpa_eap_setting is not None:
+ config.set(identifier, 'wpa_eap_setting',
+ self._settings.wpa_eap_setting)
if self._secrets is not None:
if self._settings.wireless_security.key_mgmt == 'none':
config.set(identifier, 'key', self._secrets.wep_key)
@@ -895,13 +903,21 @@ def load_wifi_connections():
settings.wireless_security.key_mgmt = mgmt
security = config.get(section, 'security')
settings.wireless.security = security
- key = config.get(section, 'key')
if mgmt == 'none':
+ key = config.get(section, 'key')
secrets.wep_key = key
auth_alg = config.get(section, 'auth-alg')
secrets.auth_alg = auth_alg
- elif mgmt == 'wpa-psk':
- secrets.psk = key
+ elif (mgmt == 'wpa-psk') or (mgmt == 'wpa-eap'):
+ if mgmt == 'wpa-psk':
+ key = config.get(section, 'key')
+ secrets.psk = key
+ elif mgmt == 'wpa-eap':
+ if config.has_option(section,
+ 'wpa_eap_setting'):
+ value = eval(config.get(section,
+ 'wpa_eap_setting'))
+ settings.wpa_eap_setting = value
if config.has_option(section, 'proto'):
value = config.get(section, 'proto')
settings.wireless_security.proto = value
--
1.7.4.4
More information about the Dextrose
mailing list