def handle_ticket(self): if "service" in self.jdata: if "name" in self.jdata: #Note the is_server part, if the request comes from one its own servers. if (self.jdata["name"] in names or is_server(self.jdata["name"])) and self.jdata["service"] in services: session_key = generate_session_key() #Cache the users ip address and session key. users[str(self.client_address[0])] = (session_key) ticket = [session_key] #Randomly choose a server for the request service server_id = random.choice(services[self.jdata["service"]]) server_key = server_id[2] server_id = (server_id[0], server_id[1]) ticket = secure.encrypt_with_key(json.dumps(ticket), server_key) jsonresult = { "ticket": ticket, "session": session_key, "server_id": server_id } #if a known client if(self.jdata["name"] in names): data = secure.encrypt_with_key(json.dumps(jsonresult), names[self.jdata["name"]]) else: #we have already checked that its a valid server. #Just need to extract its password from the config file. pwd = extract_password_from_server(self.jdata["name"]) data = secure.encrypt_with_key(json.dumps(jsonresult), pwd) self.request.send(data) return self.request.send("[]")
def handle(self): self.data = self.request.recv(1024).strip() self.jdata = json.loads(self.data) #Ping check if "type" in self.jdata: if self.jdata["type"] == "ping": self.request.send("[]") return ticket = json.loads(secure.decrypt_with_key(self.jdata["ticket"], password)) message = secure.decrypt_with_key(self.jdata["message"], ticket[0]).strip() #Note that there are all the file server which service that file #being returned, this allows the client to keep trying them until it finds #one which is live. It also allows the file server to push changes to each of the fileserver #when a change is detected. self.directory_data = dir_lookup(message) #Some weird list comprehensions, too much haskell on the brain. server_id = [ [host, port, file_name] for host, port, file_name, pwd in self.directory_data ] server_tickets = [ pwd for _,_,_,pwd in self.directory_data ] encrypted_ticket = [ secure.encrypt_with_key(json.dumps([ticket[0]]), pwd) for pwd in server_tickets ] client_msg = json.dumps(server_id) data = { "ticket":encrypted_ticket, "message":client_msg } #Encrypt response with session key self.request.send(secure.encrypt_with_key(json.dumps(data), ticket[0]))
def handle_open(self, message, session_key): data = {"payload": ""} newfile = False try: file_name = message["message"] print "Received open request from {0}.".format(file_name) f = open(file_name, "rb") except IOError: # Equivalent of touching a file print "{0} doesn't exist".format(file_name) if not os.path.exists(os.path.dirname(file_name)): os.makedirs(os.path.dirname(file_name)) open(file_name, "w").close() f = open(file_name, "rb") newfile = True except ValueError: print "No Message object on json message" data["error"] = "no message type" except OSError as e: print e data["error"] = "io" finally: b64_text = base64.b64encode(f.read()) data["payload"] = b64_text f.close() data["type"] = "read" self.request.send(secure.encrypt_with_key(json.dumps(data), session_key)) if newfile and "relative" in message: self.replicate_changes(message["relative"], "")
def close(self): file.close(self) if not self._mode == "r": command = "diff {0} {1} | tee {2} ".format(hidden_file_path(self.path), self.path, self.path + ".diff") r = os.popen(command) server_id, ticket, self.session = self.get_tickets() diff_contents = r.read() data = { "ticket": ticket, "request": { "type": "write", "message": os.path.join(server_id[2], self.rpath), "relative": self.rpath, "payload": base64.b64encode(diff_contents), }, } data["request"] = secure.encrypt_with_key(json.dumps(data["request"]), self.session) result = lookup_fs(data, "", server_id, self.session) if result == None: raise IOError("Could not write to remote server: filename:%s" % (self.rpath)) else: # Keeps mirrored local copy up to date. command = "cp {0} {1}".format(self.path, hidden_file_path(self.path)) r = os.popen(command) unlock_file(self.rpath, self._name, self.password)
def handle_ping(self, message, session_key): file_name = message["message"] if os.path.exists(file_name): data = {"type": "ping", "mtime": os.path.getmtime(file_name)} else: data = {"type": "ping", "error": "The file you requested doesn't exist"} self.request.send(secure.encrypt_with_key(json.dumps(data), session_key))
def handle(self): resp = {"status_code" : 0} self.data = self.request.recv(1024).strip() try: self.jdata = json.loads(self.data) #This ping message is for servers trying to #make sure its live. if "type" in self.jdata: if self.jdata["type"] == "ping": self.request.send("[]") session = None return session = secure.decrypt_with_key(self.jdata["ticket"], password).strip() session = json.loads(session)[0] filename = secure.decrypt_with_key(self.jdata["filename"], session).strip() filename = secure.decrypt_with_key(self.jdata["filename"], session).strip() if "type" in self.jdata: if self.jdata["type"] == "ping": self.request.send("[]") return elif self.jdata["type"] == "unlock": if filename in locked_files: if locked_files[filename] == str(self.client_address[0]) + self.jdata["name"]: del locked_files[filename] resp["message"] = "Successfully unlocked {0}".format(filename) resp["status_code"] = 1 else: resp["message"] = "You don't have the correct permission to unlock this file." else: resp["message"] = "File is not locked so an unlock is not possible." elif self.jdata["type"] == "lock": if filename in locked_files: if locked_files[filename] == str(self.client_address[0]) + self.jdata["name"]: resp["message"] = "You already have the lock for {0}".format(filename) resp["status_code"] = 1 else: resp["message"] = "Filename {0} is locked. Unable to access.".format(filename) else: locked_files[filename] = str(self.client_address[0]) + self.jdata["name"] resp["message"] = "Filename {0} successfully locked.".format(filename) resp["status_code"] = 1 else: resp["message"] = "Incorrect message parameters." except ValueError: resp["message"] = "Incorrect incoming json message." except KeyError: resp["message"] = "Incorrect incoming json parameters." finally: if session: jdata= secure.encrypt_with_key(json.dumps(resp), session) else: jdata = json.dumps(resp) self.request.send(jdata)
def get_file_from_server(self): server_id, ticket, self.session = self.get_tickets() data = { "ticket": ticket, "request": {"type": "open", "relative": self.rpath, "message": os.path.join(server_id[2], self.rpath)}, } data["request"] = secure.encrypt_with_key(json.dumps(data["request"]), self.session) check = lookup_fs(data, self.path, server_id, self.session) if check == None: self.get_file_from_server() return file.__init__(self, self.path, self._mode)
def look_for_changes(self): server_id, ticket, self.session = self.get_tickets() data = {"ticket": ticket, "request": {"type": "changed", "message": os.path.join(server_id[2], self.rpath)}} data["request"] = secure.encrypt_with_key(json.dumps(data["request"]), self.session) check = lookup_fs(data, self.path, server_id, self.session) # Some server socket error if check == None: self.look_for_changes() return local_m_time = os.path.getmtime(self.path) if local_m_time < float(check): return True else: return False
def lookup_ds(message, server_id, ticket, session): data = {"message": secure.encrypt_with_key(message, session), "ticket": ticket} sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) received = None try: sock.connect((server_id[0], int(server_id[1]))) sock.send(json.dumps(data)) received = sock.recv(1024) received = secure.decrypt_with_key(received, session) finally: sock.close() if received: return received else: return None
def lookup_ls(filename, request, server_id, ticket, session, name): data = {"ticket": ticket, "filename": secure.encrypt_with_key(filename, session), "type": request, "name": name} sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) received = None try: sock.connect((server_id[0], int(server_id[1]))) sock.send(json.dumps(data)) received = sock.recv(1024) received = secure.decrypt_with_key(received, session) finally: sock.close() if received: # print received return json.loads(received) else: return None
def handle_write(self, message, session_key): data = {"status": "Received Diff File"} try: file_name = message["message"] print "Writing changes to {0}".format(file_name) diff = base64.b64decode(message["payload"]) if not diff == "": patch_output = patch_file(file_name, diff) print "Patch output:{0}".format(patch_output) else: open(file_name, "w").close() except ValueError: print "Ugh message from user doesn't have the required fields" data["error"] = "Input" finally: data["type"] = "write" self.request.send(secure.encrypt_with_key(json.dumps(data), session_key)) # This server is master, tell the slaves... if "relative" in message: self.replicate_changes(message["relative"], message["payload"])
def file_write(file_to_lookup, diff_file_name, name, password, session=None): results = get_ticket_for_file(file_to_lookup, name, password) if(results == None): return None tickets, session, servers_id = results server_choice = random.randint(0, len(servers_id)-1) server_id = servers_id[server_choice] ticket = tickets[server_choice] contents = open(diff_file_name, "rb").read() data = { "ticket": ticket, "request": { "type":"write", "message": os.path.join(server_id[2], file_to_lookup), "relative": file_to_lookup, "payload":base64.b64encode(contents) } } data["request"] = secure.encrypt_with_key(json.dumps(data["request"]), session) print lookup_fs(data, "", server_id, session) return session
def file_open(file_to_lookup, name, password,local_file=None, session=None): results = get_ticket_for_file(file_to_lookup, name, password) if(results == None): return None tickets, session, servers_id = results server_choice = random.randint(0, len(servers_id)-1) server_id = servers_id[server_choice] ticket = tickets[server_choice] data = { "ticket": ticket, "request": { "type": "open", "message": os.path.join(server_id[2], file_to_lookup) } } data["request"] = secure.encrypt_with_key(json.dumps(data["request"]), session) local_file = os.path.join("cached", file_to_lookup) try: os.makedirs(os.path.dirname(local_file)) except OSError: pass print lookup_fs(data, local_file, server_id, session) return session
def replicate_changes(self, relative, body): print "I Am Replicating The Update" # Replicate changes. First must get ds entry from name = "fs/{0}:{1}".format(HOST, PORT) print "Connection AS at {0}:{1}".format(ASHOST, ASPORT) results = get_ticket_for_file(relative, name, password, ls_needed=False) if results == None: return None tickets, session, servers_id = results print results servers_id = [[h, p, f] for h, p, f in servers_id if not (h == HOST and p == str(PORT))] for i in range(0, len(servers_id)): # Note relative left out to let the file server know that # This is being replicated by a file server and doesnt need # further replication. ticket = tickets[i] server_id = servers_id[i] data = { "ticket": ticket, "request": {"type": "write", "message": os.path.join(server_id[2], relative), "payload": body}, } data["request"] = secure.encrypt_with_key(json.dumps(data["request"]), session) print lookup_fs(data, "", server_id, session)