Refactor pnac config into a class and separate module

This will make it easier to add proper authorization for it
in the future.
This commit is contained in:
Kai Huuhko 2014-07-16 11:46:47 +03:00
parent 1551b89b81
commit 80b83a2e28
3 changed files with 141 additions and 129 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
*.py[oc]
INSTALL
Makefile
Makefile.in

View File

@ -14,16 +14,10 @@ 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
import efl.edje
import efl.edje as edje # Class resolve hack for edje_get
from efl.dbus_mainloop import DBusEcoreMainLoop
import efl.elementary as elm
from efl.elementary import ELM_POLICY_QUIT, \
@ -51,7 +45,7 @@ except:
import elementary as elm
import evas
import ecore
import edje
import edje # Class resolve hack for edje_get
from e_dbus import DBusEcoreMainLoop
from elementary import Window, Background, Box, Label, Naviframe, Popup, \
Button, Scroller, Check, Progressbar, Genlist, GenlistItemClass, \
@ -59,6 +53,7 @@ except:
ELM_WIN_DIALOG_BASIC, ELM_POLICY_QUIT, ELM_SCROLLER_POLICY_OFF, \
ELM_SCROLLER_POLICY_AUTO, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED
from pnac import PNACConfig
dbus_ml = DBusEcoreMainLoop()
bus = dbus.SystemBus(mainloop=dbus_ml)
@ -72,9 +67,6 @@ log.addHandler(log_handler)
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)
@ -268,103 +260,6 @@ class ObjectView(object):
return lb, en
#######################################################################
# Config Files Helper:
def config_file_setup():
global configs
configs = configparser.RawConfigParser()
configs.optionxform = str
try:
fd = open(CONF_FILE, 'r', encoding='utf8')
configs.readfp(fd)
fd.close()
except IOError:
popup_error(
win,
"Cannot read configuration file",
"Econnman cannot read the coniguration file \"" + CONF_FILE +
"\", used by connman to configure your ieee802.1x networks. "
"Make sure the user running connman is able to read/write it."
)
configs = None
raise IOError
def config_del(name):
global configs
secname = 'service_' + name
if configs is None:
try:
config_file_setup()
except IOError:
return
if configs.has_section(secname):
configs.remove_section(secname)
config_write(name)
def config_set(name, key, value):
global configs
secname = 'service_' + name
if configs is None:
try:
config_file_setup()
except IOError:
return
if not configs.has_section(secname):
configs.add_section(secname)
configs.set(secname, 'Type', 'wifi')
configs.set(secname, 'Name', name)
if value is not None:
configs.set(secname, key, value)
elif configs.has_option(secname, key):
configs.remove_option(secname, key)
config_write(name)
def config_get(name):
global configs
if configs is None:
try:
config_file_setup()
except IOError:
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_option_get(secname, key):
if configs.has_option(secname, key):
return configs.get(secname, key)
return None
def config_exists(name):
if config_get(name):
return True
else:
return False
def config_write(name):
global configs
try:
with open(CONF_FILE, 'w', encoding='utf8') as configfile:
configs.write(configfile)
except IOError:
popup_error(
win,
"Cannot write configuration file",
"Econnman cannot write the coniguration file \"" + CONF_FILE +
"\", used by connman to configure your ieee802.1x networks. "
"Make sure the user running connman is able to read/write it."
)
########################################################################
# Views:
class OfflineModeMonitor(object):
@ -967,10 +862,10 @@ class ServiceView(ObjectView):
if not self.immutable and self.type != "ethernet":
self.forget = self.add_button(self.box, "Forget Network",
self._forget)
elif (self.type == "wifi") and ("ieee8021x" in self.security_mode):
elif self.type == "wifi" and "ieee8021x" in self.security_mode:
self.forget = self.add_button(self.box, "Forget Network",
self._forget)
if not config_exists(self.name):
if not pnac_conf.has_section(self.name):
self.forget.disabled = True
self.error = self.add_label(self.box, "error here")
@ -1005,6 +900,7 @@ class ServiceView(ObjectView):
self.domains_label = lb
self.domains_entry = en
# section: IPv4
self.ipv4_properties = {"IPv4": {}, "IPv4.Configuration": {}}
fr, bx = self.add_frame_and_box(self.box, "IPv4")
self.ipv4_frame = fr
@ -1018,10 +914,15 @@ class ServiceView(ObjectView):
en.callback_unfocused_add(self._on_ipv4_property_unfocused)
setattr(self, attr, en)
# section: IPv6: similar to ipv4? refactor ipv4?
if properties.get("IPv6"):
fr, bx = self.add_frame_and_box(self.box, "IPv6")
lb = self.add_label(bx, "TODO")
# section: Proxy: custom contents for direct, auto and manual
# - direct: nothing
# - auto: url
# - manual: servers, excludes
self.proxy_properties = {"Proxy": {}, "Proxy.Configuration": {}}
fr, bx = self.add_frame_and_box(self.box, "Proxy")
self.proxy_frame = fr
@ -1031,12 +932,7 @@ class ServiceView(ObjectView):
bx, options, self._on_proxy_method)
self.add_label(bx, "TODO")
# section IPv6: similar to ipv4? refactor ipv4?
# section Proxy: custom contents for direct, auto and manual
# - direct: nothing
# - auto: url
# - manual: servers, excludes
# section: Ethernet / VPN
if self.type in ("wifi", "ethernet", "wimax", "bluetooth", "cellular"):
fr, bx = self.add_readonly_section("Ethernet", self.eth_fields)
self.ethernet_frame = fr
@ -1044,20 +940,19 @@ class ServiceView(ObjectView):
fr, bx = self.add_readonly_section("VPN", self.vpn_fields)
self.vpn_frame = fr
# section 2 Phase Authentication
# section: Two 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)
#cfg_sec = pnac_conf.section_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 = config_option_get(cfg_sec, 'EAP')
if pnac_conf.has_section(self.name):
conf_val = pnac_conf.get(self.name, 'EAP')
if conf_val == "peap":
self.eap_method_items["PEAP"].selected = True
elif conf_val == "tls":
@ -1072,8 +967,8 @@ class ServiceView(ObjectView):
self.phase2, self.phase2_items = self.add_segment_control(
bx, options, self._on_phase2
)
if cfg_sec:
conf_val = config_option_get(cfg_sec, 'Phase2')
if pnac_conf.has_section(self.name):
conf_val = pnac_conf.get(self.name, 'Phase2')
if conf_val == "tls":
self.phase2_items["TLS"].selected = True
elif conf_val == "MSCHAPV2":
@ -1306,8 +1201,8 @@ class ServiceView(ObjectView):
self.forget.disabled = False
if self.type == "wifi" and "ieee8021x" in self.security_mode:
if config_exists(self.name):
config_del(self.name)
if pnac_conf.has_section(self.name):
pnac_conf.remove_section(self.name)
for it in self.phase2_items:
self.phase2_items[it].selected = False
for it in self.eap_method_items:
@ -1456,7 +1351,7 @@ class ServiceView(ObjectView):
elif item.text == "None":
eap_val = None
config_set(self.name, "EAP", eap_val)
pnac_conf.set(self.name, "EAP", eap_val)
return
def _on_phase2(self, obj, item):
@ -1468,7 +1363,7 @@ class ServiceView(ObjectView):
elif item.text == "None":
phase2_val = None
config_set(self.name, 'Phase2', phase2_val)
pnac_conf.set(self.name, 'Phase2', phase2_val)
return
@ -1501,8 +1396,8 @@ 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):
# Connman only supports two phase auth via config files
if ("ieee8021x" in sec) and not pnac_conf.has_section(name):
popup_error(
win,
"This Network needs Configuration",
@ -1738,6 +1633,8 @@ if __name__ == "__main__":
level -= 10 * args.verbose
log.setLevel(level)
pnac_conf = PNACConfig()
elm.init()
elm.policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED)

114
pnac.py Normal file
View File

@ -0,0 +1,114 @@
import sys
import logging
log = logging.getLogger("econnman.pnac")
CONF_FILE = "/var/lib/connman/econnman.config"
# python2 backwards compatibility
try:
from configparser import SafeConfigParser
except ImportError:
from ConfigParser import SafeConfigParser
class PNACConfig(SafeConfigParser):
"""A custom config parser for IEEE802.1x (PNAC)
Section names are prefixed with service_
"""
def __init__(self):
SafeConfigParser.__init__(self)
self.optionxform = str
def read(self):
args = CONF_FILE, 'r'
kwargs = {}
if sys.hexversion >= 0x03000000:
kwargs["encoding"] = 'utf8'
try:
with open(*args, **kwargs) as fd:
self.readfp(fd)
except IOError:
log.error(
"Econnman cannot read the configuration file \"%s\" used by "
"connman to configure your ieee802.1x networks. Make sure the "
"user running econnman is able to read/write it.",
CONF_FILE
)
#raise
# defaults()
# sections()
def add_section(self, service_name):
secname = 'service_' + service_name
SafeConfigParser.add_section(self, secname)
self.set(service_name, 'Type', 'wifi')
self.set(service_name, 'Name', service_name)
def has_section(self, service_name): # config_exists
return bool(self.section_get(service_name))
# options()
def has_option(self, service_name, key):
secname = self.section_get(service_name)
return SafeConfigParser.has_option(secname, key)
# read()
# readfp()
def get(self, service_name, key): # config_option_get
secname = self.section_get(service_name)
if self.has_option(service_name, key):
return SafeConfigParser.get(self, secname, key)
return None
# getint()
# getfloat()
# getboolean()
# items()
def set(self, service_name, key, value): # config_set
secname = self.section_get(service_name)
if not self.has_section(service_name):
self.add_section(service_name)
if value is not None:
SafeConfigParser.set(self, secname, key, value)
elif self.has_option(secname, key):
self.remove_option(secname, key)
#self.write()
def write(self):
try:
with open(CONF_FILE, 'w', encoding='utf8') as configfile:
SafeConfigParser.write(self, configfile)
except IOError:
log.error(
"Econnman cannot write to the configuration file \"%s\" used "
"by connman to configure your ieee802.1x networks. Make sure "
"the user running econnman is able to read/write it.",
CONF_FILE
)
def remove_option(self, service_name, key):
secname = self.section_get(service_name)
SafeConfigParser.remove_option(self, secname, key)
def remove_section(self, service_name): # config_del
secname = self.section_get(service_name)
ret = SafeConfigParser.remove_section(self, secname)
#self.write()
return ret
def section_get(self, service_name): # config_get
#secname = 'service_' + service_name
for sec in self.sections():
if self.has_option(sec, 'Name') and \
self.get(sec, 'Name') == service_name:
return sec
else:
return None