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
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)