Add support for ieee802.1x wireless networks.

Connman does only support two phase authentication via config files.
These config files reside in /var/lib/connman/ and are watched by
the connman daemon. Unfortunatelly, connman does not support per
session/user config files, so for simplicity's sake, we modify one in
/var/lib/connman. With these changes, econnman manages a single file
(/var/lib/connman/econnman.config), to which the user running it needs
write access. By default the (empty) config file shipped with this packages
has write permissions set for the group. Packagers might want to change the
owner/group to root:users after installation or come around with a more
sophisticated approach.
This commit is contained in:
Leif Middelschulte 2013-12-12 19:39:23 +01:00 committed by Kai Huuhko
parent 72838d004b
commit f797c7d2d8
6 changed files with 142 additions and 1 deletions

View File

@ -1 +1,3 @@
Gustavo Sverzut Barbieri <barbieri@profusion.mobi>
Matthias Wauer <matthiaswauer@gmail.com>
Leif Middelschulte <leif.middelschulte@gmail.com>

View File

@ -0,0 +1,4 @@
Since 1.1:
* Added basic support for ieee802.1x wireless networks configuration
The user running econnman needs to be able to write its own configfile at
/var/lib/connman/econnman.config

View File

@ -17,6 +17,12 @@ econnman-bin: $(top_srcdir)/econnman-bin.in $(top_builddir)/Makefile
$(top_srcdir)/econnman-bin.in > $(top_builddir)/econnman-bin
chmod +x $(top_builddir)/econnman-bin
configdir = $(localstatedir@)/lib/connman
dist_config_DATA = \
data/config/econnman.config
EXTRA_DIST += $(config_DATA)
desktopdir = $(datadir)/applications
desktop_DATA = \
data/desktop/econnman-agent.desktop \

1
README
View File

@ -36,6 +36,7 @@ Build::
Install::
make install
chown root:users /var/lib/connman/econnman.config
If you wish to install at alternative locations, then make sure to
configure your PYTHONPATH to be able to access this location!

View File

View File

@ -14,6 +14,12 @@ import logging
import argparse
import os.path
''' For python2 backwards compatibility '''
try:
import configparser
except ImportError:
import ConfigParser as configparser
try:
import efl.evas as evas
import efl.ecore as ecore
@ -58,6 +64,9 @@ log = logging.getLogger()
manager = None
CONF_FILE = "/var/lib/connman/econnman.config"
configs = None
EXPAND_BOTH = (evas.EVAS_HINT_EXPAND, evas.EVAS_HINT_EXPAND)
EXPAND_HORIZ = (evas.EVAS_HINT_EXPAND, 0.0)
@ -242,6 +251,52 @@ class ObjectView(object):
en.callback_activated_add(callback)
return lb, en
#######################################################################
# Config Files Helper:
def config_del(name):
secname = 'service_' + name
if configs == None:
log.error("Config file was not parsed!")
return
if not configs.has_section(secname):
configs.remove_section(secname)
config_write(name)
def config_set(name, key, value):
secname = 'service_' + name
if configs == None:
log.error("Config file was not parsed!")
return
if not configs.has_section(secname):
configs.add_section(secname)
configs.set(secname, 'Type', 'wifi')
configs.set(secname, 'Name', name)
if value != None:
configs.set(secname, key, value)
elif configs.has_option(secname, key):
configs.remove_option(sec, key)
config_write(name)
def config_get(name):
if configs == None:
log.error("Config file was not parsed!")
return None
for sec in configs.sections():
if configs.has_option(sec, 'Name') and configs.get(sec, 'Name') == name:
return sec
else:
return None
def config_exists(name):
if config_get(name):
return True
else:
return False
def config_write(name):
with open(CONF_FILE, 'w', encoding='utf8') as configfile:
configs.write(configfile)
########################################################################
# Views:
@ -803,13 +858,16 @@ class ServiceView(ObjectView):
"proxy_frame",
"ethernet_frame",
"vpn_frame",
"ieee8021x_frame",
)
def create_view(self, properties):
self.type = str(properties.get("Type"))
self.security_mode = properties.get("Security")
self.immutable = bool(properties.get("Immutable"))
self.readwrite_list_properties = {}
self.readwrite_list_widget = {}
self.name = str(properties.get("Name"))
self.connect = self.add_button(self.box, "Connect", self._connect)
self.disconnect = self.add_button(self.box, "Disconnect",
@ -890,6 +948,37 @@ class ServiceView(ObjectView):
fr, bx = self.add_readonly_section("VPN", self.vpn_fields)
self.vpn_frame = fr
# section 2 Phase Authentication
if (self.type == "wifi") and ("ieee8021x" in self.security_mode):
fr, bx = self.add_frame_and_box(self.box, "ieee8021x")
self.ieee8021x_frame = fr
cfg_sec = config_get(self.name)
lb = self.add_label(bx, "EAP:")
options = ("PEAP", "TLS", "TTLS", "None")
self.eap_method, self.eap_method_items = self.add_segment_control(
bx, options, self._on_eap_method)
if cfg_sec:
conf_val = configs.get(cfg_sec, 'EAP')
if conf_val == "peap":
self.eap_method_items["PEAP"].selected = True
elif conf_val == "tls":
self.eap_method_items["TLS"].selected = True
elif conf_val == "ttls":
self.eap_method_items["TTLS"].selected = True
options = ("TLS", "MSCHAPv2", "None")
lb = self.add_label(bx, "Phase2:")
self.phase2, self.phase2_items = self.add_segment_control(
bx, options, self._on_phase2)
if cfg_sec:
conf_val = configs.get(cfg_sec, 'Phase2')
if conf_val == "tls":
self.phase2_items["TLS"].selected = True
elif conf_val == "MSCHAPV2":
self.phase2_items["MSCHAPv2"].selected = True
def add_readonly_section(self, title, fields):
fr, bx = self.add_frame_and_box(self.box, title)
for name, attr in fields:
@ -1108,6 +1197,9 @@ class ServiceView(ObjectView):
log.error("Could not remove %s", exc)
self.forget.disabled = False
if self.security_mode == "ieee8021x":
config_del(self.name)
else:
self.bus_obj.Remove(reply_handler=on_reply, error_handler=on_error)
self.forget.disabled = True
@ -1232,6 +1324,31 @@ class ServiceView(ObjectView):
pass
#revert to configured values...
def _on_eap_method(self, obj, item):
eap_val = None
if item.text == "PEAP":
eap_val = "peap"
elif item.text == "TLS":
eap_val = "tls"
elif item.text == "TTLS":
eap_val = "ttls"
elif item.text == "None":
eap_val = None
config_set(self.name, "EAP", eap_val)
return
def _on_phase2(self, obj, item):
phase2_val = None
if item.text == "MSCHAPv2":
phase2_val = "MSCHAPV2"
elif item.text == "TLS":
phase2_val = "tls"
elif item.text == "None":
eap_val = None
config_set(self.name, 'Phase2', phase2_val)
return
########################################################################
# Main Actions:
@ -1254,6 +1371,7 @@ def connect_service(path, properties):
if type in ("system", "gps", "gadget"):
log.error("cannot connect to service with type: %s", type)
return
sec = properties.get("Security")
name = properties.get("Name")
if name:
@ -1261,6 +1379,12 @@ def connect_service(path, properties):
log.debug("connect to %s (%s): %s",
name, path, dbus_dict_to_str(properties))
''' Connman only supports 2 phase auth via config files '''
if ("ieee8021x" in sec) and not config_exists(name):
popup_error(win, "This Network needs Configuration", "This network uses 802.1x authentication. Please configure the options in the section at the bottom.")
show_service(path, properties)
return
def on_reply():
log.info("Connected to %s (%s)", name, path)
@ -1486,6 +1610,10 @@ if __name__ == "__main__":
level -= 10 * args.verbose
log.setLevel(level)
configs = configparser.RawConfigParser()
configs.optionxform = str
configs.read(CONF_FILE)
elm.init()
elm.policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED)