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

« back to all changes in this revision

Viewing changes to ivle/interpret.py

  • Committer: William Grant
  • Date: 2009-01-20 00:37:29 UTC
  • mto: This revision was merged to the branch mainline in revision 1090.
  • Revision ID: grantw@unimelb.edu.au-20090120003729-cjplw80wuit76mn6
userdb: login.state now defaults to 'no_agreement'.
        The migration is 20090120-01.

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
25
26
from ivle.util import IVLEError, IVLEJailError
26
27
import ivle.conf
27
28
 
134
135
        del os.environ[k]
135
136
    for (k,v) in req.get_cgi_environ().items():
136
137
        os.environ[k] = v
137
 
    fixup_environ(req, script_path)
 
138
    fixup_environ(req)
138
139
 
139
140
    # usage: tramp uid jail_dir working_dir script_path
140
141
    pid = subprocess.Popen(
141
 
        [trampoline, str(uid), ivle.conf.jail_base, ivle.conf.jail_src_base,
142
 
         ivle.conf.jail_system, jail_dir, working_dir, interpreter,
 
142
        [trampoline, str(uid), 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, script_path):
 
362
def fixup_environ(req):
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
 
388
397
    # CGI specifies that REMOTE_HOST SHOULD be set, and MAY just be set to
389
398
    # REMOTE_ADDR. Since Apache does not appear to set this, set it to
390
399
    # REMOTE_ADDR.
391
400
    if 'REMOTE_HOST' not in env and 'REMOTE_ADDR' in env:
392
401
        env['REMOTE_HOST'] = env['REMOTE_ADDR']
393
402
 
394
 
    env['PATH_INFO'] = ''
395
 
    del env['PATH_TRANSLATED']
396
 
 
397
 
    normuri = os.path.normpath(req.uri)
398
 
    env['SCRIPT_NAME'] = normuri
399
 
 
400
403
    # SCRIPT_NAME is the path to the script WITHOUT PATH_INFO.
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'])]
 
404
    script_name = req.uri
 
405
    env['SCRIPT_NAME'] = script_name
413
406
 
414
407
    # SERVER_SOFTWARE is actually not Apache but IVLE, since we are
415
408
    # custom-making the CGI request.
418
411
    # Additional environment variables
419
412
    username = studpath.url_to_jailpaths(req.path)[0]
420
413
    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
 
 
443
 
    (stdout, stderr) = proc.communicate()
444
 
    exitcode = proc.returncode
445
 
 
446
 
    if exitcode != 0:
447
 
        raise ExecutionError('subprocess ended with code %d, stderr %s' %
448
 
                             (exitcode, proc.stderr.read()))
449
 
    return (stdout, stderr)