diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7b2115a --- /dev/null +++ b/LICENSE @@ -0,0 +1,3 @@ +Copyright (C) The Ripple Developers - All Rights Reserved +Unauthorized copying of this file, via any medium is strictly prohibited +Proprietary and confidential \ No newline at end of file diff --git a/events/loginEvent.py b/events/loginEvent.py index 1311b70..18183fb 100644 --- a/events/loginEvent.py +++ b/events/loginEvent.py @@ -46,13 +46,13 @@ def handle(tornadoRequest): # Banned raise exceptions.loginBannedException() + # No login errors! # Log user IP userHelper.IPLog(userID, requestIP) - # No login errors! # Delete old tokens for that user and generate a new one glob.tokens.deleteOldTokens(userID) - responseToken = glob.tokens.addToken(userID) + responseToken = glob.tokens.addToken(userID, requestIP) responseTokenString = responseToken.token # Set silence end UNIX time in token diff --git a/helpers/logHelper.py b/helpers/logHelper.py index 5823a20..21ed479 100644 --- a/helpers/logHelper.py +++ b/helpers/logHelper.py @@ -29,6 +29,8 @@ def logMessage(message, alertType = "INFO", messageColor = bcolors.ENDC, discord typeColor = bcolors.RED elif alertType == "CHAT": typeColor = bcolors.BLUE + elif alertType == "DEBUG": + typeColor = bcolors.PINK else: typeColor = bcolors.ENDC diff --git a/helpers/userHelper.py b/helpers/userHelper.py index 1b877f2..1e9b7f8 100644 --- a/helpers/userHelper.py +++ b/helpers/userHelper.py @@ -317,3 +317,19 @@ def IPLog(userID, ip): """ glob.db.execute("""INSERT INTO ip_user (userid, ip, occurencies) VALUES (%s, %s, '1') ON DUPLICATE KEY UPDATE occurencies = occurencies + 1""", [userID, ip]) + +def saveBanchoSession(userID, ip): + """ + Save userid and ip of this token in bancho_sessions table. + Used to cache logins on LETS requests + """ + log.debug("Saving bancho session ({}::{}) in db".format(userID, ip)) + glob.db.execute("INSERT INTO bancho_sessions (id, userid, ip) VALUES (NULL, %s, %s)", [userID, ip]) + +def deleteBanchoSessions(userID, ip): + """Delete this bancho session from DB""" + log.debug("Deleting bancho session ({}::{}) from db".format(userID, ip)) + try: + glob.db.execute("DELETE FROM bancho_sessions WHERE userid = %s AND ip = %s", [userID, ip]) + except: + log.warning("Token for user: {} ip: {} doesn't exist".format(userID, ip)) diff --git a/objects/osuToken.py b/objects/osuToken.py index 93401ff..2d9090e 100644 --- a/objects/osuToken.py +++ b/objects/osuToken.py @@ -10,7 +10,8 @@ import time import threading class token: - """Osu Token object + """ + Osu Token object token -- token string userID -- userID associated to that token @@ -33,13 +34,14 @@ class token: """ - def __init__(self, __userID, __token = None): + def __init__(self, __userID, token = None, ip = ""): """ Create a token object and set userID and token __userID -- user associated to this token - __token -- if passed, set token to that value + token -- if passed, set token to that value if not passed, token will be generated + ip -- client ip. optional. """ # Set stuff @@ -48,7 +50,7 @@ class token: self.rank = userHelper.getRankPrivileges(self.userID) self.loginTime = int(time.time()) self.pingTime = self.loginTime - self.lock = threading.Lock() # <-- Sync primitive + self.lock = threading.Lock() # Sync primitive # Default variables self.spectators = [] @@ -60,6 +62,7 @@ class token: self.actionMd5 = "" self.actionMods = 0 self.gameMode = gameModes.std + self.ip = ip self.country = 0 self.location = [0,0] self.awayMessage = "" @@ -71,14 +74,18 @@ class token: # Spam protection self.longMessageWarning = False self.spamRate = 0 - self.lastMessagetime = 0 + #self.lastMessagetime = 0 # Generate/set token - if __token != None: - self.token = __token + if token != None: + self.token = token else: self.token = str(uuid.uuid4()) + # If we have a valid ip, save bancho session in DB so we can cache LETS logins + if ip != "": + userHelper.saveBanchoSession(self.userID, self.ip) + def enqueue(self, __bytes): """ diff --git a/objects/tokenList.py b/objects/tokenList.py index ee154bc..6d9975c 100644 --- a/objects/tokenList.py +++ b/objects/tokenList.py @@ -1,8 +1,10 @@ from objects import osuToken +from objects import glob import time import threading from events import logoutEvent from helpers import logHelper as log +from helpers import userHelper class tokenList: """ @@ -17,73 +19,77 @@ class tokenList: """ self.tokens = {} - def addToken(self, __userID): + def addToken(self, userID, ip = ""): """ Add a token object to tokens list - __userID -- user id associated to that token + userID -- user id associated to that token return -- token object """ - newToken = osuToken.token(__userID) + newToken = osuToken.token(userID, ip=ip) self.tokens[newToken.token] = newToken return newToken - def deleteToken(self, __token): + def deleteToken(self, token): """ Delete a token from token list if it exists - __token -- token string + token -- token string """ - if __token in self.tokens: - self.tokens.pop(__token) + if token in self.tokens: + # Delete session from DB + userHelper.deleteBanchoSessions(self.tokens[token].userID, self.tokens[token].ip) + + # Pop token from list + self.tokens.pop(token) - def getUserIDFromToken(self, __token): + def getUserIDFromToken(self, token): """ Get user ID from a token - __token -- token to find + token -- token to find return: false if not found, userID if found """ # Make sure the token exists - if __token not in self.tokens: + if token not in self.tokens: return False # Get userID associated to that token - return self.tokens[__token].userID + return self.tokens[token].userID - def getTokenFromUserID(self, __userID): + def getTokenFromUserID(self, userID): """ Get token from a user ID - __userID -- user ID to find + userID -- user ID to find return -- False if not found, token object if found """ # Make sure the token exists for _, value in self.tokens.items(): - if value.userID == __userID: + if value.userID == userID: return value # Return none if not found return None - def getTokenFromUsername(self, __username): + def getTokenFromUsername(self, username): """ Get token from a username - __username -- username to find + username -- username to find return -- False if not found, token object if found """ # lowercase - who = __username.lower() + who = username.lower() # Make sure the token exists for _, value in self.tokens.items(): @@ -94,16 +100,16 @@ class tokenList: return None - def deleteOldTokens(self, __userID): + def deleteOldTokens(self, userID): """ Delete old userID's tokens if found - __userID -- tokens associated to this user will be deleted + userID -- tokens associated to this user will be deleted """ # Delete older tokens for key, value in self.tokens.items(): - if value.userID == __userID: + if value.userID == userID: # Delete this token from the dictionary self.tokens.pop(key) @@ -111,36 +117,36 @@ class tokenList: break - def multipleEnqueue(self, __packet, __who, __but = False): + def multipleEnqueue(self, packet, who, but = False): """ Enqueue a packet to multiple users - __packet -- packet bytes to enqueue - __who -- userIDs array - __but -- if True, enqueue to everyone but users in __who array + packet -- packet bytes to enqueue + who -- userIDs array + but -- if True, enqueue to everyone but users in who array """ for _, value in self.tokens.items(): shouldEnqueue = False - if value.userID in __who and not __but: + if value.userID in who and not but: shouldEnqueue = True - elif value.userID not in __who and __but: + elif value.userID not in who and but: shouldEnqueue = True if shouldEnqueue: - value.enqueue(__packet) + value.enqueue(packet) - def enqueueAll(self, __packet): + def enqueueAll(self, packet): """ Enqueue packet(s) to every connected user - __packet -- packet bytes to enqueue + packet -- packet bytes to enqueue """ for _, value in self.tokens.items(): - value.enqueue(__packet) + value.enqueue(packet) def usersTimeoutCheckLoop(self, __timeoutTime = 100, __checkTime = 100): """ @@ -182,3 +188,10 @@ class tokenList: # Schedule a new check (endless loop) threading.Timer(10, self.spamProtectionResetLoop).start() + + def deleteBanchoSessions(self): + """ + Truncate bancho_sessions table. + Call at bancho startup to delete old cached sessions + """ + glob.db.execute("TRUNCATE TABLE bancho_sessions") diff --git a/pep.py b/pep.py index e0c0c78..ad8c07e 100644 --- a/pep.py +++ b/pep.py @@ -81,6 +81,11 @@ if __name__ == "__main__": consoleHelper.printColored("[!] Error while loading bancho_settings. Please make sure the table in DB has all the required rows", bcolors.RED) raise + # Delete old bancho sessions + consoleHelper.printNoNl("> Deleting cached bancho sessions from DB... ") + glob.tokens.deleteBanchoSessions() + consoleHelper.printDone() + # Create threads pool try: consoleHelper.printNoNl("> Creating threads pool... ")