pep.py/events/loginEvent.py

251 lines
9.1 KiB
Python
Raw Normal View History

2016-05-18 17:12:46 +00:00
from helpers import userHelper
from constants import serverPackets
from constants import exceptions
from objects import glob
from helpers import consoleHelper
from constants import bcolors
2016-05-18 17:12:46 +00:00
from helpers import locationHelper
from helpers import countryHelper
2016-04-19 17:40:59 +00:00
import time
2016-05-18 17:12:46 +00:00
from helpers import generalFunctions
import sys
import traceback
from helpers import requestHelper
2016-06-02 17:22:02 +00:00
from helpers import discordBotHelper
from helpers import logHelper as log
from helpers import chatHelper as chat
from constants import privileges
2016-04-19 17:40:59 +00:00
def handle(tornadoRequest):
2016-04-19 17:40:59 +00:00
# Data to return
responseTokenString = "ayy"
responseData = bytes()
# Get IP from tornado request
requestIP = tornadoRequest.getRequestIP()
2016-04-19 17:40:59 +00:00
# Avoid exceptions
clientData = ["unknown", "unknown", "unknown", "unknown", "unknown"]
osuVersion = "unknown"
2016-04-19 17:40:59 +00:00
# Split POST body so we can get username/password/hardware data
# 2:-3 thing is because requestData has some escape stuff that we don't need
loginData = str(tornadoRequest.request.body)[2:-3].split("\\n")
2016-04-19 17:40:59 +00:00
try:
# If true, print error to console
err = False
# Make sure loginData is valid
if len(loginData) < 3:
raise exceptions.haxException()
# Get HWID, MAC address and more
# Structure (new line = "|", already split)
# [0] osu! version
# [1] plain mac addressed, separated by "."
# [2] mac addresses hash set
# [3] unique ID
# [4] disk ID
splitData = loginData[2].split("|")
osuVersion = splitData[0]
2016-08-01 18:38:26 +00:00
timeOffset = int(splitData[1])
print(str(timeOffset))
clientData = splitData[3].split(":")[:5]
if len(clientData) < 4:
raise exceptions.forceUpdateException()
2016-04-19 17:40:59 +00:00
# Try to get the ID from username
username = str(loginData[0])
userID = userHelper.getID(username)
2016-04-19 17:40:59 +00:00
if userID == False:
# Invalid username
raise exceptions.loginFailedException()
if userHelper.checkLogin(userID, loginData[1]) == False:
# Invalid password
raise exceptions.loginFailedException()
# Make sure we are not banned
priv = userHelper.getPrivileges(userID)
if userHelper.isBanned(userID) == True and priv & privileges.USER_PENDING_VERIFICATION == 0:
2016-04-19 17:40:59 +00:00
raise exceptions.loginBannedException()
2016-06-11 16:43:27 +00:00
# 2FA check
if userHelper.check2FA(userID, requestIP) == True:
log.warning("Need 2FA check for user {}".format(loginData[0]))
raise exceptions.need2FAException()
2016-06-10 11:15:42 +00:00
# No login errors!
# Verify this user (if pending activation)
firstLogin = False
if priv & privileges.USER_PENDING_VERIFICATION > 0 or userHelper.hasVerifiedHardware(userID) == False:
if userHelper.verifyUser(userID, clientData) == True:
# Valid account
log.info("Account {} verified successfully!".format(userID))
glob.verifiedCache[str(userID)] = 1
firstLogin = True
else:
# Multiaccount detected
log.info("Account {} NOT verified!".format(userID))
glob.verifiedCache[str(userID)] = 0
raise exceptions.loginBannedException()
# Save HWID in db for multiaccount detection
hwAllowed = userHelper.logHardware(userID, clientData, firstLogin)
# This is false only if HWID is empty
# if HWID is banned, we get restricted so there's no
# need to deny bancho access
if hwAllowed == False:
raise exceptions.haxException()
# Log user IP
userHelper.logIP(userID, requestIP)
2016-04-19 17:40:59 +00:00
# Delete old tokens for that user and generate a new one
glob.tokens.deleteOldTokens(userID)
2016-08-01 18:38:26 +00:00
responseToken = glob.tokens.addToken(userID, requestIP, timeOffset=timeOffset)
2016-04-19 17:40:59 +00:00
responseTokenString = responseToken.token
# Check restricted mode (and eventually send message)
responseToken.checkRestricted()
# Set silence end UNIX time in token
responseToken.silenceEndTime = userHelper.getSilenceEnd(userID)
# Get only silence remaining seconds
silenceSeconds = responseToken.getSilenceSecondsLeft()
2016-04-19 17:40:59 +00:00
# Get supporter/GMT
userGMT = False
userSupporter = True
if responseToken.admin == True:
2016-04-19 17:40:59 +00:00
userGMT = True
# Server restarting check
if glob.restarting == True:
raise exceptions.banchoRestartingException()
# Send login notification before maintenance message
if glob.banchoConf.config["loginNotification"] != "":
responseToken.enqueue(serverPackets.notification(glob.banchoConf.config["loginNotification"]))
2016-04-19 17:40:59 +00:00
# Maintenance check
if glob.banchoConf.config["banchoMaintenance"] == True:
if userGMT == False:
# We are not mod/admin, delete token, send notification and logout
glob.tokens.deleteToken(responseTokenString)
raise exceptions.banchoMaintenanceException()
else:
# We are mod/admin, send warning notification and continue
responseToken.enqueue(serverPackets.notification("Bancho is in maintenance mode. Only mods/admins have full access to the server.\nType !system maintenance off in chat to turn off maintenance mode."))
# Send all needed login packets
responseToken.enqueue(serverPackets.silenceEndTime(silenceSeconds))
2016-04-19 17:40:59 +00:00
responseToken.enqueue(serverPackets.userID(userID))
responseToken.enqueue(serverPackets.protocolVersion())
responseToken.enqueue(serverPackets.userSupporterGMT(userSupporter, userGMT))
responseToken.enqueue(serverPackets.userPanel(userID, True))
responseToken.enqueue(serverPackets.userStats(userID, True))
2016-04-19 17:40:59 +00:00
# Channel info end (before starting!?! wtf bancho?)
responseToken.enqueue(serverPackets.channelInfoEnd())
# Default opened channels
# TODO: Configurable default channels
chat.joinChannel(token=responseToken, channel="#osu")
chat.joinChannel(token=responseToken, channel="#announce")
# Join admin channel if we are an admin
if responseToken.admin == True:
chat.joinChannel(token=responseToken, channel="#admin")
2016-04-19 17:40:59 +00:00
# Output channels info
for key, value in glob.channels.channels.items():
2016-07-15 09:46:44 +00:00
if value.publicRead == True and value.hidden == False:
2016-04-19 17:40:59 +00:00
responseToken.enqueue(serverPackets.channelInfo(key))
# Send friends list
2016-04-19 17:40:59 +00:00
responseToken.enqueue(serverPackets.friendList(userID))
# Send main menu icon
2016-04-19 17:40:59 +00:00
if glob.banchoConf.config["menuIcon"] != "":
responseToken.enqueue(serverPackets.mainMenuIcon(glob.banchoConf.config["menuIcon"]))
# Send online users IDs array
responseToken.enqueue(serverPackets.onlineUsers())
# Get location and country from ip.zxq.co or database
if glob.localize == True:
# Get location and country from IP
location = locationHelper.getLocation(requestIP)
countryLetters = locationHelper.getCountry(requestIP)
country = countryHelper.getCountryID(countryLetters)
2016-04-19 17:40:59 +00:00
else:
# Set location to 0,0 and get country from db
log.warning("Location skipped")
2016-04-19 17:40:59 +00:00
location = [0,0]
countryLetters = "XX"
2016-04-19 17:40:59 +00:00
country = countryHelper.getCountryID(userHelper.getCountry(userID))
# Set location and country
responseToken.setLocation(location)
responseToken.setCountry(country)
2016-05-01 16:09:35 +00:00
# Set country in db if user has no country (first bancho login)
if userHelper.getCountry(userID) == "XX":
userHelper.setCountry(userID, countryLetters)
# Send to everyone our userpanel if we are not restricted
if responseToken.restricted == False:
glob.tokens.enqueueAll(serverPackets.userPanel(userID))
2016-04-19 17:40:59 +00:00
# Set reponse data to right value and reset our queue
responseData = responseToken.queue
responseToken.resetQueue()
except exceptions.loginFailedException:
# Login failed error packet
# (we don't use enqueue because we don't have a token since login has failed)
err = True
responseData += serverPackets.loginFailed()
except exceptions.haxException:
# Invalid POST data
# (we don't use enqueue because we don't have a token since login has failed)
err = True
responseData += serverPackets.loginFailed()
responseData += serverPackets.notification("I see what you're doing...")
2016-04-19 17:40:59 +00:00
except exceptions.loginBannedException:
# Login banned error packet
err = True
responseData += serverPackets.loginBanned()
except exceptions.banchoMaintenanceException:
# Bancho is in maintenance mode
responseData = responseToken.queue
2016-04-19 17:40:59 +00:00
responseData += serverPackets.notification("Our bancho server is in maintenance mode. Please try to login again later.")
2016-06-11 16:43:27 +00:00
responseData += serverPackets.loginFailed()
2016-04-19 17:40:59 +00:00
except exceptions.banchoRestartingException:
# Bancho is restarting
responseData += serverPackets.notification("Bancho is restarting. Try again in a few minutes.")
2016-06-11 16:43:27 +00:00
responseData += serverPackets.loginFailed()
except exceptions.need2FAException:
# User tried to log in from unknown IP
responseData += serverPackets.needVerification()
except exceptions.haxException:
# Using oldoldold client, we don't have client data. Force update.
# (we don't use enqueue because we don't have a token since login has failed)
err = True
responseData += serverPackets.forceUpdate()
responseData += serverPackets.notification("Hory shitto, your client is TOO old! Nice preistoria! Please turn off the switcher and update it.")
except:
log.error("Unknown error!\n```\n{}\n{}```".format(sys.exc_info(), traceback.format_exc()))
2016-04-19 17:40:59 +00:00
finally:
# Console and discord log
if len(loginData) < 3:
msg = "Invalid bancho login request from **{}** (insufficient POST data)".format(requestIP)
else:
msg = "Bancho login request from **{}** for user **{}** ({})".format(requestIP, loginData[0], "failed" if err == True else "success")
log.info(msg, "bunker")
2016-06-02 17:22:02 +00:00
# Return token string and data
return (responseTokenString, responseData)