diff --git a/src/opnsense/scripts/OPNsense/CaptivePortal/cp-background-process.py b/src/opnsense/scripts/OPNsense/CaptivePortal/cp-background-process.py index 1ae97fee4..2c2d42f58 100755 --- a/src/opnsense/scripts/OPNsense/CaptivePortal/cp-background-process.py +++ b/src/opnsense/scripts/OPNsense/CaptivePortal/cp-background-process.py @@ -29,7 +29,6 @@ update captive portal statistics """ import sys -import ujson import time import syslog import traceback @@ -40,6 +39,7 @@ from lib.arp import ARP from lib.ipfw import IPFW from lib.daemonize import Daemonize + class CPBackgroundProcess(object): """ background process helper class """ @@ -90,12 +90,12 @@ class CPBackgroundProcess(object): # cleanup removed static sessions for dbclient in self.db.list_clients(zoneid): if dbclient['authenticated_via'] == '---ip---' \ - and dbclient['ipAddress'] not in cpzones[zoneid]['allowedaddresses']: + and dbclient['ipAddress'] not in cpzones[zoneid]['allowedaddresses']: self.ipfw.delete(zoneid, dbclient['ipAddress']) self.db.del_client(zoneid, dbclient['sessionId']) elif dbclient['authenticated_via'] == '---mac---' \ - and dbclient['macAddress'] not in cpzones[zoneid]['allowedmacaddresses']: - if dbclient['ipAddress'] != '': + and dbclient['macAddress'] not in cpzones[zoneid]['allowedmacaddresses']: + if dbclient['ipAddress'] != '': self.ipfw.delete(zoneid, dbclient['ipAddress']) self.db.del_client(zoneid, dbclient['sessionId']) @@ -125,7 +125,7 @@ class CPBackgroundProcess(object): # check if hardtimeout is set and overrun for this session if 'hardtimeout' in cpzone_info and str(cpzone_info['hardtimeout']).isdigit(): # hardtimeout should be set and we should have collected some session data from the client - if int(cpzone_info['hardtimeout']) > 0 and float(db_client['startTime']) > 0: + if int(cpzone_info['hardtimeout']) > 0 and float(db_client['startTime']) > 0: if (time.time() - float(db_client['startTime'])) / 60 > int(cpzone_info['hardtimeout']): drop_session_reason = "session %s hit hardtimeout" % db_client['sessionId'] @@ -148,12 +148,12 @@ class CPBackgroundProcess(object): # session accounting if db_client['acc_session_timeout'] is not None \ - and time.time() - float(db_client['startTime']) > db_client['acc_session_timeout'] : + and time.time() - float(db_client['startTime']) > db_client['acc_session_timeout']: drop_session_reason = "accounting limit reached for session %s" % db_client['sessionId'] elif db_client['authenticated_via'] == '---mac---': # detect mac changes current_ip = self.arp.get_address_by_mac(db_client['macAddress']) - if current_ip != None: + if current_ip is not None: if db_client['ipAddress'] != '': # remove old ip self.ipfw.delete(zoneid, db_client['ipAddress']) @@ -187,6 +187,7 @@ class CPBackgroundProcess(object): if not address_active: self.ipfw.delete(zoneid, registered_address) + def main(): """ Background process loop, runs as backend daemon for all zones. only one should be active at all times. The main job of this procedure is to sync the administration with the actual situation in the ipfw firewall. diff --git a/src/opnsense/scripts/OPNsense/CaptivePortal/fetch_template.py b/src/opnsense/scripts/OPNsense/CaptivePortal/fetch_template.py index f8141ff47..d4352bbcb 100755 --- a/src/opnsense/scripts/OPNsense/CaptivePortal/fetch_template.py +++ b/src/opnsense/scripts/OPNsense/CaptivePortal/fetch_template.py @@ -37,7 +37,7 @@ import StringIO from lib import OPNSenseConfig response = dict() -source_directory = '/usr/local/opnsense/scripts/OPNsense/CaptivePortal/htdocs_default' +source_directory = '/usr/local/opnsense/scripts/OPNsense/CaptivePortal/htdocs_default' output_data = StringIO.StringIO() @@ -67,10 +67,10 @@ with zipfile.ZipFile(output_data, mode='w', compression=zipfile.ZIP_DEFLATED) as # read standard template from disk for root, dirs, files in os.walk(source_directory): for filename in files: - filename = '%s/%s' % (root,filename) + filename = '%s/%s' % (root, filename) output_filename = filename[len(source_directory)+1:] if output_filename not in user_filenames: - zf.writestr(output_filename, open(filename,'rb').read()) + zf.writestr(output_filename, open(filename, 'rb').read()) response['payload'] = output_data.getvalue().encode('base64') response['size'] = len(response['payload']) diff --git a/src/opnsense/scripts/OPNsense/CaptivePortal/lib/__init__.py b/src/opnsense/scripts/OPNsense/CaptivePortal/lib/__init__.py index a4afc682c..e2838cf50 100644 --- a/src/opnsense/scripts/OPNsense/CaptivePortal/lib/__init__.py +++ b/src/opnsense/scripts/OPNsense/CaptivePortal/lib/__init__.py @@ -29,6 +29,7 @@ import stat import xml.etree.ElementTree from ConfigParser import ConfigParser + class Config(object): """ handle to captive portal config (/usr/local/etc/captiveportal.conf) """ @@ -50,17 +51,16 @@ class Config(object): self._conf_handle.read(self._cnf_filename) self.last_updated = mod_time - def get_zones(self): """ return list of configured zones :return: dictionary index by zoneid, containing dictionaries with zone properties """ result = dict() self._update() - if self._conf_handle != None: + if self._conf_handle is not None: for section in self._conf_handle.sections(): if section.find('zone_') == 0: - zoneid=section.split('_')[1] + zoneid = section.split('_')[1] result[zoneid] = dict() for item in self._conf_handle.items(section): result[zoneid][item[0]] = item[1] @@ -86,10 +86,12 @@ class Config(object): return self._conf_handle.get(section, 'content') return None + class OPNSenseConfig(object): """ Read configuration data from config.xml """ def __init__(self): + self.rootNode = None self.load_config() def load_config(self): @@ -106,7 +108,7 @@ class OPNSenseConfig(object): templates = self.rootNode.findall("./OPNsense/captiveportal/templates/template") if templates is not None: for template in templates: - if template.find('fileid') is not None and template.find('content') is not None : + if template.find('fileid') is not None and template.find('content') is not None: if template.find('fileid').text == fileid: return template.find('content').text diff --git a/src/opnsense/scripts/OPNsense/CaptivePortal/lib/arp.py b/src/opnsense/scripts/OPNsense/CaptivePortal/lib/arp.py index d13234498..4360d7af0 100644 --- a/src/opnsense/scripts/OPNsense/CaptivePortal/lib/arp.py +++ b/src/opnsense/scripts/OPNsense/CaptivePortal/lib/arp.py @@ -66,7 +66,7 @@ class ARP(object): if address in self._arp_table: self._arp_table[address]['intf'].append(physical_intf) else: - self._arp_table[address] = {'mac': mac, 'intf': [physical_intf],'expires' : expires} + self._arp_table[address] = {'mac': mac, 'intf': [physical_intf], 'expires': expires} def list_items(self): """ return parsed arp list diff --git a/src/opnsense/scripts/OPNsense/CaptivePortal/lib/db.py b/src/opnsense/scripts/OPNsense/CaptivePortal/lib/db.py index 452cbf8f3..d673ea151 100644 --- a/src/opnsense/scripts/OPNsense/CaptivePortal/lib/db.py +++ b/src/opnsense/scripts/OPNsense/CaptivePortal/lib/db.py @@ -37,6 +37,7 @@ class DB(object): """ construct new database connection, open and make sure the sqlite file exists :return: """ + self._connection = None self.open() self.create() @@ -73,14 +74,14 @@ class DB(object): cur.executescript(open(init_script_filename, 'rb').read()) cur.close() - def sessions_per_address(self, zoneid, ip_address = None, mac_address = None): + def sessions_per_address(self, zoneid, ip_address=None, mac_address=None): """ fetch session(s) per (mac) address :param zoneid: cp zone number :param ip_address: ip address :return: active status (boolean) """ cur = self._connection.cursor() - request = {'zoneid':zoneid, 'ip_address': ip_address, 'mac_address': mac_address} + request = {'zoneid': zoneid, 'ip_address': ip_address, 'mac_address': mac_address} cur.execute("""select cc.sessionid sessionId , cc.authenticated_via authenticated_via from cp_clients cc @@ -94,7 +95,7 @@ class DB(object): result = [] for row in cur.fetchall(): - result.append({'sessionId':row[0], 'authenticated_via': row[1]}) + result.append({'sessionId': row[0], 'authenticated_via': row[1]}) return result def add_client(self, zoneid, authenticated_via, username, ip_address, mac_address): @@ -144,7 +145,6 @@ class DB(object): """, {'zoneid': zoneid, 'sessionid': sessionid, 'ip_address': ip_address}) self._connection.commit() - def del_client(self, zoneid, sessionid): """ mark (administrative) client for removal :param zoneid: zone id @@ -340,7 +340,7 @@ class DB(object): :return: string "add"/"update" to signal the performed action to the client """ cur = self._connection.cursor() - qry_params = {'zoneid': zoneid, 'sessionid' : sessionid, 'session_timeout': session_timeout} + qry_params = {'zoneid': zoneid, 'sessionid': sessionid, 'session_timeout': session_timeout} sql_update = """update session_restrictions set session_timeout = :session_timeout where zoneid = :zoneid and sessionid = :sessionid""" diff --git a/src/opnsense/scripts/OPNsense/CaptivePortal/listClients.py b/src/opnsense/scripts/OPNsense/CaptivePortal/listClients.py index 682b54997..597f536e1 100755 --- a/src/opnsense/scripts/OPNsense/CaptivePortal/listClients.py +++ b/src/opnsense/scripts/OPNsense/CaptivePortal/listClients.py @@ -57,14 +57,16 @@ if parameters['output_type'] != 'json': 'ipAddress': 'ip_address', 'macAddress': 'mac_address', 'total_bytes': 'total_bytes', - 'idletime' : 'idletime', + 'idletime': 'idletime', 'totaltime': 'totaltime' } - print '%(sessionId)-30s %(userName)-20s %(ipAddress)-20s %(macAddress)-20s %(total_bytes)-15s %(idletime)-10s %(totaltime)-10s' % heading + print '%(sessionId)-30s %(userName)-20s %(ipAddress)-20s %(macAddress)-20s '\ + + '%(total_bytes)-15s %(idletime)-10s %(totaltime)-10s' % heading for item in response: item['total_bytes'] = (item['bytes_out'] + item['bytes_in']) item['idletime'] = time.time() - item['last_accessed'] item['totaltime'] = time.time() - item['startTime'] - print '%(sessionId)-30s %(userName)-20s %(ipAddress)-20s %(macAddress)-20s %(total_bytes)-15s %(idletime)-10d %(totaltime)-10d' % item + print '%(sessionId)-30s %(userName)-20s %(ipAddress)-20s %(macAddress)-20s '\ + + '%(total_bytes)-15s %(idletime)-10d %(totaltime)-10d' % item else: print(ujson.dumps(response)) diff --git a/src/opnsense/scripts/OPNsense/CaptivePortal/overlay_template.py b/src/opnsense/scripts/OPNsense/CaptivePortal/overlay_template.py index c9184636d..824fb0134 100755 --- a/src/opnsense/scripts/OPNsense/CaptivePortal/overlay_template.py +++ b/src/opnsense/scripts/OPNsense/CaptivePortal/overlay_template.py @@ -31,8 +31,6 @@ """ import os import sys -import ujson -import binascii import zipfile import StringIO from lib import Config @@ -43,7 +41,7 @@ if len(sys.argv) > 1: target_directory = '/var/captiveportal/zone%s/htdocs/' % zoneid template_data = cnf.fetch_template_data(sys.argv[1]) if template_data is not None and len(template_data) > 20: - print ('overlay user template package for zone %s' % zoneid ) + print ('overlay user template package for zone %s' % zoneid) zip_content = template_data.decode('base64') input_data = StringIO.StringIO(zip_content) with zipfile.ZipFile(input_data, mode='r', compression=zipfile.ZIP_DEFLATED) as zf_in: @@ -57,7 +55,7 @@ if len(sys.argv) > 1: f_out.write(zf_in.read(zf_info.filename)) os.chmod(target_filename, 0444) # write zone settings - filename ='%sjs/zone.js' % target_directory + filename = '%sjs/zone.js' % target_directory with open(filename, 'wb') as f_out: f_out.write('var zoneid = %s' % zoneid) os.chmod(filename, 0444) diff --git a/src/opnsense/scripts/OPNsense/CaptivePortal/strip_template.py b/src/opnsense/scripts/OPNsense/CaptivePortal/strip_template.py index 0a1743c79..30f33e75c 100755 --- a/src/opnsense/scripts/OPNsense/CaptivePortal/strip_template.py +++ b/src/opnsense/scripts/OPNsense/CaptivePortal/strip_template.py @@ -36,16 +36,17 @@ import binascii import StringIO import zipfile import ujson -import md5 +from hashlib import md5 htdocs_default_root = '/usr/local/opnsense/scripts/OPNsense/CaptivePortal/htdocs_default' + def load_exclude_list(): """ load exclude list, files that should be removed from the input stream """ result = [] - filename = '%s/exclude.list' % htdocs_default_root - for line in open(filename, 'r').read().split('\n'): + excl_filename = '%s/exclude.list' % htdocs_default_root + for line in open(excl_filename, 'r').read().split('\n'): line = line.strip() if len(line) > 1 and line[0] != '#': result.append(line) @@ -53,12 +54,13 @@ def load_exclude_list(): response = dict() +zip_content = None if len(sys.argv) < 2: response['error'] = 'Filename parameter missing' else: input_filename = '/tmp/%s' % os.path.basename(sys.argv[1]) try: - zip_content = open(input_filename,'r').read().decode('base64') + zip_content = open(input_filename, 'r').read().decode('base64') except binascii.Error: # not in base64 response['error'] = 'Not a base64 encoded file' @@ -81,17 +83,17 @@ if 'error' not in response: if index_location is not None: for zf_info in zf_in.infolist(): if zf_info.filename[-1] != '/': - filename = zf_info.filename.replace(index_location.replace('index.html',''),'') + filename = zf_info.filename.replace(index_location.replace('index.html', ''), '') # ignore internal osx metadata files, maybe we need to ignore some others (windows?) as well # here. - if filename.split('/')[0] in ('__MACOSX') or filename.split('/')[-1] == '.DS_Store': + if filename.split('/')[0] == '__MACOSX' or filename.split('/')[-1] == '.DS_Store': continue if filename not in exclude_list: file_data = zf_in.read(zf_info.filename) src_filename = '%s/%s' % (htdocs_default_root, filename) if os.path.isfile(src_filename): - md5_src = md5.new(open(src_filename, 'rb').read()).hexdigest() - md5_new = md5.new(file_data).hexdigest() + md5_src = md5(open(src_filename, 'rb').read()).hexdigest() + md5_new = md5(file_data).hexdigest() if md5_src != md5_new: # changed file zf_out.writestr(filename, file_data) @@ -99,7 +101,7 @@ if 'error' not in response: # new file, always write zf_out.writestr(filename, file_data) if 'error' not in response: - response['payload'] = output_data.getvalue().encode('base64').strip().replace('\n' ,'') + response['payload'] = output_data.getvalue().encode('base64').strip().replace('\n', '') response['size'] = len(response['payload']) print(ujson.dumps(response))