def url_to_jailpaths(config, urlpath): """Given a URL path (part of a URL query string), returns a tuple of * the username of the student whose directory is being browsed * the absolute path where the jail will be located. * the path of the file relative to the jail. urlpath: See urlpath in url_to_local. >>> stubconfig = {'paths': {'jails': {'mounts': '/jails'}}} >>> url_to_jailpaths(stubconfig, "joe/mydir//myfile/.././myfile") ('joe', '/jails/joe', '/home/joe/mydir/myfile') >>> url_to_jailpaths(stubconfig, "") (None, None, None) >>> url_to_jailpaths(stubconfig, "../foo") (None, None, None) >>> url_to_jailpaths(stubconfig, "/foo") (None, None, None) """ # First normalise the path urlpath = os.path.normpath(urlpath) # Now if it begins with "..", or is absolute, then it's illegal if urlpath.startswith("..") or os.path.isabs(urlpath): return (None, None, None) # Note: User can be a group name. There is absolutely no difference in our # current directory scheme. (user, subpath) = util.split_path(urlpath) if user is None: return (None, None, None) jail = os.path.join(config['paths']['jails']['mounts'], user) path = to_home_path(urlpath) return (user, jail, path)
def url_to_local(config, urlpath): """Given a URL path (part of a URL query string, see below), returns a tuple of * the username of the student whose directory is being browsed * the absolute path in the file system where that file will be found within the student directories. urlpath: Part of the URL, but only the part *after* the application. For instance, given the URL "/ivle/browse/joe/mydir/myfile", urlpath will be just "joe/mydir/myfile". The expected result is something like ("joe", "/home/informatics/jails/joe/home/joe/mydir/myfile"). Note that the actual location is not guaranteed by this interface (this function serves as a single point of control as to how URLs map onto student directories). Returns (None, None) if the path is empty. >>> stubconfig = {'paths': {'jails': {'mounts': '/jails'}}} >>> url_to_local(stubconfig, 'joe/foo/bar/baz') ('joe', '/jails/joe/home/joe/foo/bar/baz') >>> url_to_local(stubconfig, 'joe') ('joe', '/jails/joe/home/joe') >>> url_to_local(stubconfig, 'joe/') ('joe', '/jails/joe/home/joe') We have some protection from various potential attacks. An empty, absolute, or ..-prefixed path yields a special result. >>> url_to_local(stubconfig, '') (None, None) >>> url_to_local(stubconfig, '/foo') (None, None) >>> url_to_local(stubconfig, '../bar') (None, None) """ # First normalise the path urlpath = os.path.normpath(urlpath) # Now if it begins with ".." or separator, then it's illegal if urlpath.startswith("..") or urlpath.startswith(os.sep): return (None, None) # Note: User can be a group name. There is absolutely no difference in our # current directory scheme. (user, subpath) = util.split_path(urlpath) if user is None: return (None, None) # Join the user onto 'home' then the full path specified. # This results in the user's name being repeated twice, which is in # accordance with our directory scheme. # (The first time is the name of the jail, the second is the user's home # directory within the jail). path = os.path.join(config['paths']['jails']['mounts'], user, 'home', urlpath) return (user, path)
def authorize(req, user): """Given a request, checks whether req.user is allowed to access req.path. Returns None on authorization success. Raises HTTP_FORBIDDEN on failure. This is for general authorization (assuming not in public mode; this is the standard auth code for fileservice, download and serve). """ # TODO: Groups # First normalise the path urlpath = os.path.normpath(req.path) # Now if it begins with ".." or separator, then it's illegal if urlpath.startswith("..") or urlpath.startswith(os.sep): return False (owner, _) = util.split_path(urlpath) if user.login != owner: return False return True