[Sugar-devel] [PATCH RFC sugar sucrose-0.94 v6] Add capability to connect to WPA/WPA2-Enterprise Networks.

Ajay Garg ajay at activitycentral.com
Fri Dec 23 09:14:37 EST 2011


This patch helps connects to wireless networks, protected via WPA/WPA2-security
protocols.
 
Currently, three out of the four WPA-WPA2-authentication types are supported:
a. TLS
b. Protected EAP
c. Tunnelled TLS

And, one is unsupported:
a. LEAP

Following links may be useful, for security-protocol-specifications:
a. http://en.wikipedia.org/wiki/Wi-Fi_Protected_Access
b. http://en.wikipedia.org/wiki/EAP-TLS#EAP-TLS
c. http://en.wikipedia.org/wiki/Protected_Extensible_Authentication_Protocol
d. http://en.wikipedia.org/wiki/EAP-TTLS#EAP-TTLS


The method used here is simply to pass on the additional settings required for 
connecting to WPA/WPA-2 authenticated networks. Following is the BIBLE link :)

********************************************************************************
http://projects.gnome.org/NetworkManager/developers/api/08/settings-spec-08.html
********************************************************************************



(Note that this is a consolidated patch, to be applied in full;
 and NOT OVER version-5, version-4, version-3, version-2, and 
 version-1 patches).

Enhancements/Fixes of current version (version-6), over version-5 ::
--------------------------------------------------------------------

Fixing of subtle issues (all courtesy Sascha).

a. Fixed internationalization errors.
b. Corrected indentations.
c. Added docstrings, links and comments for easy maintenance.
d. Used better OOP methodologies (hiding private members of class).



For the record.
----------------
Enhancements/Fixes of version-5, over version-4 ::
--------------------------------------------------

a. Fixed the regression - Unable to connect to Unprotected-Wireless-Networks.
   Catcher :: Anish.



For the record.
----------------
Enhancements/Fixes of version-4, over version-3 ::
--------------------------------------------------

a. Fixing logging statements, and some formatting-changes (Thanks Sascha).
b. Not passing parameters to NetworkManager, that are not entered (required),
   as in TTLS- and PEAP-configuration (Thanks Anish).



For the record.
----------------
Enhancements/Fixes of version-3, over version-2 ::
--------------------------------------------------------------------

a. Now, TLS-based-authentication is also supported.
   -----------------------------------------------

   Thus, now, the following three authentication types are supported :
   (i)   TTLS
   (ii)  PEAP
   (iii) TLS

   Following authentication types are still not supported :
   (i)   LEAP (actually this may work, but the set-up has not been
               able to be worked out, and hence, this has not been
	       verified, even with nm-applet).

b. Journal-Chooser integration.
   ----------------------------

   This is useful in picking up chooser-entries (especially in case
   of certificates requirements, like in TLS and TTLS).

For the record.
----------------
Enhancements/Fixes of version-2, over version-1 ::
--------------------------------------------------

a. Network-Autoconnect-Upon-Hibernate-Resume
   ------------------------------------------

   Fixing the case, when network wouldn't (auto-)come-up,
   when the XO resumed from hibernation. (Thanks Anish for
   catching that :-) ).
   However, there wasn't a problem with auto-connect-on-reboot;
   it's working fine.


 src/jarabe/desktop/keydialog.py     |  248 ++++++++++++++++++++++++++++++++++-
 src/jarabe/desktop/networkviews.py  |  218 ++++++++++++++++++++++++++++++-
 src/jarabe/journal/objectchooser.py |   19 +++
 src/jarabe/model/network.py         |   28 +++-
 4 files changed, 501 insertions(+), 12 deletions(-)

diff --git a/src/jarabe/desktop/keydialog.py b/src/jarabe/desktop/keydialog.py
index c72f498..6fb92d3 100644
--- a/src/jarabe/desktop/keydialog.py
+++ b/src/jarabe/desktop/keydialog.py
@@ -16,13 +16,17 @@
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 import hashlib
+import os
+import shutil
 from gettext import gettext as _
 
 import gtk
 import dbus
 
+from sugar import env
 from jarabe.model import network
 from jarabe.model.network import Secrets
+from jarabe.journal.objectchooser import ObjectChooser
 
 
 IW_AUTH_ALG_OPEN_SYSTEM = 'open'
@@ -32,6 +36,11 @@ WEP_PASSPHRASE = 1
 WEP_HEX = 2
 WEP_ASCII = 3
 
+SETTING_TYPE_STRING = 1
+SETTING_TYPE_LIST = 2
+SETTING_TYPE_CHOOSER = 3
+
+
 
 def string_is_hex(key):
     is_hex = True
@@ -120,6 +129,227 @@ class KeyDialog(gtk.Dialog):
         return self._response
 
 
+class WirelessNetworkConnectionSettingsUI(gtk.HBox):
+    def __init__(self, auth_param):
+        gtk.HBox.__init__(self, homogeneous=True)
+        self._key = auth_param._get_key_name()
+        self._label = gtk.Label(auth_param._get_key_label())
+        self._key_type = auth_param._get_key_type()
+        self._auth_param = auth_param
+
+        self.pack_start(self._label)
+        self._label.show()
+
+        if self._is_entry():
+            self._entry = gtk.Entry()
+            self.pack_start(self._entry)
+            self._entry.show()
+        elif self._is_liststore():
+            self._option_store = gtk.ListStore(str, str)
+            for option in auth_param._options:
+                self._option_store.append(option)
+
+            self._entry = auth_param._get_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()
+        elif self._is_chooser():
+            self._chooser_button = gtk.Button(_('Choose...'))
+            self._chooser_button.connect('clicked',
+                                          self._object_chooser_cb)
+            self.pack_start(self._chooser_button)
+            self._chooser_button.show()
+            self._entry = ''
+
+    def _is_entry(self):
+        return ((not self._is_chooser()) and
+                (len(self._auth_param._options) == 0))
+
+    def _is_liststore(self):
+        return ((not self._is_chooser()) and
+                (len(self._auth_param._options) > 0 ))
+
+    def _is_chooser(self):
+        return self._key_type == SETTING_TYPE_CHOOSER
+
+    def _object_chooser_cb(self, chooser_button):
+        self._want_document = True
+        self._show_picker_cb()
+
+    def _show_picker_cb(self):
+        if not self._want_document:
+            return
+        self._chooser = ObjectChooser()
+        self._chooser._set_callback(self.__process_selected_journal_object)
+
+        self._chooser.show()
+
+    def __process_selected_journal_object(self, object_id):
+        jobject = self._chooser.get_selected_object()
+        if jobject and jobject.file_path:
+            user_visible_file_name = jobject._metadata._properties['title']
+            file_basename = os.path.basename(user_visible_file_name)
+            self._chooser_button.set_label(file_basename)
+
+
+
+            # The chooser entries are chosen from the journal.
+            # Now, the journal entries misbehave, and the entries keep
+            # changing their names. Thus, in order to have the same
+            # entry available at later times, we need to store the
+            # selected entries at a 'fixed-name' place.
+            #
+            # REQUIREMENT:
+            # ------------
+            #   It is needed that networks auto-connect on reboot; and
+            #   the user need not ne re-prompted to enter the
+            #   network-parameters.
+
+            profile_path = env.get_profile_path()
+            self._entry = os.path.join(profile_path, 'nm',
+                                       file_basename)
+
+            # Remove (older) file, if it exists.
+            if os.path.exists(self._entry):
+                os.remove(self._entry)
+
+            # Copy the file.
+            shutil.copy2(jobject.file_path, self._entry)
+
+        self._chooser.destroy()
+
+    def _option_combo_changed_cb(self, widget):
+        it = self._option_combo.get_active_iter()
+        (value, ) = self._option_store.get(it, 1)
+        self._entry = value
+
+    def _get_key(self):
+        return self._key
+
+    def _get_value(self):
+        if self._is_entry():
+            return self._entry.get_text()
+        elif self._is_liststore():
+            return self._entry
+        elif self._is_chooser():
+            if len(self._entry) > 0:
+                return dbus.ByteArray('file://' + self._entry + '\0')
+            else:
+                return self._entry
+
+
+class KeyValuesDialog(gtk.Dialog):
+    def __init__(self, auth_lists, final_callback, uuid, settings):
+        # This must not be "modal", else the "chooser" widgets won't
+        # accept anything !!
+        gtk.Dialog.__init__(self)
+        self.set_title(_('Wireless Parameters required'))
+
+        self._spacing_between_children_widgets = 5
+        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.set_spacing(self._spacing_between_children_widgets)
+        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._get_params_list()[0]._get_options()[0][1] == auth_type:
+                return auth_list
+
+    def _populate_auth_params(self, auth_list):
+        params_list = auth_list._get_params_list()
+        for auth_param in params_list[1:]:
+            obj = WirelessNetworkConnectionSettingsUI(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(spacing=self._spacing_between_children_widgets)
+        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._get_params_list():
+            if auth_param._get_key_name() == key:
+                if ((auth_param._get_key_type() == SETTING_TYPE_STRING) or
+                    (auth_param._get_key_type() == SETTING_TYPE_CHOOSER)):
+                    auth_param._set_value(value)
+                elif auth_param._get_key_type() == SETTING_TYPE_LIST:
+                    values = []
+                    values.append(value)
+                    auth_param._set_value(values)
+
+
 class WEPKeyDialog(KeyDialog):
     def __init__(self, ssid, flags, wpa_flags, rsn_flags, dev_caps, settings,
                  response):
@@ -218,7 +448,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 +526,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.
+        return
 
     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..a1bfa7a 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,151 @@ _OLPC_MESH_ICON_NAME = 'network-mesh'
 
 _FILTERED_ALPHA = 0.33
 
+SETTING_TYPE_STRING = 1
+SETTING_TYPE_LIST = 2
+SETTING_TYPE_CHOOSER = 3
+
+
+class AuthenticationType:
+    """
+    An instance of this class holds ::
+        a. The user-visible string for the authentication-type.
+        b. The authentication-type (TLS, LEAP, TTLS, PEAP).
+        c. All setting-parameters, that need to be passed to the
+           Networkmanager, given a particular authentication type.
+           Each setting, is an object of class
+           "AuthenticationParameter" (see below).
+    """
+    def __init__(self, auth_label, auth_type, params_list):
+        self._auth_label = auth_label
+        self._auth_type = auth_type
+        self._params_list = params_list
+
+    def _get_auth_label(self):
+        return self._auth_label
+
+    def _get_auth_type(self):
+        return self._auth_type
+
+    def _get_params_list(self):
+        return self._params_list
+
+
+class AuthenticationParameter:
+    """
+    Each instance of this class, contains all the data that is required
+    to fulfill the backend and frontend requirements of a setting of a
+    particular WPA/WPA2-authentication type.
+    """
+    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
+
+    def _get_key_name(self):
+        return self._key_name
+
+    def _get_key_label(self):
+        return self._key_label
+
+    def _get_key_type(self):
+        return self._key_type
+
+    def _get_options(self):
+        return self._options
+
+    def _set_value(self, value):
+        self._value = value
+
+
+WPA_AUTHENTICATION_METHODS = [
+        AuthenticationType(_('TLS'), 'tls',
+            [AuthenticationParameter('eap', _('Authentication'),
+                 SETTING_TYPE_LIST,
+                 [[_('TLS'), 'tls']]),
+             AuthenticationParameter('identity', _('Identity'),
+                 SETTING_TYPE_STRING,
+                 []),
+             AuthenticationParameter('client-cert', _('User certificate'),
+                 SETTING_TYPE_CHOOSER,
+                 []),
+             AuthenticationParameter('ca-cert', _('CA certificate'),
+                 SETTING_TYPE_CHOOSER,
+                 []),
+             AuthenticationParameter('private-key', _('Private key'),
+                 SETTING_TYPE_CHOOSER,
+                 []),
+             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_CHOOSER,
+                 []),
+             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_CHOOSER,
+                 []),
+             AuthenticationParameter('phase1-peapver', _('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):
@@ -323,7 +469,7 @@ class WirelessNetworkView(CanvasPulsingIcon):
             group = self._add_ciphers_from_flags(self._rsn_flags, False)
             wireless_security = WirelessSecurity()
             wireless_security.key_mgmt = 'wpa-psk'
-            wireless_security.proto = 'rsn'
+            wireless_security.proto = ['rsn']
             wireless_security.pairwise = pairwise
             wireless_security.group = group
             return wireless_security
@@ -335,11 +481,71 @@ class WirelessNetworkView(CanvasPulsingIcon):
             group = self._add_ciphers_from_flags(self._wpa_flags, False)
             wireless_security = WirelessSecurity()
             wireless_security.key_mgmt = 'wpa-psk'
-            wireless_security.proto = 'wpa'
+            wireless_security.proto = ['wpa']
+            wireless_security.pairwise = pairwise
+            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 (provided the network has ANY security at all)
+        if (wireless_security is not None) and \
+                ( (wireless_security.key_mgmt == 'ieee8021x') or \
+                  (wireless_security.key_mgmt == 'wpa-eap') ):
+            keydialog.get_key_values(WPA_AUTHENTICATION_METHODS,
+                                     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
+                logging.debug('key == %s', key)
+                logging.debug('value == %s', value)
+                if len(value) > 0:
+                    key_value_dict[key] = value
+                else:
+                    logging.debug('Not setting empty value for key :'
+                    ' %s', key)
+
+            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 +556,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 +578,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/journal/objectchooser.py b/src/jarabe/journal/objectchooser.py
index ecb8ecf..59df14b 100644
--- a/src/jarabe/journal/objectchooser.py
+++ b/src/jarabe/journal/objectchooser.py
@@ -20,9 +20,12 @@ import logging
 import gobject
 import gtk
 import wnck
+import os
 
+from sugar import env
 from sugar.graphics import style
 from sugar.graphics.toolbutton import ToolButton
+from sugar.datastore import datastore
 
 from jarabe.journal.listview import BaseListView
 from jarabe.journal.listmodel import ListModel
@@ -46,6 +49,7 @@ class ObjectChooser(gtk.Window):
         self.set_border_width(style.LINE_WIDTH)
 
         self._selected_object_id = None
+        self._callback = None
 
         self.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK)
         self.connect('visibility-notify-event',
@@ -109,6 +113,15 @@ class ObjectChooser(gtk.Window):
         self._selected_object_id = uid
         self.emit('response', gtk.RESPONSE_ACCEPT)
 
+        if self._callback is not None:
+            self._callback(self._selected_object_id)
+
+    def get_selected_object(self):
+        if self._selected_object_id is None:
+            return None
+        else:
+            return datastore.get(self._selected_object_id)
+
     def __delete_event_cb(self, chooser, event):
         self.emit('response', gtk.RESPONSE_DELETE_EVENT)
 
@@ -120,6 +133,9 @@ class ObjectChooser(gtk.Window):
     def __close_button_clicked_cb(self, button):
         self.emit('response', gtk.RESPONSE_DELETE_EVENT)
 
+        if self._callback is not None:
+            self._callback(self._selected_object_id)
+
     def get_selected_object_id(self):
         return self._selected_object_id
 
@@ -135,6 +151,9 @@ class ObjectChooser(gtk.Window):
         visible = event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED
         self._list_view.set_is_visible(visible)
 
+    def _set_callback(self, callback):
+        self._callback = callback
+
 
 class TitleBox(VolumesToolbar):
     __gtype_name__ = 'TitleBox'
diff --git a/src/jarabe/model/network.py b/src/jarabe/model/network.py
index f265ae4..84e3666 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,21 +903,29 @@ 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')
+                        value = eval(config.get(section, 'proto'))
                         settings.wireless_security.proto = value
                     if config.has_option(section, 'group'):
-                        value = config.get(section, 'group')
+                        value = eval(config.get(section, 'group'))
                         settings.wireless_security.group = value
                     if config.has_option(section, 'pairwise'):
-                        value = config.get(section, 'pairwise')
+                        value = eval(config.get(section, 'pairwise'))
                         settings.wireless_security.pairwise = value
         except ConfigParser.Error:
             logging.exception('Error reading section')
-- 
1.7.4.4



More information about the Sugar-devel mailing list