diff options
| author | 2011-10-03 11:43:59 +0200 | |
|---|---|---|
| committer | 2011-10-03 11:43:59 +0200 | |
| commit | 5c3dbb734b7f958cb1bb227c2ffd934906820b3e (patch) | |
| tree | e123e91e90680cd14474ffd265eb1c4808746fe2 /module | |
| parent | fixed urlmatcher, clear links on start option (diff) | |
| download | pyload-5c3dbb734b7f958cb1bb227c2ffd934906820b3e.tar.xz | |
new SafeEval
Diffstat (limited to 'module')
| -rw-r--r-- | module/lib/SafeEval.py | 103 | ||||
| -rw-r--r-- | module/lib/SecureXMLRPCServer.py | 120 | ||||
| -rw-r--r-- | module/plugins/PluginManager.py | 6 | ||||
| -rw-r--r-- | module/web/api_app.py | 6 | 
4 files changed, 42 insertions, 193 deletions
| diff --git a/module/lib/SafeEval.py b/module/lib/SafeEval.py index 8ec9766e6..8fc57f261 100644 --- a/module/lib/SafeEval.py +++ b/module/lib/SafeEval.py @@ -1,70 +1,47 @@ -## {{{ http://code.activestate.com/recipes/364469/ (r2) -import compiler +## {{{ http://code.activestate.com/recipes/286134/ (r3) (modified) +import dis -class Unsafe_Source_Error(Exception): -    def __init__(self,error,descr = None,node = None): -        self.error = error -        self.descr = descr -        self.node = node -        self.lineno = getattr(node,"lineno",None) -         -    def __repr__(self): -        return "Line %d.  %s: %s" % (self.lineno, self.error, self.descr) -    __str__ = __repr__     -            -class SafeEval(object): -     -    def visit(self, node,**kw): -        cls = node.__class__ -        meth = getattr(self,'visit'+cls.__name__,self.default) -        return meth(node, **kw) -             -    def default(self, node, **kw): -        for child in node.getChildNodes(): -            return self.visit(child, **kw) -             -    visitExpression = default -     -    def visitConst(self, node, **kw): -        return node.value +_const_codes = map(dis.opmap.__getitem__, [ +    'POP_TOP','ROT_TWO','ROT_THREE','ROT_FOUR','DUP_TOP', +    'BUILD_LIST','BUILD_MAP','BUILD_TUPLE', +    'LOAD_CONST','RETURN_VALUE','STORE_SUBSCR' +    ]) -    def visitDict(self,node,**kw): -        return dict([(self.visit(k),self.visit(v)) for k,v in node.items]) -         -    def visitTuple(self,node, **kw): -        return tuple(self.visit(i) for i in node.nodes) -         -    def visitList(self,node, **kw): -        return [self.visit(i) for i in node.nodes] -class SafeEvalWithErrors(SafeEval): +_load_names = ['False', 'True', 'null', 'true', 'false'] -    def default(self, node, **kw): -        raise Unsafe_Source_Error("Unsupported source construct", -                                node.__class__,node) -             -    def visitName(self,node, **kw): -        if node.name == "None": -            return None -        elif node.name == "True": -            return True -        elif node.name == "False": -            return False +_locals = {'null': None, 'true': True, 'false': False} + +def _get_opcodes(codeobj): +    i = 0 +    opcodes = [] +    s = codeobj.co_code +    names = codeobj.co_names +    while i < len(s): +        code = ord(s[i]) +        opcodes.append(code) +        if code >= dis.HAVE_ARGUMENT: +            i += 3          else: -            raise Unsafe_Source_Error("Strings must be quoted",  -                                 node.name, node) -                                  -    # Add more specific errors if desired -             +            i += 1 +    return opcodes, names -def safe_eval(source, fail_on_error = True): -    walker = fail_on_error and SafeEvalWithErrors() or SafeEval() -    try: -        ast = compiler.parse(source,"eval") -    except SyntaxError, err: -        raise +def test_expr(expr, allowed_codes):      try: -        return walker.visit(ast) -    except Unsafe_Source_Error, err: -        raise -## end of http://code.activestate.com/recipes/364469/ }}} +        c = compile(expr, "", "eval") +    except: +        raise ValueError, "%s is not a valid expression" % expr +    codes, names = _get_opcodes(c) +    for code in codes: +        if code not in allowed_codes: +            for n in names: +                if n not in _load_names: +                    raise ValueError, "opcode %s not allowed" % dis.opname[code] +    return c + + +def const_eval(expr): +    c = test_expr(expr, _const_codes) +    return eval(c, None, _locals) + +## end of http://code.activestate.com/recipes/286134/ }}} diff --git a/module/lib/SecureXMLRPCServer.py b/module/lib/SecureXMLRPCServer.py deleted file mode 100644 index 33b91a187..000000000 --- a/module/lib/SecureXMLRPCServer.py +++ /dev/null @@ -1,120 +0,0 @@ -# Source: http://sources.gentoo.org/viewcvs.py/gimli/server/SecureXMLRPCServer.py?view=markup -#         which seems to be based on http://www.sabren.net/code/python/SecureXMLRPCServer.py -# -# Changes: -#     2007-01-06 Christian Hoffmann <ch@hoffie.info> -#         * Bugfix: replaced getattr by hasattr in the conditional -#           (lead to an error otherwise) -#         * SecureXMLRPCServer: added self.instance = None, otherwise a "wrong" -#           exception is raised when calling unknown methods via xmlrpc -#         * Added HTTP Basic authentication support -#  -# Modified for the Sceradon project -# -# This code is in the public domain -# and is provided AS-IS WITH NO WARRANTY WHATSOEVER. -# $Id: SecureXMLRPCServer.py 5 2007-01-06 17:54:13Z hoffie $ - -from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler -import SocketServer -import socket -import base64 - - -class SecureSocketConnection: -    def __init__(self, connection): -        self.__dict__["connection"] = connection -     -    def __getattr__(self, name): -        return getattr(self.__dict__["connection"], name) -     -    def __setattr__(self, name, value): -        setattr(self.__dict__["connection"], name, value) -     -    def shutdown(self, how=1): -        self.__dict__["connection"].shutdown() -     -    def accept(self): -        connection, address = self.__dict__["connection"].accept() -        return (SecureSocketConnection(connection), address) - -class SecureSocketServer(SocketServer.TCPServer, SocketServer.ThreadingMixIn): -    def __init__(self, addr, cert, key, requestHandler, verify_cert_func=None): -        SSL = __import__("OpenSSL", globals(), locals(), "SSL", -1).SSL -        SocketServer.TCPServer.__init__(self, addr, requestHandler) -        ctx = SSL.Context(SSL.SSLv23_METHOD) -        if not verify_cert_func and hasattr(self, 'verify_client_cert'): -            verify_cert_func = getattr(self, 'verify_client_cert') -        if verify_cert_func: -            ctx.set_verify(SSL.VERIFY_PEER|SSL.VERIFY_FAIL_IF_NO_PEER_CERT, verify_cert_func) -        ctx.use_privatekey_file(key) -        ctx.use_certificate_file(cert) -         -        tmpConnection = SSL.Connection(ctx, socket.socket(socket.AF_INET, socket.SOCK_STREAM)) -        self.socket = SecureSocketConnection(tmpConnection) -         -        self.server_bind() -        self.server_activate() - -    def finish_request(self, request, client_address): -        """Finish one request by instantiating RequestHandlerClass.""" -        self.RequestHandlerClass(request, client_address, self) -         -####################################### -########### Request Handler ########### -####################################### - -class AuthXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): -    def __init__(self, request, client_address, server): -        self.checkAuth = server.checkAuth -        SimpleXMLRPCRequestHandler.__init__(self, request, client_address, server) -     -    def setup(self): -        self.connection = self.request -        self.rfile = socket._fileobject(self.request, "rb", self.rbufsize) -        self.wfile = socket._fileobject(self.request, "wb", self.wbufsize) -     -    def do_POST(self): -        # authentication -        if self.checkAuth is not None: # explicit None! -            if self.headers.has_key('authorization') and self.headers['authorization'].startswith('Basic '): -                authenticationString = base64.b64decode(self.headers['authorization'].split(' ')[1]) -                if authenticationString.find(':') != -1: -                    username, password = authenticationString.split(':', 1) -                    if self.checkAuth(username, password, self.client_address[0]): -                        return SimpleXMLRPCRequestHandler.do_POST(self) -            self.send_response(401) -            self.end_headers() -            return False -        return SimpleXMLRPCRequestHandler.do_POST(self) - -class SecureXMLRPCRequestHandler(AuthXMLRPCRequestHandler): -    def __init__(self, request, client_address, server, client_digest=None): -        self.checkAuth = server.checkAuth -        SimpleXMLRPCRequestHandler.__init__(self, request, client_address, server) -        self.client_digest = client_digest - -##################################### -########### XMLRPC Server ########### -##################################### - -class AuthXMLRPCServer(SimpleXMLRPCServer): -    def __init__(self, address, checkAuth = None, handler=AuthXMLRPCRequestHandler): -        SimpleXMLRPCServer.__init__(self, address, requestHandler=handler) -        self.logRequests = False -        self._send_traceback_header = False -        self.encoding = "utf-8" -        self.allow_none = True -        self.checkAuth = checkAuth - -class SecureXMLRPCServer(AuthXMLRPCServer, SecureSocketServer): -    def __init__(self, address, cert, key, checkAuth = None, handler=SecureXMLRPCRequestHandler, verify_cert_func=None): -        self.logRequests = False -        self._send_traceback_header = False -        self.encoding = "utf-8" -        self.allow_none = True -        SecureSocketServer.__init__(self, address, cert, key, handler, verify_cert_func) -        # This comes from SimpleXMLRPCServer.__init__()->SimpleXMLRPCDispatcher.__init__() -        self.funcs = {} -        self.instance = None -        self.checkAuth = checkAuth diff --git a/module/plugins/PluginManager.py b/module/plugins/PluginManager.py index 62460c644..0bf15f1a8 100644 --- a/module/plugins/PluginManager.py +++ b/module/plugins/PluginManager.py @@ -26,11 +26,7 @@ from sys import version_info  from itertools import chain  from traceback import print_exc -try: -    from ast import literal_eval -except ImportError: # python 2.5 -    from module.lib.SafeEval import safe_eval as literal_eval - +from module.lib.SafeEval import const_eval as literal_eval  from module.ConfigParser import IGNORE  class PluginManager(): diff --git a/module/web/api_app.py b/module/web/api_app.py index c14eb6ed5..61be8b510 100644 --- a/module/web/api_app.py +++ b/module/web/api_app.py @@ -13,11 +13,7 @@ from utils import toDict, set_session  from webinterface import PYLOAD  from module.common.json_layer import json - -try: -    from ast import literal_eval -except ImportError: # python 2.5 -    from module.lib.SafeEval import safe_eval as literal_eval +from module.lib.SafeEval import const_eval as literal_eval  # json encoder that accepts TBase objects  class TBaseEncoder(json.JSONEncoder): | 
