def get(self, path): if Check_state_cookie and GTSocket.get_auth_code(): state_cookie = self.get_cookie(COOKIE_NAME) or self.get_argument("state_cookie", "") if not GTSocket.get_state(state_cookie): raise tornado.web.HTTPError(403, "Invalid cookie to access %s", path) host, sep, self.file_path = path.partition("/") if not host or not self.file_path: raise tornado.web.HTTPError(403, "Null host/filename") if_mod_since_datetime = None if_mod_since = self.request.headers.get("If-Modified-Since") if if_mod_since: if_mod_since_datetime = gtermhost.str2datetime(if_mod_since) self.cached_copy = None last_modified = None last_modified_datetime = None btime, bheaders, bcontent = Proxy_cache.get_blob(self.request.path) if bheaders: # Path in cache last_modified = dict(bheaders).get("Last-Modified") if last_modified: last_modified_datetime = gtermhost.str2datetime(last_modified) if self.request.path.startswith("/blob/"): if last_modified_datetime and \ if_mod_since_datetime and \ if_mod_since_datetime >= last_modified_datetime: # Remote copy is up-to-date self.send_error(304) # Not modified status code return # Return immutable cached blob self.finish_write(bheaders, bcontent) return if self.request.path.startswith("/file/"): # Check if access to file is permitted self.file_path = "/" + self.file_path normalized_host = gtermhost.get_normalized_host(host) host_secret = TerminalConnection.host_secrets.get(normalized_host) if not host_secret: raise tornado.web.HTTPError(403, "Unauthorized access to %s", path) shared_secret = self.get_cookie("GRAPHTERM_HOST_"+normalized_host) if shared_secret: if host_secret != shared_secret: raise tornado.web.HTTPError(403, "Unauthorized access to %s", path) else: shared_secret = self.get_argument("shared_secret", "") check_host = gtermhost.get_normalized_host(self.get_argument("host", "")) expect_secret = TerminalConnection.host_secrets.get(check_host) if not expect_secret or expect_secret != shared_secret: raise tornado.web.HTTPError(403, "Unauthorized access to %s", path) fpath_hmac = hmac.new(str(host_secret), self.file_path, digestmod=hashlib.sha256).hexdigest()[:HEX_DIGITS] if fpath_hmac != self.get_argument("hmac", ""): raise tornado.web.HTTPError(403, "Unauthorized access to %s", path) if bheaders: # File copy is cached if last_modified_datetime and \ if_mod_since_datetime and \ if_mod_since_datetime < last_modified_datetime: # Remote copy older than cached copy; change if_mod_since to cache copy time self.cached_copy = (btime, bheaders, bcontent) if_mod_since = last_modified self.async_id = self.get_async_id() self._async_requests[self.async_id] = self self.timeout_callback = IO_loop.add_timeout(time.time()+REQUEST_TIMEOUT, functools.partial(self.complete_request, self.async_id)) TerminalConnection.send_to_connection(host, "request", "", [["file_request", self.async_id, self.request.method, self.file_path, if_mod_since]])
def open(self): need_code = bool(self._auth_code) need_user = need_code ##bool(self._auth_users) user = "" try: if not self._auth_code: self.authorized = {"user": "", "auth_type": "null_auth", "time": time.time(), "state_id": ""} elif COOKIE_NAME in self.request.cookies: state_value = self.get_state(self.request.cookies[COOKIE_NAME].value) if state_value: self.authorized = state_value webcast_auth = False if not self.authorized: query_data = {} if self.request_query: try: query_data = urlparse.parse_qs(self.request_query) except Exception: pass user = query_data.get("user", [""])[0] code = query_data.get("code", [""])[0] expect_code = self._auth_code if self._auth_users: if user in self._auth_users: expect_code = self._auth_users[user] else: self.write_json([["authenticate", need_user, need_code, "Invalid user" if user else ""]]) self.close() return if code == self._auth_code or code == expect_code: state_id = uuid.uuid4().hex[:HEX_DIGITS] self.authorized = {"user": user, "auth_type": "code_auth", "time": time.time(), "state_id": state_id} if len(self._cookie_states) >= MAX_COOKIE_STATES: self._cookie_states.pop(last=False) self._cookie_states[state_id] = self.authorized elif self.req_path in self._webcast_paths: self.authorized = {"user": user, "auth_type": "webcast_auth", "time": time.time(), "state_id": ""} webcast_auth = True if not self.authorized: self.write_json([["authenticate", need_user, need_code, "Authentication failed; retry"]]) self.close() return comps = self.req_path.split("/") if len(comps) < 1 or not comps[0]: host_list = TerminalConnection.get_connection_ids() if self._auth_users and self.authorized["user"] not in SUPER_USERS: if LOCAL_HOST in host_list: host_list.remove(LOCAL_HOST) host_list.sort() self.write_json([["host_list", self.authorized["state_id"], host_list]]) self.close() return host = comps[0].lower() if not host or not gtermhost.HOST_RE.match(host): self.write_json([["abort", "Invalid characters in host name"]]) self.close() return if host == LOCAL_HOST and self._auth_users and self.authorized["user"] not in SUPER_USERS: self.write_json([["abort", "Local host access not allowed for user %s" % self.authorized["user"]]]) self.close() return wildhost = "?" in host or "*" in host or "[" in host term_feedback = False if wildhost: if len(comps) < 2 or not comps[1] or comps[1].lower() == "new": self.write_json([["abort", "Must specify terminal name for wildcard host"]]) self.close() return term_name = comps[1].lower() else: conn = TerminalConnection.get_connection(host) if not conn: self.write_json([["abort", "Invalid host"]]) self.close() return if len(comps) < 2 or not comps[1]: term_list = list(conn.term_set) term_list.sort() self.write_json([["term_list", self.authorized["state_id"], host, term_list]]) self.close() return term_name = comps[1].lower() if term_name == "new": term_name = conn.remote_terminal_update() self.write_json([["redirect", "/"+host+"/"+term_name]]) self.close() if not gtermhost.SESSION_RE.match(term_name): self.write_json([["abort", "Invalid characters in terminal name"]]) self.close() return term_feedback = term_name in conn.allow_feedback path = host + "/" + term_name option = comps[2] if len(comps) > 2 else "" if option == "kill" and not webcast_auth and not wildhost: kill_remote(path) return self.oshell = (term_name == gtermhost.OSHELL_NAME) self._counter[0] += 1 self.websocket_id = str(self._counter[0]) if "?" in path or "*" in path or "[" in path: self.wildcard = re.compile("^"+path.replace("+", "\\+").replace(".", "\\.").replace("?", ".?").replace("*", ".*")+"$") self._wildcards[path] = (self.wildcard, self.websocket_id) self._watch_set[path].add(self.websocket_id) if webcast_auth: self.controller = False elif self.wildcard: self.controller = True elif option == "share": self.controller = True self._control_set[path].add(self.websocket_id) elif option == "steal": msg = ["update", "controller", False] for ws_id in self._control_set[path]: ws = GTSocket._all_websockets.get(ws_id) if ws and ws_id != self.websocket_id: ws.write_json([msg]) self.controller = True self._control_set[path] = set([self.websocket_id]) elif option == "watch" or (path in self._control_set and self._control_set[path]): self.controller = False else: self.controller = True self._control_set[path] = set([self.websocket_id]) self.remote_path = path self._all_websockets[self.websocket_id] = self if user: self._all_users[user][self.websocket_id] = self display_splash = self.controller and self._counter[0] <= 2 normalized_host, host_secret = "", "" if not self.wildcard: TerminalConnection.send_to_connection(host, "request", term_name, [["reconnect", self.websocket_id]]) normalized_host = gtermhost.get_normalized_host(host) if self.authorized["auth_type"] in ("null_auth", "code_auth"): host_secret = TerminalConnection.host_secrets.get(normalized_host) self.write_json([["setup", {"host": host, "term": term_name, "oshell": self.oshell, "host_secret": host_secret, "normalized_host": normalized_host, "about_version": about.version, "about_authors": about.authors, "about_url": about.url, "about_description": about.description, "controller": self.controller, "wildcard": bool(self.wildcard), "display_splash": display_splash, "apps_url": APPS_URL, "feedback": term_feedback, "state_id": self.authorized["state_id"]}]]) except Exception, excp: logging.warning("GTSocket.open: ERROR %s", excp) self.close()