summaryrefslogtreecommitdiff
path: root/python_server.py
diff options
context:
space:
mode:
authorPrabhu Ramachandran2011-11-12 10:02:57 +0530
committerPrabhu Ramachandran2011-11-12 10:02:57 +0530
commitfb31dcc7693395c9856fb19c3e867fbfa2e9b4f8 (patch)
tree24b50d4bce7ac5faa5ec6ae98db041766340814b /python_server.py
parentc69bc272c1c3ba02c3f244586b65254036e73de3 (diff)
downloadonline_test-fb31dcc7693395c9856fb19c3e867fbfa2e9b4f8.tar.gz
online_test-fb31dcc7693395c9856fb19c3e867fbfa2e9b4f8.tar.bz2
online_test-fb31dcc7693395c9856fb19c3e867fbfa2e9b4f8.zip
ENH: Running remote code safely via XMLRPC.
Adding a python_server which executes code as nobody safely so users cannot do too much damage.
Diffstat (limited to 'python_server.py')
-rwxr-xr-xpython_server.py65
1 files changed, 65 insertions, 0 deletions
diff --git a/python_server.py b/python_server.py
new file mode 100755
index 0000000..debd73d
--- /dev/null
+++ b/python_server.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python
+"""This server runs an XMLRPC server that can be submitted code and tests
+and returns the output. It *should* be run as root and will run as the user
+'nobody' so as to minimize any damange by errant code.
+"""
+import sys
+from SimpleXMLRPCServer import SimpleXMLRPCServer
+import pwd
+import os
+
+
+# Set the effective uid
+nobody = pwd.getpwnam('nobody')
+os.seteuid(nobody.pw_uid)
+
+
+def run_code(answer, test_code, in_dir=None):
+ """Tests given Python function (`answer`) with the `test_code` supplied.
+ If the optional `in_dir` keyword argument is supplied it changes the
+ directory to that directory (it does not change it back to the original when
+ done).
+
+ Returns
+ -------
+
+ A tuple: (success, error message).
+
+ """
+ if in_dir is not None:
+ os.chdir(in_dir)
+
+ success = False
+ tb = None
+ try:
+ submitted = compile(answer, '<string>', mode='exec')
+ g = {}
+ exec submitted in g
+ _tests = compile(test_code, '<string>', mode='exec')
+ exec _tests in g
+ except AssertionError:
+ type, value, tb = sys.exc_info()
+ info = traceback.extract_tb(tb)
+ fname, lineno, func, text = info[-1]
+ text = str(test_code).splitlines()[lineno-1]
+ err = "{0} {1} in: {2}".format(type.__name__, str(value), text)
+ except:
+ type, value = sys.exc_info()[:2]
+ err = "Error: {0}".format(repr(value))
+ else:
+ success = True
+ err = 'Correct answer'
+ finally:
+ del tb
+
+ return success, err
+
+
+def main():
+ server = SimpleXMLRPCServer(("localhost", 8001))
+ server.register_function(run_code)
+ server.serve_forever()
+
+if __name__ == '__main__':
+ main()
+ \ No newline at end of file