"""Restricted execution facilities.

The class RExec exports methods r_exec(), r_eval(), r_execfile(), and
r_import(), which correspond roughly to the built-in operations
exec, eval(), execfile() and import, but executing the code in an
environment that only exposes those built-in operations that are
deemed safe.  To this end, a modest collection of 'fake' modules is
created which mimics the standard modules by the same names.  It is a
policy decision which built-in modules and operations are made
available; this module provides a reasonable default, but derived
classes can change the policies e.g. by overriding or extending class
variables like ok_builtin_modules or methods like make_sys().

XXX To do:
- r_open should allow writing tmp dir
- r_exec etc. with explicit globals/locals? (Use rexec("exec ... in ...")?)

"""


import sys
import __builtin__
import os
import ihooks
import imp

__all__ = ["RExec"]

class FileBase:

    ok_file_methods = ('fileno', 'flush', 'isatty', 'read', 'readline',
            'readlines', 'seek', 'tell', 'write', 'writelines', 'xreadlines',
            '__iter__')


class FileWrapper(FileBase):

    # XXX This is just like a Bastion -- should use that!

    def __init__(self, f):
        for m in self.ok_file_methods:
            if not hasattr(self, m) and hasattr(f, m):
                setattr(self, m, getattr(f, m))

    def close(self):
        self.flush()


TEMPLATE = """
def %s(self, *args):
        return getattr(self.mod, self.name).%s(*args)
"""

class FileDelegate(FileBase):

    def __init__(self, mod, name):
        self.mod = mod
        self.name = name

    for m in FileBase.ok_file_methods + ('close',):
        exec TEMPLATE % (m, m)


class RHooks(ihooks.Hooks):

    def __init__(self, *args):
        # Hacks to support both old and new interfaces:
        # old interface was RHooks(rexec[, verbose])
        # new interface is RHooks([verbose])
        verbose = 0
        rexec = None
        if args and type(args[-1]) == type(0):
            verbose = args[-1]
            args = args[:-1]
        if args and hasattr(args[0], '__class__'):
            rexec = args[0]
            args = args[1:]
        if args:
            raise TypeError, "too many arguments"
        ihooks.Hooks.__init__(self, verbose)
        self.rexec = rexec

    def set_rexec(self, rexec):
        # Called by RExec instance to complete initialization
        self.rexec = rexec

    def get_suffixes(self):
        return self.rexec.get_suffixes()

    def is_builtin(self, name):
        return self.rexec.is_builtin(name)

    def init_builtin(self, name):
        m = __import__(name)
        return self.rexec.copy_except(m, ())

    def init_frozen(self, name): raise SystemError, "don't use this"
    def load_source(self, *args): raise SystemError, "don't use this"
    def load_compiled(self, *args): raise SystemError, "don't use this"
    def load_package(self, *args): raise SystemError, "don't use this"

    def load_dynamic(self, name, filename, file):
        return self.rexec.load_dynamic(name, filename, file)

    def add_module(self, name):
        return self.rexec.add_module(name)

    def modules_dict(self):
        return self.rexec.modules

    def default_path(self):
        return self.rexec.modules['sys'].path


# XXX Backwards compatibility
RModuleLoader = ihooks.FancyModuleLoader
RModuleImporter = ihooks.ModuleImporter


class RExec(ihooks._Verbose):
    """Basic restricted execution framework.

    Code executed in this restricted environment will only have access to
    modules and functions that are deemed safe; you can subclass RExec to
    add or remove capabilities as desired.

    The RExec class can prevent code from performing unsafe operations like
    reading or writing disk files, or using TCP/IP sockets.  However, it does
    not protect against code using extremely large amounts of memory or
    processor time.

    """

    ok_path = tuple(sys.path)           # That's a policy decision

    ok_builtin_modules = ('audioop', 'array', 'binascii',
                          'cmath', 'errno', 'imageop',
                          'marshal', 'math', 'md5', 'operator',
                          'parser', 'regex', 'rotor', 'select',
                          'sha', '_sre', 'strop', 'struct', 'time',
                          'xreadlines', '_weakref')

    ok_posix_names = ('error', 'fstat', 'listdir', 'lstat', 'readlink',
                      'stat', 'times', 'uname', 'getpid', 'getppid',
                      'getcwd', 'getuid', 'getgid', 'geteuid', 'getegid')

    ok_sys_names = ('byteorder', 'copyright', 'exit', 'getdefaultencoding',
                    'getrefcount', 'hexversion', 'maxint', 'maxunicode',
                    'platform', 'ps1', 'ps2', 'version', 'version_info')

    nok_builtin_names = ('open', 'file', 'reload', '__import__')

    ok_file_types = (imp.C_EXTENSION, imp.PY_SOURCE)

    def __init__(self, hooks = None, verbose = 0):
        """Returns an instance of the RExec class.

        The hooks parameter is an instance of the RHooks class or a subclass
        of it.  If it is omitted or None, the default RHooks class is
        instantiated.

        Whenever the RExec module searches for a module (even a built-in one)
        or reads a module's code, it doesn't actually go out to the file
        system itself.  Rather, it calls methods of an RHooks instance that
        was passed to or created by its constructor.  (Actually, the RExec
        object doesn't make these calls --- they are made by a module loader
        object that's part of the RExec object.  This allows another level of
        flexibility, which can be useful when changing the mechanics of
        import within the restricted environment.)

        By providing an alternate RHooks object, we can control the file
        system accesses made to import a module, without changing the
        actual algorithm that controls the order in which those accesses are
        made.  For instance, we could substitute an RHooks object that
        passes all filesystem requests to a file server elsewhere, via some
        RPC mechanism such as ILU.  Grail's applet loader uses this to support
        importing applets from a URL for a directory.

        If the verbose parameter is true, additional debugging output may be
        sent to standard output.

        """

        raise RuntimeError, "This code is not secure in Python 2.2 and 2.3"

        ihooks._Verbose.__init__(self, verbose)
        # XXX There's a circular reference here:
        self.hooks = hooks or RHooks(verbose)
        self.hooks.set_rexec(self)
        self.modules = {}
        self.ok_dynamic_modules = self.ok_builtin_modules
        list = []
        for mname in self.ok_builtin_modules:
            if mname in sys.builtin_module_names:
                list.append(mname)
        self.ok_builtin_modules = tuple(list)
        self.set_trusted_path()
        self.make_builtin()
        self.make_initial_modules()
        # make_sys must be last because it adds the already created
        # modules to its builtin_module_names
        self.make_sys()
        self.loader = RModuleLoader(self.hooks, verbose)
        self.importer = RModuleImporter(self.loader, verbose)

    def set_trusted_path(self):
        # Set the path from which dynamic modules may be loaded.
        # Those dynamic modules must also occur in ok_builtin_modules
        self.trusted_path = filter(os.path.isabs, sys.path)

    def load_dynamic(self, name, filename, file):
        if name not in self.ok_dynamic_modules:
            raise ImportError, "untrusted dynamic module: %s" % name
        if name in sys.modules:
            src = sys.modules[name]
        else:
            src = imp.load_dynamic(name, filename, file)
        dst = self.copy_except(src, [])
        return dst

    def make_initial_modules(self):
        self.make_main()
        self.make_osname()

    # Helpers for RHooks

    def get_suffixes(self):
        return [item   # (suff, mode, type)
                for item in imp.get_suffixes()
                if item[2] in self.ok_file_types]

    def is_builtin(self, mname):
        return mname in self.ok_builtin_modules

    # The make_* methods create specific built-in modules

    def make_builtin(self):
        m = self.copy_except(__builtin__, self.nok_builtin_names)
        m.__import__ = self.r_import
        m.reload = self.r_reload
        m.open = m.file = self.r_open

    def make_main(self):
        m = self.add_module('__main__')

    def make_osname(self):
        osname = os.name
        src = __import__(osname)
        dst = self.copy_only(src, self.ok_posix_names)
        dst.environ = e = {}
        for key, value in os.environ.items():
            e[key] = value

    def make_sys(self):
        m = self.copy_only(sys, self.ok_sys_names)
        m.modules = self.modules
        m.argv = ['RESTRICTED']
        m.path = map(None, self.ok_path)
        m.exc_info = self.r_exc_info
        m = self.modules['sys']
        l = self.modules.keys() + list(self.ok_builtin_modules)
        l.sort()
        m.builtin_module_names = tuple(l)

    # The copy_* methods copy existing modules with some changes

    def copy_except(self, src, exceptions):
        dst = self.copy_none(src)
        for name in dir(src):
            setattr(dst, name, getattr(src, name))
        for name in exceptions:
            try:
                delattr(dst, name)
            except AttributeError:
                pass
        return dst

    def copy_only(self, src, names):
        dst = self.copy_none(src)
        for name in names:
            try:
                value = getattr(src, name)
            except AttributeError:
                continue
            setattr(dst, name, value)
        return dst

    def copy_none(self, src):
        m = self.add_module(src.__name__)
        m.__doc__ = src.__doc__
        return m

    # Add a module -- return an existing module or create one

    def add_module(self, mname):
        m = self.modules.get(mname)
        if m is None:
            self.modules[mname] = m = self.hooks.new_module(mname)
        m.__builtins__ = self.modules['__builtin__']
        return m

    # The r* methods are public interfaces

    def r_exec(self, code):
        """Execute code within a restricted environment.

        The code parameter must either be a string containing one or more
        lines of Python code, or a compiled code object, which will be
        executed in the restricted environment's __main__ module.

        """
        m = self.add_module('__main__')
        exec code in m.__dict__

    def r_eval(self, code):
        """Evaluate code within a restricted environment.

        The code parameter must either be a string containing a Python
        expression, or a compiled code object, which will be evaluated in
        the restricted environment's __main__ module.  The value of the
        expression or code object will be returned.

        """
        m = self.add_module('__main__')
        return eval(code, m.__dict__)

    def r_execfile(self, file):
        """Execute the Python code in the file in the restricted
        environment's __main__ module.

        """
        m = self.add_module('__main__')
        execfile(file, m.__dict__)

    def r_import(self, mname, globals={}, locals={}, fromlist=[]):
        """Import a module, raising an ImportError exception if the module
        is considered unsafe.

        This method is implicitly called by code executing in the
        restricted environment.  Overriding this method in a subclass is
        used to change the policies enforced by a restricted environment.

        """
        return self.importer.import_module(mname, globals, locals, fromlist)

    def r_reload(self, m):
        """Reload the module object, re-parsing and re-initializing it.

        This method is implicitly called by code executing in the
        restricted environment.  Overriding this method in a subclass is
        used to change the policies enforced by a restricted environment.

        """
        return self.importer.reload(m)

    def r_unload(self, m):
        """Unload the module.

        Removes it from the restricted environment's sys.modules dictionary.

        This method is implicitly called by code executing in the
        restricted environment.  Overriding this method in a subclass is
        used to change the policies enforced by a restricted environment.

        """
        return self.importer.unload(m)

    # The s_* methods are similar but also swap std{in,out,err}

    def make_delegate_files(self):
        s = self.modules['sys']
        self.delegate_stdin = FileDelegate(s, 'stdin')
        self.delegate_stdout = FileDelegate(s, 'stdout')
        self.delegate_stderr = FileDelegate(s, 'stderr')
        self.restricted_stdin = FileWrapper(sys.stdin)
        self.restricted_stdout = FileWrapper(sys.stdout)
        self.restricted_stderr = FileWrapper(sys.stderr)

    def set_files(self):
        if not hasattr(self, 'save_stdin'):
            self.save_files()
        if not hasattr(self, 'delegate_stdin'):
            self.make_delegate_files()
        s = self.modules['sys']
        s.stdin = self.restricted_stdin
        s.stdout = self.restricted_stdout
        s.stderr = self.restricted_stderr
        sys.stdin = self.delegate_stdin
        sys.stdout = self.delegate_stdout
        sys.stderr = self.delegate_stderr

    def reset_files(self):
        self.restore_files()
        s = self.modules['sys']
        self.restricted_stdin = s.stdin
        self.restricted_stdout = s.stdout
        self.restricted_stderr = s.stderr


    def save_files(self):
        self.save_stdin = sys.stdin
        self.save_stdout = sys.stdout
        self.save_stderr = sys.stderr

    def restore_files(self):
        sys.stdin = self.save_stdin
        sys.stdout = self.save_stdout
        sys.stderr = self.save_stderr

    def s_apply(self, func, args=(), kw={}):
        self.save_files()
        try:
            self.set_files()
            r = func(*args, **kw)
        finally:
            self.restore_files()
        return r

    def s_exec(self, *args):
        """Execute code within a restricted environment.

        Similar to the r_exec() method, but the code will be granted access
        to restricted versions of the standard I/O streams sys.stdin,
        sys.stderr, and sys.stdout.

        The code parameter must either be a string containing one or more
        lines of Python code, or a compiled code object, which will be
        executed in the restricted environment's __main__ module.

        """
        return self.s_apply(self.r_exec, args)

    def s_eval(self, *args):
        """Evaluate code within a restricted environment.

        Similar to the r_eval() method, but the code will be granted access
        to restricted versions of the standard I/O streams sys.stdin,
        sys.stderr, and sys.stdout.

        The code parameter must either be a string containing a Python
        expression, or a compiled code object, which will be evaluated in
        the restricted environment's __main__ module.  The value of the
        expression or code object will be returned.

        """
        return self.s_apply(self.r_eval, args)

    def s_execfile(self, *args):
        """Execute the Python code in the file in the restricted
        environment's __main__ module.

        Similar to the r_execfile() method, but the code will be granted
        access to restricted versions of the standard I/O streams sys.stdin,
        sys.stderr, and sys.stdout.

        """
        return self.s_apply(self.r_execfile, args)

    def s_import(self, *args):
        """Import a module, raising an ImportError exception if the module
        is considered unsafe.

        This method is implicitly called by code executing in the
        restricted environment.  Overriding this method in a subclass is
        used to change the policies enforced by a restricted environment.

        Similar to the r_import() method, but has access to restricted
        versions of the standard I/O streams sys.stdin, sys.stderr, and
        sys.stdout.

        """
        return self.s_apply(self.r_import, args)

    def s_reload(self, *args):
        """Reload the module object, re-parsing and re-initializing it.

        This method is implicitly called by code executing in the
        restricted environment.  Overriding this method in a subclass is
        used to change the policies enforced by a restricted environment.

        Similar to the r_reload() method, but has access to restricted
        versions of the standard I/O streams sys.stdin, sys.stderr, and
        sys.stdout.

        """
        return self.s_apply(self.r_reload, args)

    def s_unload(self, *args):
        """Unload the module.

        Removes it from the restricted environment's sys.modules dictionary.

        This method is implicitly called by code executing in the
        restricted environment.  Overriding this method in a subclass is
        used to change the policies enforced by a restricted environment.

        Similar to the r_unload() method, but has access to restricted
        versions of the standard I/O streams sys.stdin, sys.stderr, and
        sys.stdout.

        """
        return self.s_apply(self.r_unload, args)

    # Restricted open(...)

    def r_open(self, file, mode='r', buf=-1):
        """Method called when open() is called in the restricted environment.

        The arguments are identical to those of the open() function, and a
        file object (or a class instance compatible with file objects)
        should be returned.  RExec's default behaviour is allow opening
        any file for reading, but forbidding any attempt to write a file.

        This method is implicitly called by code executing in the
        restricted environment.  Overriding this method in a subclass is
        used to change the policies enforced by a restricted environment.

        """
        mode = str(mode)
        if mode not in ('r', 'rb'):
            raise IOError, "can't open files for writing in restricted mode"
        return open(file, mode, buf)

    # Restricted version of sys.exc_info()

    def r_exc_info(self):
        ty, va, tr = sys.exc_info()
        tr = None
        return ty, va, tr


def test():
    import getopt, traceback
    opts, args = getopt.getopt(sys.argv[1:], 'vt:')
    verbose = 0
    trusted = []
    for o, a in opts:
        if o == '-v':
            verbose = verbose+1
        if o == '-t':
            trusted.append(a)
    r = RExec(verbose=verbose)
    if trusted:
        r.ok_builtin_modules = r.ok_builtin_modules + tuple(trusted)
    if args:
        r.modules['sys'].argv = args
        r.modules['sys'].path.insert(0, os.path.dirname(args[0]))
    else:
        r.modules['sys'].path.insert(0, "")
    fp = sys.stdin
    if args and args[0] != '-':
        try:
            fp = open(args[0])
        except IOError, msg:
            print "%s: can't open file %r" % (sys.argv[0], args[0])
            return 1
    if fp.isatty():
        try:
            import readline
        except ImportError:
            pass
        import code
        class RestrictedConsole(code.InteractiveConsole):
            def runcode(self, co):
                self.locals['__builtins__'] = r.modules['__builtin__']
                r.s_apply(code.InteractiveConsole.runcode, (self, co))
        try:
            RestrictedConsole(r.modules['__main__'].__dict__).interact()
        except SystemExit, n:
            return n
    else:
        text = fp.read()
        fp.close()
        c = compile(text, fp.name, 'exec')
        try:
            r.s_exec(c)
        except SystemExit, n:
            return n
        except:
            traceback.print_exc()
            return 1


if __name__ == '__main__':
    sys.exit(test())
