diff --git a/src/opnsense/scripts/OPNsense/CaptivePortal/allow.py b/src/opnsense/scripts/OPNsense/CaptivePortal/allow.py index 3cf48394f..4a9a6550d 100755 --- a/src/opnsense/scripts/OPNsense/CaptivePortal/allow.py +++ b/src/opnsense/scripts/OPNsense/CaptivePortal/allow.py @@ -1,7 +1,7 @@ -#!/usr/local/bin/python2.7 +#!/usr/local/bin/python3 """ - Copyright (c) 2015 Ad Schellevis + Copyright (c) 2015-2019 Ad Schellevis All rights reserved. Redistribution and use in source and binary forms, with or without @@ -75,6 +75,6 @@ else: # output result as plain text or json if parameters['output_type'] != 'json': for item in response: - print '%20s %s' % (item, response[item]) + print ('%20s %s' % (item, response[item])) else: print(ujson.dumps(response)) diff --git a/src/opnsense/scripts/OPNsense/CaptivePortal/cp-background-process.py b/src/opnsense/scripts/OPNsense/CaptivePortal/cp-background-process.py index d038f419d..040f8d097 100755 --- a/src/opnsense/scripts/OPNsense/CaptivePortal/cp-background-process.py +++ b/src/opnsense/scripts/OPNsense/CaptivePortal/cp-background-process.py @@ -1,7 +1,7 @@ -#!/usr/local/bin/python2.7 +#!/usr/local/bin/python3 """ - Copyright (c) 2015 Ad Schellevis + Copyright (c) 2015-2019 Ad Schellevis All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/src/opnsense/scripts/OPNsense/CaptivePortal/disconnect.py b/src/opnsense/scripts/OPNsense/CaptivePortal/disconnect.py index 5a3dcb333..4af0ec628 100755 --- a/src/opnsense/scripts/OPNsense/CaptivePortal/disconnect.py +++ b/src/opnsense/scripts/OPNsense/CaptivePortal/disconnect.py @@ -1,7 +1,7 @@ -#!/usr/local/bin/python2.7 +#!/usr/local/bin/python3 """ - Copyright (c) 2015 Ad Schellevis + Copyright (c) 2015-2019 Ad Schellevis All rights reserved. Redistribution and use in source and binary forms, with or without @@ -46,18 +46,16 @@ for param in sys.argv[1:]: # disconnect client response = {'terminateCause': 'UNKNOWN'} if parameters['sessionid'] is not None and parameters['zoneid'] is not None: - cp_db = DB() # remove client - client_session_info = cp_db.del_client(parameters['zoneid'], parameters['sessionid']) + client_session_info = DB().del_client(parameters['zoneid'], parameters['sessionid']) if client_session_info is not None: - cpIPFW = IPFW() - cpIPFW.delete(parameters['zoneid'], client_session_info['ip_address']) + IPFW().delete(parameters['zoneid'], client_session_info['ip_address']) client_session_info['terminateCause'] = 'User-Request' response = client_session_info # output result as plain text or json if parameters['output_type'] != 'json': for item in response: - print '%20s %s' % (item, response[item]) + print ('%20s %s' % (item, response[item])) else: print(ujson.dumps(response)) diff --git a/src/opnsense/scripts/OPNsense/CaptivePortal/fetch_template.py b/src/opnsense/scripts/OPNsense/CaptivePortal/fetch_template.py index d969e2823..09f5acb1d 100755 --- a/src/opnsense/scripts/OPNsense/CaptivePortal/fetch_template.py +++ b/src/opnsense/scripts/OPNsense/CaptivePortal/fetch_template.py @@ -1,7 +1,7 @@ -#!/usr/local/bin/python2.7 +#!/usr/local/bin/python3 """ - Copyright (c) 2015 Ad Schellevis + Copyright (c) 2015-2019 Ad Schellevis All rights reserved. Redistribution and use in source and binary forms, with or without @@ -33,13 +33,14 @@ import sys import ujson import binascii import zipfile -import StringIO +import base64 +from io import BytesIO from lib import OPNsenseConfig response = dict() source_directory = '/usr/local/opnsense/scripts/OPNsense/CaptivePortal/htdocs_default' -output_data = StringIO.StringIO() +output_data = BytesIO() with zipfile.ZipFile(output_data, mode='w', compression=zipfile.ZIP_DEFLATED) as zf: # overlay user template data @@ -52,7 +53,7 @@ with zipfile.ZipFile(output_data, mode='w', compression=zipfile.ZIP_DEFLATED) as template_content = cnf.get_template(sys.argv[1]) if template_content is not None: try: - input_data = StringIO.StringIO(template_content.decode('base64')) + input_data = BytesIO(base64.b64decode(template_content)) with zipfile.ZipFile(input_data, mode='r', compression=zipfile.ZIP_DEFLATED) as zf_in: for zf_info in zf_in.infolist(): user_filenames.append(zf_info.filename) @@ -70,8 +71,9 @@ with zipfile.ZipFile(output_data, mode='w', compression=zipfile.ZIP_DEFLATED) as 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()) + tmp = open(filename, 'rb').read() + zf.writestr(output_filename, tmp) -response['payload'] = output_data.getvalue().encode('base64') +response['payload'] = base64.b64encode(output_data.getvalue()).decode() response['size'] = len(response['payload']) print(ujson.dumps(response)) diff --git a/src/opnsense/scripts/OPNsense/CaptivePortal/lib/__init__.py b/src/opnsense/scripts/OPNsense/CaptivePortal/lib/__init__.py index 0c8901c19..3eda8827e 100755 --- a/src/opnsense/scripts/OPNsense/CaptivePortal/lib/__init__.py +++ b/src/opnsense/scripts/OPNsense/CaptivePortal/lib/__init__.py @@ -1,5 +1,5 @@ """ - Copyright (c) 2015 Ad Schellevis + Copyright (c) 2015-2019 Ad Schellevis All rights reserved. Redistribution and use in source and binary forms, with or without @@ -27,7 +27,7 @@ import os.path import stat import xml.etree.ElementTree -from ConfigParser import ConfigParser +from configparser import ConfigParser class Config(object): @@ -67,12 +67,12 @@ class Config(object): # convert allowed(MAC)addresses string to list if 'allowedaddresses' in result[zoneid] and result[zoneid]['allowedaddresses'].strip() != '': result[zoneid]['allowedaddresses'] = \ - map(lambda x: x.strip(), result[zoneid]['allowedaddresses'].split(',')) + [x.strip() for x in result[zoneid]['allowedaddresses'].split(',')] else: result[zoneid]['allowedaddresses'] = list() if 'allowedmacaddresses' in result[zoneid] and result[zoneid]['allowedmacaddresses'].strip() != '': result[zoneid]['allowedmacaddresses'] = \ - map(lambda x: x.strip(), result[zoneid]['allowedmacaddresses'].split(',')) + [x.strip() for x in result[zoneid]['allowedmacaddresses'].split(',')] else: result[zoneid]['allowedmacaddresses'] = list() return result diff --git a/src/opnsense/scripts/OPNsense/CaptivePortal/lib/arp.py b/src/opnsense/scripts/OPNsense/CaptivePortal/lib/arp.py index 50fa5aced..e8118ca50 100755 --- a/src/opnsense/scripts/OPNsense/CaptivePortal/lib/arp.py +++ b/src/opnsense/scripts/OPNsense/CaptivePortal/lib/arp.py @@ -1,5 +1,5 @@ """ - Copyright (c) 2015 Ad Schellevis + Copyright (c) 2015-2019 Ad Schellevis All rights reserved. Redistribution and use in source and binary forms, with or without @@ -50,13 +50,12 @@ class ARP(object): with tempfile.NamedTemporaryFile() as output_stream: subprocess.check_call(['/usr/sbin/arp', '-an'], stdout=output_stream, stderr=subprocess.STDOUT) output_stream.seek(0) - for line in output_stream.read().split('\n'): - line_parts = line.split() + for line in output_stream: + line_parts = line.decode().split() if len(line_parts) < 6 or line_parts[2] != 'at' or line_parts[4] != 'on': continue - - if len(line_parts[1]) < 2 or line_parts[1][0] != '(' or line_parts[1][-1] != ')': + elif len(line_parts[1]) < 2 or line_parts[1][0] != '(' or line_parts[1][-1] != ')': continue address = line_parts[1][1:-1] diff --git a/src/opnsense/scripts/OPNsense/CaptivePortal/lib/daemonize.py b/src/opnsense/scripts/OPNsense/CaptivePortal/lib/daemonize.py index 7468805c8..5037ac582 100755 --- a/src/opnsense/scripts/OPNsense/CaptivePortal/lib/daemonize.py +++ b/src/opnsense/scripts/OPNsense/CaptivePortal/lib/daemonize.py @@ -1,5 +1,3 @@ -#!/usr/local/bin/python2.7 - # original source from https://github.com/thesharp/daemonize import fcntl diff --git a/src/opnsense/scripts/OPNsense/CaptivePortal/lib/db.py b/src/opnsense/scripts/OPNsense/CaptivePortal/lib/db.py index e1d95a800..0da05a3eb 100755 --- a/src/opnsense/scripts/OPNsense/CaptivePortal/lib/db.py +++ b/src/opnsense/scripts/OPNsense/CaptivePortal/lib/db.py @@ -1,5 +1,5 @@ """ - Copyright (c) 2015 Ad Schellevis + Copyright (c) 2015-2019 Ad Schellevis All rights reserved. Redistribution and use in source and binary forms, with or without @@ -84,9 +84,14 @@ class DB(object): :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 + , cc.ip_address from cp_clients cc where cc.deleted = 0 and cc.zoneid = :zoneid @@ -117,7 +122,7 @@ class DB(object): response['ipAddress'] = ip_address response['macAddress'] = mac_address response['startTime'] = time.time() # record creation = sign-in time - response['sessionId'] = base64.b64encode(os.urandom(16)) # generate a new random session id + response['sessionId'] = base64.b64encode(os.urandom(16)).decode() # generate a new random session id cur = self._connection.cursor() # set cp_client as deleted in case there's already a user logged-in at this ip address. @@ -139,6 +144,8 @@ class DB(object): def update_client_ip(self, zoneid, sessionid, ip_address): """ change client ip address """ + if type(sessionid) == bytes: + sessionid = sessionid.decode() cur = self._connection.cursor() cur.execute("""update cp_clients set ip_address = :ip_address @@ -154,6 +161,8 @@ class DB(object): :param sessionid: session id :return: client info before removal or None if client not found """ + if type(sessionid) == bytes: + sessionid = sessionid.decode() cur = self._connection.cursor() cur.execute(""" select * from cp_clients diff --git a/src/opnsense/scripts/OPNsense/CaptivePortal/lib/ipfw.py b/src/opnsense/scripts/OPNsense/CaptivePortal/lib/ipfw.py index cfeff18a6..7e967a953 100755 --- a/src/opnsense/scripts/OPNsense/CaptivePortal/lib/ipfw.py +++ b/src/opnsense/scripts/OPNsense/CaptivePortal/lib/ipfw.py @@ -1,5 +1,5 @@ """ - Copyright (c) 2015 Ad Schellevis + Copyright (c) 2015-2019 Ad Schellevis All rights reserved. Redistribution and use in source and binary forms, with or without @@ -46,7 +46,8 @@ class IPFW(object): stdout=output_stream, stderr=devnull) output_stream.seek(0) - for line in output_stream.read().split('\n'): + for line in output_stream: + line = line.decode() if line.split(' ')[0].strip() != "": # process / 32 nets as single addresses to align better with the rule syntax # and local administration. @@ -103,8 +104,8 @@ class IPFW(object): stdout=output_stream, stderr=devnull) output_stream.seek(0) - for line in output_stream.read().split('\n'): - parts = line.split() + for line in output_stream: + parts = line.decode().split() if len(parts) > 5: if 30001 <= int(parts[0]) <= 50000 and parts[4] == 'count': line_pkts = int(parts[1]) diff --git a/src/opnsense/scripts/OPNsense/CaptivePortal/listClients.py b/src/opnsense/scripts/OPNsense/CaptivePortal/listClients.py index 0a340fd28..58e2c5c0c 100755 --- a/src/opnsense/scripts/OPNsense/CaptivePortal/listClients.py +++ b/src/opnsense/scripts/OPNsense/CaptivePortal/listClients.py @@ -1,7 +1,7 @@ -#!/usr/local/bin/python2.7 +#!/usr/local/bin/python3 """ - Copyright (c) 2015 Ad Schellevis + Copyright (c) 2015-2019 Ad Schellevis All rights reserved. Redistribution and use in source and binary forms, with or without @@ -45,22 +45,22 @@ for param in sys.argv[1:]: current_param = None if parameters['zoneid'] is not None: - cpDB = DB() - response = cpDB.list_clients(parameters['zoneid']) + response = DB().list_clients(parameters['zoneid']) else: response = [] # output result as plain text or json if parameters['output_type'] != 'json': - heading = {'sessionId': 'sessionid', - 'userName': 'username', - 'ipAddress': 'ip_address', - 'macAddress': 'mac_address', - 'total_bytes': 'total_bytes', - 'idletime': 'idletime', - 'totaltime': 'totaltime', - 'acc_timeout': 'acc_session_timeout' - } + heading = { + 'sessionId': 'sessionid', + 'userName': 'username', + 'ipAddress': 'ip_address', + 'macAddress': 'mac_address', + 'total_bytes': 'total_bytes', + 'idletime': 'idletime', + 'totaltime': 'totaltime', + 'acc_timeout': 'acc_session_timeout' + } heading_format = '%(sessionId)-30s %(userName)-25s %(ipAddress)-20s %(macAddress)-20s '\ + '%(total_bytes)-15s %(idletime)-10s %(totaltime)-10s %(acc_timeout)-10s' print (heading_format % heading) diff --git a/src/opnsense/scripts/OPNsense/CaptivePortal/overlay_template.py b/src/opnsense/scripts/OPNsense/CaptivePortal/overlay_template.py index a27bd6850..9cd3a6c2d 100755 --- a/src/opnsense/scripts/OPNsense/CaptivePortal/overlay_template.py +++ b/src/opnsense/scripts/OPNsense/CaptivePortal/overlay_template.py @@ -1,7 +1,7 @@ -#!/usr/local/bin/python2.7 +#!/usr/local/bin/python3 """ - Copyright (c) 2015 Ad Schellevis + Copyright (c) 2015-2019 Ad Schellevis All rights reserved. Redistribution and use in source and binary forms, with or without @@ -32,7 +32,8 @@ import os import sys import zipfile -import StringIO +import base64 +from io import BytesIO from lib import Config if len(sys.argv) > 1: @@ -42,8 +43,8 @@ if len(sys.argv) > 1: 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) - zip_content = template_data.decode('base64') - input_data = StringIO.StringIO(zip_content) + zip_content = base64.b64decode(template_data) + input_data = BytesIO(zip_content) with zipfile.ZipFile(input_data, mode='r', compression=zipfile.ZIP_DEFLATED) as zf_in: for zf_info in zf_in.infolist(): if zf_info.filename[-1] != '/': @@ -53,11 +54,11 @@ if len(sys.argv) > 1: os.makedirs(file_target_directory) with open(target_filename, 'wb') as f_out: f_out.write(zf_in.read(zf_info.filename)) - os.chmod(target_filename, 0444) + os.chmod(target_filename, 0o444) # write zone settings filename = '%sjs/zone.js' % target_directory with open(filename, 'wb') as f_out: - f_out.write('var zoneid = %s' % zoneid) - os.chmod(filename, 0444) + f_out.write(('var zoneid = %s' % zoneid).encode()) + os.chmod(filename, 0o444) sys.exit(0) diff --git a/src/opnsense/scripts/OPNsense/CaptivePortal/set_session_restrictions.py b/src/opnsense/scripts/OPNsense/CaptivePortal/set_session_restrictions.py index 694917804..b98f36559 100755 --- a/src/opnsense/scripts/OPNsense/CaptivePortal/set_session_restrictions.py +++ b/src/opnsense/scripts/OPNsense/CaptivePortal/set_session_restrictions.py @@ -1,6 +1,6 @@ -#!/usr/local/bin/python2.7 +#!/usr/local/bin/python3 """ - Copyright (c) 2015 Ad Schellevis + Copyright (c) 2015-2019 Ad Schellevis All rights reserved. Redistribution and use in source and binary forms, with or without @@ -49,6 +49,6 @@ if parameters['zoneid'] is not None and parameters['sessionid'] is not None: # output result as plain text or json if parameters['output_type'] != 'json': for item in response: - print '%20s %s' % (item, response[item]) + print ('%20s %s' % (item, response[item])) else: print(ujson.dumps(response)) diff --git a/src/opnsense/scripts/OPNsense/CaptivePortal/strip_template.py b/src/opnsense/scripts/OPNsense/CaptivePortal/strip_template.py index e184c48d8..b3dfb7f5e 100755 --- a/src/opnsense/scripts/OPNsense/CaptivePortal/strip_template.py +++ b/src/opnsense/scripts/OPNsense/CaptivePortal/strip_template.py @@ -1,7 +1,7 @@ -#!/usr/local/bin/python2.7 +#!/usr/local/bin/python3 """ - Copyright (c) 2015 Ad Schellevis + Copyright (c) 2015-2019 Ad Schellevis All rights reserved. Redistribution and use in source and binary forms, with or without @@ -33,9 +33,10 @@ import sys import os.path import binascii -import StringIO import zipfile import ujson +import base64 +from io import BytesIO from hashlib import md5 htdocs_default_root = '/usr/local/opnsense/scripts/OPNsense/CaptivePortal/htdocs_default' @@ -60,7 +61,7 @@ if len(sys.argv) < 2: else: input_filename = '/tmp/%s' % os.path.basename(sys.argv[1]) try: - zip_content = open(input_filename, 'r').read().decode('base64') + zip_content = base64.b64decode(open(input_filename, 'rb').read()) except binascii.Error: # not in base64 response['error'] = 'Not a base64 encoded file' @@ -70,8 +71,8 @@ else: if 'error' not in response: exclude_list = load_exclude_list() - input_data = StringIO.StringIO(zip_content) - output_data = StringIO.StringIO() + input_data = BytesIO(zip_content) + output_data = BytesIO() with zipfile.ZipFile(input_data, mode='r', compression=zipfile.ZIP_DEFLATED) as zf_in: with zipfile.ZipFile(output_data, mode='w', compression=zipfile.ZIP_DEFLATED) as zf_out: # the zip content may be in a folder, use index to track actual location @@ -101,7 +102,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'] = base64.b64encode(output_data.getvalue()).decode().replace('\n', '') response['size'] = len(response['payload']) print(ujson.dumps(response))