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

« back to all changes in this revision

Viewing changes to scripts/interpretservice

  • Committer: wagrant
  • Date: 2008-12-23 01:58:44 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:1063
Set PATH_INFO and PATH_TRANSLATED properly for student CGI scripts.

If the requested path doesn't exist, interpretservice now traverses up the
directory tree until it finds a prefix of the path that does exist. If we are
allowed to execute that path, we do so, giving it the trimmed bits in
PATH_INFO. If execution is not permissible, we 404 anyway.

Fixes [ 2094777 ] Serve: Allow path after CGI script

Show diffs side-by-side

added added

removed removed

Lines of Context:
36
36
 
37
37
serveservice_path = "/opt/ivle/scripts/serveservice"
38
38
 
 
39
def determine_file_type(filename):
 
40
    filetype = mimetypes.guess_type(filename)[0]
 
41
    if filetype is None:
 
42
         filetype = conf.mimetypes.default_mimetype
 
43
    return filetype
 
44
 
39
45
req = cgirequest.CGIRequest()
40
46
req.install_error_handler()
41
47
 
 
48
python = "/usr/bin/python"
 
49
 
42
50
# Work out the parts of the URL
43
 
url = urlparse.urlparse(req.path)
44
 
querystr = url[4]
45
 
urlpath = url[2]
46
 
username, _, filename = studpath.url_to_jailpaths(urlpath)
 
51
urlpath = urlparse.urlparse(req.path)[2]
 
52
filename = studpath.url_to_jailpaths(urlpath)[2]
 
53
path_info = ''
 
54
 
 
55
if filename is None:
 
56
    req.throw_error(req.HTTP_NOT_FOUND, "The path specified is invalid.")
 
57
 
 
58
if not os.access(filename, os.F_OK):
 
59
    # The given path doesn't exist. CGI lets us backtrack and put the path
 
60
    # elements through which we pass into PATH_INFO, so we try that.
 
61
    while not os.access(filename, os.F_OK):
 
62
        filename, path_info_frag = os.path.split(filename)
 
63
 
 
64
        # os.path.join tacks a / on the end even if the second fragment is
 
65
        # empty, which we don't want.
 
66
        if len(path_info) > 0:
 
67
            path_info = os.path.join(path_info_frag, path_info)
 
68
        else:
 
69
            path_info = path_info_frag
 
70
 
 
71
    # PATH_INFO is meant to start with a /.
 
72
    path_info = os.path.join(os.sep, path_info)
 
73
 
 
74
    # We now have a file that exists, but is it something that we're allowed
 
75
    # to execute? If not, we should 404 anyway.
 
76
    if determine_file_type(filename) not in conf.app.server.interpreters:
 
77
        req.throw_error(req.HTTP_NOT_FOUND,
 
78
            "The specified file (%s) does not exist." % urlpath)
 
79
 
47
80
path = os.path.split(filename)[0]
48
81
 
49
 
python = "/usr/bin/python"
50
 
 
51
82
# Everything should be done from the same directory as the script
52
 
# If we can't chdir, a 404 will be thrown later when we can't access the file.
53
83
try:
54
84
    os.chdir(path)
55
85
except OSError:
56
 
    pass
 
86
    req.throw_error(req.HTTP_NOT_FOUND,
 
87
        "The specified file (%s) does not exist." % urlpath)
57
88
 
58
89
# Search the path for modules first
59
90
sys.path[0] = path
60
91
 
61
 
(type, _) = mimetypes.guess_type(filename)
62
 
if type is None:
63
 
    type = conf.mimetypes.default_mimetype
64
 
 
65
 
if filename is None:
66
 
    req.throw_error(req.HTTP_NOT_FOUND, "The path specified is invalid.")
67
 
elif not os.access(filename, os.R_OK):
 
92
# Now we have lots of fun mangling environment variables to fix PATH_INFO
 
93
# and related stuff.
 
94
os.environ['PATH_INFO'] = path_info
 
95
if len(path_info) > 0:
 
96
    os.environ['SCRIPT_NAME'] = os.environ['SCRIPT_NAME'][:-len(path_info)]
 
97
 
 
98
# Set PATH_TRANSLATED. We trim the leading / from path_info or things go bad.
 
99
path_translated = studpath.url_to_jailpaths(path_info[1:])[2]
 
100
if path_translated is not None:
 
101
    if len(path_translated) == 0 or path_translated[0] != os.sep:
 
102
        path_translated = os.sep + path_translated
 
103
    os.environ['PATH_TRANSLATED'] = path_translated
 
104
 
 
105
if not os.access(filename, os.R_OK):
68
106
    req.throw_error(req.HTTP_NOT_FOUND,
69
107
        "The specified file (%s) does not exist." % urlpath)
70
108
elif os.path.isdir(filename):
73
111
    # the world at large. Directory contents are private).
74
112
    req.throw_error(req.HTTP_FORBIDDEN,
75
113
        "The path specified is a directory.")
76
 
elif type in conf.app.server.interpreters:
 
114
elif determine_file_type(filename) in conf.app.server.interpreters:
77
115
    # We'll save on a fork and execute in this python process
78
116
    # Let exceptions blow up normally again
79
117
    sys.excepthook = sys.__excepthook__
84
122
    # Otherwise, use the blacklist/whitelist to see if this file should be
85
123
    # served or disallowed
86
124
    if (conf.app.server.blacklist_served_filetypes and \
87
 
            type in conf.app.server.served_filetypes_blacklist) or \
 
125
            determine_file_type(filename) in \
 
126
            conf.app.server.served_filetypes_blacklist) or \
88
127
        (conf.app.server.served_filetypes_whitelist and \
89
 
            type not in conf.app.server.served_filetypes_whitelist):
 
128
            determine_file_type(filename) not in \
 
129
            conf.app.server.served_filetypes_whitelist):
90
130
        req.throw_error(req.HTTP_FORBIDDEN,
91
131
            "Files of this type are not allowed to be served.")
92
132