[Dextrose] [PATCH] Porting to 0.97.6; Patch Numbers 69; (WPA-Enterprise)

Ajay Garg ajay at activitycentral.com
Wed Oct 10 01:38:45 EDT 2012


*
Feature Page ::
http://wiki.sugarlabs.org/go/Features/WPA-WPA2-Enterprise-Network-Connections


*
The patch has been tested to work on http://build.laptop.org/13.1.0/os4/xo-1.75/31004o2.zd
(after copying the 4 patched source-code files to the XO-1.75).


 src/jarabe/desktop/keydialog.py     |  236 +++++++++++++++++++++++++++++++++-
 src/jarabe/desktop/networkviews.py  |  243 ++++++++++++++++++++++++++++++++++-
 src/jarabe/journal/objectchooser.py |   20 +++
 src/jarabe/model/network.py         |    3 +
 4 files changed, 494 insertions(+), 8 deletions(-)

diff --git a/src/jarabe/desktop/keydialog.py b/src/jarabe/desktop/keydialog.py
index 5215d05..8a57feb 100644
--- a/src/jarabe/desktop/keydialog.py
+++ b/src/jarabe/desktop/keydialog.py
@@ -20,8 +20,12 @@ from gettext import gettext as _
 
 from gi.repository import Gtk
 import dbus
+import os
+import shutil
 
+from sugar import env
 from jarabe.model import network
+from jarabe.journal.objectchooser import ObjectChooser
 
 
 IW_AUTH_ALG_OPEN_SYSTEM = 'open'
@@ -31,6 +35,10 @@ 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
@@ -72,6 +80,210 @@ class CanceledKeyRequestError(dbus.DBusException):
         self._dbus_error_name = network.NM_SETTINGS_IFACE + '.CanceledError'
 
 
+class NetworkParameters(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
+        self._auth_param = auth_param
+
+        self.pack_start(self._label, True, True, 0)
+        self._label.show()
+
+        if self._is_entry():
+            self._entry = Gtk.Entry()
+            self.pack_start(self._entry, True, True, 0)
+            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._options[0][1]
+            self._option_combo = Gtk.ComboBox(model=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, True, True, 0)
+            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, True, True, 0)
+            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:
+            file_basename = \
+                    os.path.basename(jobject._metadata._properties['title'])
+            self._chooser_button.set_label(file_basename)
+
+            profile_path = env.get_profile_path()
+            self._entry = os.path.join(profile_path, 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, 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._settings = settings
+
+        label = Gtk.Label(_("Please enter parameters\n"))
+        self.vbox.set_spacing(self._spacing_between_children_widgets)
+        self.vbox.pack_start(label, True, True, 0)
+
+        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(model=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, True, True, 0)
+        self._auth_type_box.pack_start(self._auth_type_combo,
+                                       True, True, 0)
+        self.vbox.pack_start(self._auth_type_box, True, True, 0)
+        self._auth_label.show()
+        self._auth_type_combo.show()
+
+        self.add_buttons(Gtk.STOCK_OK, Gtk.ResponseType.OK)
+        self.set_default_response(Gtk.ResponseType.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 = NetworkParameters(auth_param)
+            self._key_values_box.pack_start(obj, True, True, 0)
+            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, True, True, 0)
+        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.ResponseType.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._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) or \
+                   (auth_param._key_type == SETTING_TYPE_CHOOSER):
+                    auth_param._value = value
+                elif auth_param._key_type == SETTING_TYPE_LIST:
+                    values = []
+                    values.append(value)
+                    auth_param._value = values
+
+
 class KeyDialog(Gtk.Dialog):
     def __init__(self, ssid, flags, wpa_flags, rsn_flags, dev_caps, response):
         Gtk.Dialog.__init__(self, flags=Gtk.DialogFlags.MODAL)
@@ -134,7 +346,7 @@ class WEPKeyDialog(KeyDialog):
         self.key_combo.connect('changed', self._key_combo_changed_cb)
 
         hbox = Gtk.HBox()
-        hbox.pack_start(Gtk.Label(_('Key Type:', True, True, 0)))
+        hbox.pack_start(Gtk.Label(_('Key Type:')), True, True, 0)
         hbox.pack_start(self.key_combo, True, True, 0)
         hbox.show_all()
         self.vbox.pack_start(hbox, True, True, 0)
@@ -154,7 +366,7 @@ class WEPKeyDialog(KeyDialog):
         self.auth_combo.set_active(0)
 
         hbox = Gtk.HBox()
-        hbox.pack_start(Gtk.Label(_('Authentication Type:', True, True, 0)))
+        hbox.pack_start(Gtk.Label(_('Authentication Type:')), True, True, 0)
         hbox.pack_start(self.auth_combo, True, True, 0)
         hbox.show_all()
 
@@ -210,7 +422,7 @@ class WEPKeyDialog(KeyDialog):
         self.set_response_sensitive(Gtk.ResponseType.OK, valid)
 
 
-class WPAKeyDialog(KeyDialog):
+class WPAPersonalKeyDialog(KeyDialog):
     def __init__(self, ssid, flags, wpa_flags, rsn_flags, dev_caps, response):
         KeyDialog.__init__(self, ssid, flags, wpa_flags, rsn_flags,
                            dev_caps, response)
@@ -286,14 +498,26 @@ def create(ssid, flags, wpa_flags, rsn_flags, dev_caps, response):
             rsn_flags == network.NM_802_11_AP_SEC_NONE:
         key_dialog = WEPKeyDialog(ssid, flags, wpa_flags, rsn_flags,
                                   dev_caps, response)
-    else:
-        key_dialog = WPAKeyDialog(ssid, flags, wpa_flags, rsn_flags,
-                                  dev_caps, response)
+    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, settings):
+    key_dialog = KeyValuesDialog(key_list, final_callback,
+                                 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 c949b7e..e9c138f 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 sugar3.graphics.icon import Icon
 from sugar3.graphics.xocolor import XoColor
@@ -47,6 +48,192 @@ _OLPC_MESH_ICON_NAME = 'network-mesh'
 
 _FILTERED_ALPHA = 0.33
 
+SETTING_TYPE_STRING = 1
+SETTING_TYPE_LIST = 2
+SETTING_TYPE_CHOOSER = 3
+
+
+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_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(EventPulsingIcon):
     def __init__(self, initial_ap):
@@ -309,7 +496,7 @@ class WirelessNetworkView(EventPulsingIcon):
             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
@@ -321,7 +508,31 @@ class WirelessNetworkView(EventPulsingIcon):
             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_WIFI_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_WIFI_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
@@ -365,6 +576,34 @@ class WirelessNetworkView(EventPulsingIcon):
         if wireless_security is not None:
             settings.wireless.security = '802-11-wireless-security'
 
+        # Take in the settings, if applicable.
+        if (wireless_security is not None) and \
+                ( (wireless_security.key_mgmt == 'ieee8021x') or \
+                  (wireless_security.key_mgmt == 'wpa-eap') ):
+            keydialog.get_key_values(AUTHENTICATION_LIST,
+                                     self.__add_and_activate_connection,
+                                     settings)
+        else:
+            self.__add_and_activate_connection(settings)
+
+    def __add_and_activate_connection(self, 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
+
         network.add_and_activate_connection(self._device, settings,
                                             self.get_first_ap().model)
 
diff --git a/src/jarabe/journal/objectchooser.py b/src/jarabe/journal/objectchooser.py
index d860b0d..45e72af 100644
--- a/src/jarabe/journal/objectchooser.py
+++ b/src/jarabe/journal/objectchooser.py
@@ -16,15 +16,20 @@
 
 from gettext import gettext as _
 import logging
+import os
 
 from gi.repository import GObject
 from gi.repository import Gtk
 from gi.repository import Gdk
 from gi.repository import Wnck
 
+from sugar3 import env
+
 from sugar3.graphics import style
 from sugar3.graphics.toolbutton import ToolButton
 
+from sugar3.datastore import datastore
+
 from jarabe.journal.listview import BaseListView
 from jarabe.journal.listmodel import ListModel
 from jarabe.journal.journaltoolbox import MainToolbox
@@ -47,6 +52,7 @@ class ObjectChooser(Gtk.Window):
         self.set_border_width(style.LINE_WIDTH)
 
         self._selected_object_id = None
+        self._callback = None
 
         self.add_events(Gdk.EventMask.VISIBILITY_NOTIFY_MASK)
         self.connect('visibility-notify-event',
@@ -111,6 +117,15 @@ class ObjectChooser(Gtk.Window):
         self._selected_object_id = uid
         self.emit('response', Gtk.ResponseType.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.ResponseType.DELETE_EVENT)
 
@@ -121,6 +136,8 @@ class ObjectChooser(Gtk.Window):
 
     def __close_button_clicked_cb(self, button):
         self.emit('response', Gtk.ResponseType.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
@@ -140,6 +157,9 @@ class ObjectChooser(Gtk.Window):
     def __clear_clicked_cb(self, list_view):
         self._toolbar.clear_query()
 
+    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 930ba13..95b294b 100644
--- a/src/jarabe/model/network.py
+++ b/src/jarabe/model/network.py
@@ -492,6 +492,7 @@ class Settings(object):
         self.connection = ConnectionSettings()
         self.ip4_config = None
         self.wireless_security = None
+        self.wpa_eap_setting = None
 
         if wireless_cfg is not None:
             self.wireless = wireless_cfg
@@ -507,6 +508,8 @@ 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
 
 
-- 
1.7.10.2



More information about the Dextrose mailing list