Ejemplo n.º 1
0
    def restart(self):
        # Empty all the buffers
        self.stdin.truncate(0)
        self.stdout.truncate(0)
        self.stderr.truncate(0)

        # TODO: Check if we are already running a console. If we are shut it 
        # down first.

        # TODO: Figure out the host name the console server is running on.
        self.host = socket.gethostname()

        # Create magic
        # TODO
        self.magic = hashlib.md5(uuid.uuid4().bytes).hexdigest()

        # Try to find a free port on the server.
        # Just try some random ports in the range [3000,8000)
        # until we either succeed, or give up. If you think this
        # sounds risky, it isn't:
        # For N ports (e.g. 5000) with k (e.g. 100) in use, the
        # probability of failing to find a free port in t (e.g. 5) tries
        # is (k / N) ** t (e.g. 3.2*10e-9).

        tries = 0
        error = None
        while tries < 5:
            self.port = int(random.uniform(3000, 8000))

            python_console = os.path.join(self.config['paths']['share'],
                        'services/python-console')
            args = [python_console, str(self.port), str(self.magic)]

            try:
                interpret.execute_raw(self.config, self.user, self.jail_path,
                        self.working_dir, "/usr/bin/python", args)
                # success
                break
            except interpret.ExecutionError, e:
                tries += 1
                error = e.message
Ejemplo n.º 2
0
    def serve_file(self, req, owner, jail, path, download=False, files=None):
        """Serves a file, using one of three possibilities: interpreting it,
        serving it directly, or denying it and returning a 403 Forbidden error.
        No return value. Writes to req (possibly throwing an HTTP error).

        req: An IVLE request object.
        owner: The user who owns the file being served.
        jail: The user's jail.
        path: Filename in the jail.
        download:  Should the file be viewed in browser or downloaded
        """

        # We need a no-op trampoline run to ensure that the jail is mounted.
        # Otherwise we won't be able to authorise for public mode!
        noop_object = interpret.interpreter_objects["noop"]
        interpret.interpret_file(req, owner, jail, '', noop_object)

        # Authorize access. If failure, this throws a HTTP_FORBIDDEN error.
        if not self.path_authorize(req):
            raise Unauthorized()

        args = []
        if download:
            args.append('-d')

        if files and download:
            args += [os.path.join(path, f) for f in files]
        else:
            args.append(path)

        (out, err) = interpret.execute_raw(req.config, owner, jail, '/home',
                    os.path.join(req.config['paths']['share'],
                                 'services/serveservice'),
                    args)
        assert not err

        # Remove the JSON from the front of the response, and decode it.
        j = out.split('\n', 1)[0]
        out = out[len(j) + 1:]
        response = json.loads(j)

        if 'error' in response:
            if response['error'] == 'not-found':
                raise NotFound()
            elif response['error'] in ('is-directory', 'forbidden'):
                raise Forbidden()
            elif response['error'] == 'is-executable':
                # We need to execute it. Just run it with Python in the jail.
                interp_object = interpret.interpreter_objects["cgi-python"]
                interpret.interpret_file(req, owner, jail, response['path'],
                                         interp_object, gentle=True)
                return
            else:
                raise AssertionError('Unknown error from serveservice: %s' %
                                     response['error'])

        if download:
            req.headers_out["Content-Disposition"] = (
                         "attachment; filename=%s" %
                             response['name'].encode('utf-8'))
        req.content_type = response['type'].encode('utf-8')
        req.content_length = response.get('size')
        req.write(out)