1 """Restricted execution facilities.
3 The class RExec exports methods r_exec(), r_eval(), r_execfile(), and
4 r_import(), which correspond roughly to the built-in operations
5 exec, eval(), execfile() and import, but executing the code in an
6 environment that only exposes those built-in operations that are
7 deemed safe. To this end, a modest collection of 'fake' modules is
8 created which mimics the standard modules by the same names. It is a
9 policy decision which built-in modules and operations are made
10 available; this module provides a reasonable default, but derived
11 classes can change the policies e.g. by overriding or extending class
12 variables like ok_builtin_modules or methods like make_sys().
15 - r_open should allow writing tmp dir
16 - r_exec etc. with explicit globals/locals? (Use rexec("exec ... in ...")?)
30 ok_file_methods = (
'fileno',
'flush',
'isatty',
'read',
'readline',
31 'readlines',
'seek',
'tell',
'write',
'writelines')
41 if not hasattr(self, m)
and hasattr(f, m):
42 setattr(self, m, getattr(f, m))
50 return apply(getattr(self.mod, self.name).%s, args)
59 for m
in FileBase.ok_file_methods + (
'close',):
60 exec TEMPLATE % (m, m)
71 if args
and type(args[-1]) == type(0):
74 if args
and hasattr(args[0],
'__class__'):
78 raise TypeError,
"too many arguments"
87 return self.rexec.is_builtin(name)
91 return self.rexec.copy_except(m, ())
93 def init_frozen(self, name):
raise SystemError,
"don't use this"
94 def load_source(self, *args):
raise SystemError,
"don't use this"
99 return self.rexec.load_dynamic(name, filename, file)
102 return self.rexec.add_module(name)
105 return self.rexec.modules
108 return self.rexec.modules[
'sys'].path
118 """Restricted Execution environment."""
122 ok_builtin_modules = (
'audioop',
'array',
'binascii',
123 'cmath',
'errno',
'imageop',
124 'marshal',
'math',
'md5',
'operator',
125 'parser',
'regex',
'pcre',
'rotor',
'select',
126 'sha',
'_sre',
'strop',
'struct',
'time')
128 ok_posix_names = (
'error',
'fstat',
'listdir',
'lstat',
'readlink',
129 'stat',
'times',
'uname',
'getpid',
'getppid',
130 'getcwd',
'getuid',
'getgid',
'geteuid',
'getegid')
132 ok_sys_names = (
'ps1',
'ps2',
'copyright',
'version',
133 'platform',
'exit',
'maxint')
135 nok_builtin_names = (
'open',
'file',
'reload',
'__import__')
141 self.hooks.set_rexec(self)
146 if mname
in sys.builtin_module_names:
165 raise ImportError,
"untrusted dynamic module: %s" % name
166 if sys.modules.has_key(name):
167 src = sys.modules[name]
170 src = imp.load_dynamic(name, filename, file)
189 m.open = m.file = self.
r_open
196 src = __import__(osname)
199 for key, value
in os.environ.items():
205 m.argv = [
'RESTRICTED']
206 m.path = map(
None, self.
ok_path)
211 m.builtin_module_names =
tuple(l)
217 for name
in dir(src):
218 setattr(dst, name, getattr(src, name))
219 for name
in exceptions:
222 except AttributeError:
230 value = getattr(src, name)
231 except AttributeError:
233 setattr(dst, name, value)
238 m.__doc__ = src.__doc__
244 if self.modules.has_key(mname):
246 self.
modules[mname] = m = self.hooks.new_module(mname)
247 m.__builtins__ = self.
modules[
'__builtin__']
254 exec code
in m.__dict__
258 return eval(code, m.__dict__)
262 execfile(file, m.__dict__)
264 def r_import(self, mname, globals={}, locals={}, fromlist=[]):
265 return self.importer.import_module(mname, globals, locals, fromlist)
268 return self.importer.reload(m)
271 return self.importer.unload(m)
285 if not hasattr(self,
'save_stdin'):
287 if not hasattr(self,
'delegate_stdin'):
320 r = apply(func, args, kw)
322 r = apply(func, args)
347 def r_open(self, file, mode='r', buf=-1):
348 if mode
not in (
'r', 'rb'):
349 raise IOError,
"can't open files for writing in restricted mode"
350 return open(file, mode, buf)
355 ty, va, tr = sys.exc_info()
361 import getopt, traceback
370 r =
RExec(verbose=verbose)
372 r.ok_builtin_modules = r.ok_builtin_modules +
tuple(trusted)
374 r.modules[
'sys'].argv = args
375 r.modules[
'sys'].path.insert(0, os.path.dirname(args[0]))
377 r.modules[
'sys'].path.insert(0,
"")
379 if args
and args[0] !=
'-':
383 print "%s: can't open file %s" % (sys.argv[0], `args[0]`)
386 print "*** RESTRICTED *** Python", sys.version
387 print 'Type "help", "copyright", "credits" or "license" ' \
388 'for more information.'
393 s = raw_input(
'>>> ')
397 if s
and s[0] !=
'#':
399 c =
compile(s,
'<stdin>',
'single')
401 except SystemExit, n:
408 c =
compile(text, fp.name,
'exec')
411 except SystemExit, n:
418 if __name__ ==
'__main__':