~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to ivle/interpret.py

  • Committer: William Grant
  • Date: 2009-02-24 13:29:44 UTC
  • Revision ID: grantw@unimelb.edu.au-20090224132944-lm29zd1li1rjg77p
Privileges (apart from admin) are now offering-local, not global.

Offering privileges are granted by Enrolment.role, and global admin
by User.admin. ivle.caps is dead.

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
# Runs a student script in a safe execution environment.
23
23
 
24
24
from ivle import studpath
25
 
from ivle import db
26
25
from ivle.util import IVLEError, IVLEJailError
27
26
import ivle.conf
28
27
 
135
134
        del os.environ[k]
136
135
    for (k,v) in req.get_cgi_environ().items():
137
136
        os.environ[k] = v
138
 
    fixup_environ(req)
 
137
    fixup_environ(req, script_path)
139
138
 
140
139
    # usage: tramp uid jail_dir working_dir script_path
141
140
    pid = subprocess.Popen(
142
 
        [trampoline, str(uid), jail_dir, working_dir, interpreter,
 
141
        [trampoline, str(uid), ivle.conf.jail_base, ivle.conf.jail_src_base,
 
142
         ivle.conf.jail_system, jail_dir, working_dir, interpreter,
143
143
        script_path],
144
144
        stdin=f, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
145
145
        cwd=tramp_dir)
359
359
    # python-server-page
360
360
}
361
361
 
362
 
def fixup_environ(req):
 
362
def fixup_environ(req, script_path):
363
363
    """Assuming os.environ has been written with the CGI variables from
364
364
    apache, make a few changes for security and correctness.
365
365
 
385
385
        del env['PATH']
386
386
    except: pass
387
387
 
388
 
    # Remove SCRIPT_FILENAME. Not part of CGI spec (see SCRIPT_NAME).
389
 
 
390
 
    # PATH_INFO is wrong because the script doesn't physically exist.
391
 
    # Apache makes it relative to the "serve" app. It should actually be made
392
 
    # relative to the student's script. intepretservice does that in the jail,
393
 
    # so here we just clear it.
394
 
    env['PATH_INFO'] = ''
395
 
    env['PATH_TRANSLATED'] = ''
396
 
 
397
388
    # CGI specifies that REMOTE_HOST SHOULD be set, and MAY just be set to
398
389
    # REMOTE_ADDR. Since Apache does not appear to set this, set it to
399
390
    # REMOTE_ADDR.
400
391
    if 'REMOTE_HOST' not in env and 'REMOTE_ADDR' in env:
401
392
        env['REMOTE_HOST'] = env['REMOTE_ADDR']
402
393
 
 
394
    env['PATH_INFO'] = ''
 
395
    del env['PATH_TRANSLATED']
 
396
 
 
397
    normuri = os.path.normpath(req.uri)
 
398
    env['SCRIPT_NAME'] = normuri
 
399
 
403
400
    # SCRIPT_NAME is the path to the script WITHOUT PATH_INFO.
404
 
    script_name = req.uri
405
 
    env['SCRIPT_NAME'] = script_name
 
401
    # We don't care about these if the script is null (ie. noop).
 
402
    # XXX: We check for /home because we don't want to interfere with
 
403
    # CGIRequest, which fileservice still uses.
 
404
    if script_path and script_path.startswith('/home'):
 
405
        normscript = os.path.normpath(script_path)
 
406
 
 
407
        uri_into_jail = studpath.url_to_jailpaths(os.path.normpath(req.path))[2]
 
408
 
 
409
        # PATH_INFO is wrong because the script doesn't physically exist.
 
410
        env['PATH_INFO'] = uri_into_jail[len(normscript):]
 
411
        if len(env['PATH_INFO']) > 0:
 
412
            env['SCRIPT_NAME'] = normuri[:-len(env['PATH_INFO'])]
406
413
 
407
414
    # SERVER_SOFTWARE is actually not Apache but IVLE, since we are
408
415
    # custom-making the CGI request.
411
418
    # Additional environment variables
412
419
    username = studpath.url_to_jailpaths(req.path)[0]
413
420
    env['HOME'] = os.path.join('/home', username)
 
421
 
 
422
class ExecutionError(Exception):
 
423
    pass
 
424
 
 
425
def execute_raw(user, jail_dir, working_dir, binary, args):
 
426
    '''Execute a binary in a user's jail, returning the raw output.
 
427
 
 
428
    The binary is executed in the given working directory with the given
 
429
    args. A tuple of (stdout, stderr) is returned.
 
430
    '''
 
431
 
 
432
    tramp = location_cgi_python
 
433
    tramp_dir = os.path.split(location_cgi_python)[0]
 
434
 
 
435
    # Fire up trampoline. Vroom, vroom.
 
436
    proc = subprocess.Popen(
 
437
        [tramp, str(user.unixid), ivle.conf.jail_base,
 
438
         ivle.conf.jail_src_base, ivle.conf.jail_system, jail_dir,
 
439
         working_dir, binary] + args,
 
440
        stdin=subprocess.PIPE, stdout=subprocess.PIPE,
 
441
        stderr=subprocess.PIPE, cwd=tramp_dir, close_fds=True)
 
442
    exitcode = proc.wait()
 
443
 
 
444
    if exitcode != 0:
 
445
        raise ExecutionError('subprocess ended with code %d, stderr %s' %
 
446
                             (exitcode, proc.stderr.read()))
 
447
    return (proc.stdout.read(), proc.stderr.read())