mirror of
https://github.com/naruxde/revpipyload.git
synced 2025-11-09 07:28:03 +01:00
IP Prüfung für XML-RPC begonnen. Prüft lediglich auf IP und noch keine Level
This commit is contained in:
@@ -12,6 +12,72 @@ from re import match as rematch
|
||||
from subprocess import Popen, PIPE
|
||||
|
||||
|
||||
class IpAclManager():
|
||||
|
||||
"""Verwaltung fuer IP Adressen und deren ACL Level."""
|
||||
|
||||
def __init__(self, acl=None, minlevel=0, maxlevel=1):
|
||||
"""Init IpAclManager class.
|
||||
@param acl ACL Liste fuer Berechtigungen als <class 'str'>"""
|
||||
if minlevel >= maxlevel:
|
||||
raise ValueError("minlevel is smaller or equal than maxlevel")
|
||||
|
||||
self.__dict_acl = {}
|
||||
self.__rawacl = ""
|
||||
self.__re_ipacl = "(([\\d\\*]{1,3}\\.){3}[\\d\\*]{1,3},[" \
|
||||
+ str(minlevel) + "-" + str(maxlevel) + "] ?)*"
|
||||
|
||||
# Liste erstellen, wenn übergeben
|
||||
if acl is not None:
|
||||
self.__set_acl(acl)
|
||||
|
||||
def __get_acl(self):
|
||||
"""Getter fuer den rohen ACL-String.
|
||||
return ACLs als <class 'str'>"""
|
||||
return self.__rawacl
|
||||
|
||||
def __refullmatch(self, regex, string):
|
||||
"""re.fullmatch wegen alter python version aus wheezy nachgebaut.
|
||||
|
||||
@param regex RegEx Statement
|
||||
@param string Zeichenfolge gegen die getestet wird
|
||||
@return True, wenn komplett passt sonst False
|
||||
|
||||
"""
|
||||
m = rematch(regex, string)
|
||||
return m is not None and m.end() == len(string)
|
||||
|
||||
def __set_acl(self, value):
|
||||
"""Uebernimmt neue ACL-Liste fuer die Ausertung der Level.
|
||||
@param value Neue ACL-Liste als <class 'str'>"""
|
||||
if type(value) != str:
|
||||
raise ValueError("parameter acl must be <class 'str'>")
|
||||
|
||||
if not self.__refullmatch(self.__re_ipacl, value):
|
||||
raise ValueError("acl format ist not okay - 1.2.3.4,0 5.6.7.8,1")
|
||||
|
||||
# Klassenwerte übernehmen
|
||||
self.__dict_acl = {}
|
||||
self.__rawacl = value
|
||||
|
||||
# Liste neu füllen mit regex Strings
|
||||
for ip_level in value.split():
|
||||
ip, level = ip_level.split(",", 1)
|
||||
ip = ip.replace(".", "\\.").replace("*", "\\d{1,3}")
|
||||
self.__dict_acl[ip] = int(level)
|
||||
|
||||
def get_acllevel(self, ipaddress):
|
||||
"""Prueft IP gegen ACL List und gibt ACL-Wert aus.
|
||||
@param ipaddress zum pruefen
|
||||
@return int() ACL Wert oder -1 wenn nicht gefunden"""
|
||||
for aclip in sorted(self.__dict_acl, reverse=True):
|
||||
if self.__refullmatch(aclip, ipaddress):
|
||||
return self.__dict_acl[aclip]
|
||||
return -1
|
||||
|
||||
acl = property(__get_acl, __set_acl)
|
||||
|
||||
|
||||
def _ipmatch(ipaddress, dict_acl):
|
||||
"""Prueft IP gegen ACL List und gibt ACL aus.
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@ import os
|
||||
import signal
|
||||
import tarfile
|
||||
import zipfile
|
||||
from concurrent import futures
|
||||
from configparser import ConfigParser
|
||||
from helper import refullmatch
|
||||
from json import loads as jloads
|
||||
@@ -48,7 +47,7 @@ from tempfile import mkstemp
|
||||
from threading import Event
|
||||
from time import asctime
|
||||
from xmlrpc.client import Binary
|
||||
from xmlrpc.server import SimpleXMLRPCServer
|
||||
from xrpcserver import SaveXMLRPCServer
|
||||
|
||||
pyloadversion = "0.6.0"
|
||||
re_ipacl = "(([\\d\\*]{1,3}\\.){3}[\\d\\*]{1,3},[0-1] ?)*"
|
||||
@@ -76,7 +75,6 @@ class RevPiPyLoad():
|
||||
self.plc = None
|
||||
self.plc_pause = False
|
||||
self.tfile = {}
|
||||
self.tpe = None
|
||||
self.xsrv = None
|
||||
self.xml_ps = None
|
||||
|
||||
@@ -172,13 +170,14 @@ class RevPiPyLoad():
|
||||
# XMLRPC-Server Instantiieren und konfigurieren
|
||||
if self.xmlrpc >= 1:
|
||||
proginit.logger.debug("create xmlrpc server")
|
||||
self.xsrv = SimpleXMLRPCServer(
|
||||
self.xsrv = SaveXMLRPCServer(
|
||||
(
|
||||
"",
|
||||
int(self.globalconfig["DEFAULT"].get("xmlrpcport", 55123))
|
||||
),
|
||||
logRequests=False,
|
||||
allow_none=True
|
||||
allow_none=True,
|
||||
acl=self.xmlrpcacl
|
||||
)
|
||||
self.xsrv.register_introspection_functions()
|
||||
self.xsrv.register_multicall_functions()
|
||||
@@ -387,8 +386,7 @@ class RevPiPyLoad():
|
||||
|
||||
if self.xmlrpc >= 1:
|
||||
proginit.logger.info("start xmlrpc-server")
|
||||
self.tpe = futures.ThreadPoolExecutor(max_workers=1)
|
||||
self.tpe.submit(self.xsrv.serve_forever)
|
||||
self.xsrv.start()
|
||||
|
||||
if self.plcslave:
|
||||
# Slaveausfuehrung übergeben
|
||||
@@ -450,9 +448,7 @@ class RevPiPyLoad():
|
||||
|
||||
if self.xmlrpc >= 1:
|
||||
proginit.logger.info("shutting down xmlrpc-server")
|
||||
self.xsrv.shutdown()
|
||||
self.tpe.shutdown()
|
||||
self.xsrv.server_close()
|
||||
self.xsrv.stop()
|
||||
|
||||
# Logreader schließen
|
||||
self.logr.closeall()
|
||||
|
||||
88
revpipyload/xrpcserver.py
Normal file
88
revpipyload/xrpcserver.py
Normal file
@@ -0,0 +1,88 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# RevPiPyLoad
|
||||
#
|
||||
# Webpage: https://revpimodio.org/revpipyplc/
|
||||
# (c) Sven Sager, License: LGPLv3
|
||||
#
|
||||
"""XML-RPC Server anpassungen fuer Absicherung."""
|
||||
from helper import IpAclManager
|
||||
from concurrent import futures
|
||||
from xmlrpc.server import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
|
||||
|
||||
|
||||
class SaveXMLRPCServer(SimpleXMLRPCServer):
|
||||
|
||||
"""Erstellt einen erweiterten XMLRPCServer."""
|
||||
|
||||
aclmgr = IpAclManager()
|
||||
|
||||
def __init__(
|
||||
self, addr, logRequests=True, allow_none=False,
|
||||
use_builtin_types=False, acl=""):
|
||||
"""Init SaveXMLRPCServer class."""
|
||||
|
||||
SaveXMLRPCServer.aclmgr.acl = acl
|
||||
|
||||
# Vererbte Klasse instantiieren
|
||||
super().__init__(
|
||||
addr=addr,
|
||||
requestHandler=SaveXMLRPCRequestHandler,
|
||||
logRequests=logRequests,
|
||||
allow_none=allow_none,
|
||||
encoding="utf-8",
|
||||
bind_and_activate=False,
|
||||
use_builtin_types=use_builtin_types
|
||||
)
|
||||
|
||||
# Klassenvariablen
|
||||
self.tpe = futures.ThreadPoolExecutor(max_workers=1)
|
||||
self.fut = None
|
||||
|
||||
def isAlive(self):
|
||||
"""Prueft ob der XML RPC Server laeuft.
|
||||
@return True, wenn Server noch laeuft"""
|
||||
return False if self.fut is None else self.fut.running()
|
||||
|
||||
def start(self):
|
||||
"""Startet den XML-RPC Server."""
|
||||
if self.fut is None:
|
||||
self.server_bind()
|
||||
self.server_activate()
|
||||
self.fut = self.tpe.submit(self.serve_forever)
|
||||
else:
|
||||
raise RuntimeError("savexmlrpcservers can only be started once")
|
||||
|
||||
def stop(self):
|
||||
"""Stoppt den XML-RPC Server."""
|
||||
if self.fut is not None:
|
||||
self.shutdown()
|
||||
self.tpe.shutdown()
|
||||
self.server_close()
|
||||
else:
|
||||
raise RuntimeError("save xml rpc server was not started")
|
||||
|
||||
|
||||
class SaveXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||
|
||||
"""Verwaltet die XML-Requests und prueft Berechtigungen."""
|
||||
|
||||
def parse_request(self):
|
||||
"""Berechtigungen pruefen.
|
||||
@return True, wenn Parsen erfolgreich war"""
|
||||
# Request parsen und ggf. schon abbrechen
|
||||
if not super().parse_request():
|
||||
return False
|
||||
|
||||
# IP-Adresse prüfen
|
||||
int_acl = SaveXMLRPCServer.aclmgr.get_acllevel(self.address_string())
|
||||
if int_acl >= 0:
|
||||
return True
|
||||
else:
|
||||
self.send_error(
|
||||
401,
|
||||
"IP '{}' not allowed with acl level '{}'"
|
||||
"".format(self.address_string(), int_acl)
|
||||
)
|
||||
|
||||
return False
|
||||
Reference in New Issue
Block a user