def __init__(self, server, port): if not isinstance(server, str): raise TypeError("Server's IP Adress must be str") return False if not isinstance(port, int): raise TypeError("Server's Port must be int") return False self.server = server self.port = port self.max_rcv = 2048 self.sock = socket.socket() self.crypt = EncryptionHandler() self.sid = None self.uidstring = None self.sesskey = None self.counter = None self.retry_counter = None self.max_retry = 10 if not self.get_sesskey(): raise RuntimeError("Error in client-server communication: DH exchange failed")
class SocketHandler: def __init__(self, server, port): if not isinstance(server, str): raise TypeError("Server's IP Adress must be str") return False if not isinstance(port, int): raise TypeError("Server's Port must be int") return False self.server = server self.port = port self.max_rcv = 2048 self.sock = socket.socket() self.crypt = EncryptionHandler() self.sid = None self.uidstring = None self.sesskey = None self.counter = None self.retry_counter = None self.max_retry = 10 if not self.get_sesskey(): raise RuntimeError("Error in client-server communication: DH exchange failed") def send(self, data, type_of_package): """ Sendet einen Datensatz in der Paketstruktur verpackt an den Server und gibt antwort zurueck @param data: Datensatz @type_of_package data: str @param type_of_package: Typ des Pakets @type type_of_package: str @return: str - Ergebnis, None bei Fehler """ if not isinstance(type_of_package, str): raise TypeError("Type must be str") return False # Paket nach Protokollstandart zusammenbauen msg = type_of_package + ":" msg += "12.12.12" + ":" if self.sid == None: msg += "x" else: msg += self.sid msg +=";" #if (type_of_package != "dhex") or not "get" in type_of_package : if type_of_package != "dhex": if self.sesskey == None: raise RuntimeError("No sesskey defined - aborting") return False data = data.encode("utf-8") #msg += self.crypt.encrypt(self.sesskey, self.counter, data) msg += data else: msg += data self.sock = socket.socket() self.sock.connect((self.server, self.port)) self.sock.send(msg) # Auf Antwort warten for attempt in range(10): try: ret_data = self.sock.recv(self.max_rcv) except EnvironmentError as exc: if exc.errno == errno.ECONNREFUSED: time.sleep(1) else: raise else: break else: raise RuntimeError("maximum number of unsuccessful attempts reached") return False self.sock.close() try: if type_of_package != "dhex": if "error" in ret_data: return ret_data ret_data = ret_data.split(";", 2) ret_data = ret_data[1] #ret_data = self.crypt.decrypt(self.sesskey, self.counter, ret_data) if ("get" in type_of_package) and not type_of_package == "getfile": try: ret_data = json.loads(ret_data) except ValueError as error: print "Error in JSON decoding :" + ret_data raise RuntimeError(error) return False else: ret_data = ret_data.decode("utf-8", "ignore") except IndexError as error: raise IndexError(error) return False return ret_data def parse_error(self, data): """ Extrahiert Fehlermeldungen aus einem Antwortpaket @param data: Antwortpaket @type data: str @return: 2x Tuple (str - Stelle, str - Fehler), False falls es kein Fehler ist """ try: #if string.find(data,"error", 0, 4) == -1 : if not "error - " in data: return False else: data = data.split(" - ", 3) return (data[2], data[1]) except IndexError: if isinstance(data, list): for item in data: print "error: " + item else: raise RuntimeError("Wrong server response :" + data) return False def get_sesskey(self): """ Generiert einen Sessionkey durch einen DH-Schluesselaustausch mit dem Server @return: Boolean success """ proot = 3 #prime = 2959259 prime = 13 num = random.randrange(1, prime - 2, 1) a = proot**num % prime b_data = self.send(str(a), "dhex") try: # Antwortpaket auswerten b_data = split(":", b_data) # Session-ID self.sid = b_data[0] # Sessionkey self.sesskey = self.crypt.generate_sesskey(num, int(b_data[1]), prime) # Counter iv = b_data[2] #iv = binascii.unhexlify(iv) self.counter = Counter.new(128, initial_value=long(iv, 16)) return True except IndexError as error: print error return False def auth(self, username, password, stay_logged_in): """ Authentifiziert einen Nutzer @param username: Nutzername @type username: str @param password: Passwort @type password: str @param stay_logged_in: Boolean ob der Nutzer eingeloggt beleiben soll @type stay_logged_in: Boolean @return: Boolean Success """ if not isinstance(stay_logged_in, bool): raise TypeError("stay_logged_in must be bool") return False if (username == None) or (password == None): print("Error no Username or Password given") else: password = self.crypt.get_hash(password) plain = username + ":" + password response = self.send(plain, "auth") error = self.parse_error(response) if not error: self.uidstring = response if stay_logged_in == True: self.write_loginfile(username, password) return True else: #raise RuntimeError(error) print error return False def auth_stayLogedIn(self): """ Authentifiziert einen Nutzer anhand der login.dat @return: Boolean Success """ plain = open('login.dat', 'r').read() plain_list = plain.split('\n') if len(plain_list) > 0: plain = str(plain_list[0]) else: raise RuntimeError("Login.dat content invalid and no password/username given") return False response = self.send(plain, "auth") error = self.parse_error(response) if not error: self.uidstring = response return True else: #raise RuntimeError(error) print error return False def write_message(self, receiver, content): """ Schickt eine Nachricht an einen User @param receiver: Empfaenger @type receiver: str @param content: Inhalt @type content: str @return: Boolean Success """ if not isinstance(receiver, str): raise TypeError("receiver must be str") return False if not isinstance(content, str): raise TypeError("content must be str") return False data = self.uidstring + ":" data += receiver + ":" data += content response = self.send(data, "msg") error = self.parse_error(response) if error == False: return True else: raise RuntimeError(error) return False def get_messages(self, last_mid): """ Ruft Nachrichten vom Server ab @param last_mid: Letzte bekannte Gruppennachrichten-ID @type last_mid: int @return: Array [str - sender, str - content], False bei Fehler, None bei keinen neuen Nachrichten """ msg = self.uidstring + ":" + str(last_mid) try: messages = self.send(msg, "getmsg") except (RuntimeError, ValueError, TypeError) as error: print error return False #messages = pickle.loads(messages) ret_msg = [] #if not messages: # raise RuntimeError("No messages have been received") # return False if isinstance(messages, int): raise RuntimeError("server communication failed") return False if len(messages) == 0: raise RuntimeError("Messages empty") return None elif isinstance(messages, str): error = self.parse_error(messages) if not error: return messages else: return False else: try: for item in messages: #parts = split(":", item, 2) ret_msg.append((item[0], item[1])) print "returning ret_msg" return ret_msg except IndexError as error: print error return False def write_group_message(self, group_receiver, content): """ Schickt eine Nachricht an eine Gruppe @param group_receiver: Empfaenger (Gruppe) @type group_receiver: str @param content: Inhalt @type content: str @return: Boolean Success """ if not isinstance(group_receiver, str): raise TypeError("group_receiver must be str") return False if not isinstance(content, str): raise TypeError("content must be str") return False data = self.uidstring + ":" + str(group_receiver) + ":" + str(content) response = self.send(data, "gmsg") error = self.parse_error(response) if error == False: return True else: raise RuntimeError(error) return False def get_group_messages(self, last_gmid): """ Ruft Gruppennachrichten vom Server ab @param last_gmid: Letzte bekannte Gruppennachrichten-ID @type last_gmid: int @return: Array [str - sender, str - gruppe, str - content], False bei Fehler, None bei keinen neuen Nachrichten """ if not isinstance(last_gmid, int): raise TypeError("last_gmid must be int") return False msg = self.uidstring + ":" + str(last_gmid) messages = self.send(msg, "getgmsg") ret_msg = [] if len(messages) == 0: return None elif len(messages) == 1: error = self.parse_error(messages) if not error: return messages else: raise RuntimeError(error) return False else: for item in messages: parts = split(":", item, 3) ret_msg.append((parts[0], parts[1], parts[1])) return ret_msg def write_loginfile(self, username, plain_password) : """ Schreibt eine valide Login.dat Datei @param username: Nutzername @type username: str @param plain_password: Passwort im Klartext @type plain_password: str @return: None """ data = username + ":" + self.crypt.get_hash(plain_password) loginfile = open("login.dat", 'w') loginfile.write(data) loginfile.close() def request_file(self): """ Beantragt einen neuen Dateiupload @return Dateiname """ ret = self.send("", "reqfile") error = self.parse_error(ret) if not error: return ret else: raise RuntimeError(error) return False def get_globalname(self, filestring): """ Findet den Dateinamen der Datei heraus @param filestring: Dateistring @type filestring: str @return: str - globalname """ ret = self.send(filestring, "getfile") error = self.parse_error(ret) if not error: return ret else: raise RuntimeError(error) return False def get_file(self, filestring): """ Laedt eine Datei von dem Server herunter @param filestring: Dateistring auf dem server @type filestring: str @return: Boolean Erfolg """ ftp = ftplib.FTP("127.0.0.1") ftp.login("ftp-user", "test") f = open("./data/" + filestring, "wr") data = "" ftp.retrbinary("RETR " + filestring, f.write) f.write(data) ftp.quit() f.close() name = self.get_globalname(filestring) print name if name: os.rename("./data/" + filestring, "./data/" + name) return "./data/" + name else: return False def upload_file(self, filestring, localfile, localname): """ Laedt eine Datei auf den Server hoch @param filestring: Dateistring auf dem Server @type filestring: str @param localfile: Lokale Datei @type localfile: str @return: Boolean Erfolg """ try: shutil.copyfile(localfile, "./tmp/" + filestring) ftp = ftplib.FTP("127.0.0.1") ftp.login("ftp-user", "test") f = open("./tmp/" + filestring, "r") #ftp.cwd("pub") ftp.storbinary("STOR " + filestring, f) f.close() ftp.quit() msg = filestring + ":" msg += localname ret = self.send(msg, "regfile") print ret error = self.parse_error(ret) if not error: return True return False except ftplib.all_errors as error: raise RuntimeError(error) return False def get_profile_pic(self, username): """ Speichert das Profilbild fuer einen Nutzer @param username: Nutzername @type username: str @return: None """ ret = self.send(username, "getpic") error = self.parse_error(ret) if not error: ret = self.get_file(ret) error = self.parse_error(ret) if not error: shutil.copyfile("./data/" + username + ".jpg", "./pic/" + username + ".jpg") return None shutil.copyfile("./pic/default.jpg", "./pic/" + username + ".jpg") def add_new_user(self, username, password): """ Fuegt einen neuen Nutzer auf dem Server hinzu @param username: Nutzername @type username: str @param password: Passwort @type password: str @param saveuser: Nutzer speichern ? @type saveuser: Boolean @return: Boolean Erfolg """ msg = username + ":" + self.crypt.get_hash(password) ret = self.send(msg, "adduser") print ret error = self.parse_error(ret) if error != False: return False return True def get_user_address_book(self): """ Empfaengt das Nutzer-Adressenbuch @return: Array - Adressbuch """ ret = self.send(self.uidstring, "adressbook") error = self.parse_error(ret) if error != False: print error return False return ret
hashengine = SHA256.new() if exists("login.dat") == True: plain_read = open('login.dat', 'r').read() plain_list = plain_read.split('\n') if len(plain_list) > 0: plain = str(plain_list[0]) elif exists("login.dat") == False: user = raw_input("Username:"******"Passwort:") stay_loged_in = raw_input("Stay Logedin:") hash_password = EncryptionHandler() hash_password_output = hash_password.get_hash(password) plain = user + ":" + hash_password_output if stay_loged_in == 'yes': save_info_user = open("login.dat", 'w') save_info_user.write(plain) else: pass #if Checkbox Safe my data is checked: #hash_password = EncryptionHandler()