async def handle_login(p, credentials: WorldCredentials): async with p.server.redis.pipeline(transaction=True) as tr: tr.get(f'{credentials.username}.lkey') tr.get(f'{credentials.username}.ckey') tr.delete(f'{credentials.username}.lkey', f'{credentials.username}.ckey') login_key, confirmation_hash, _ = await tr.execute() if login_key is None or confirmation_hash is None: return await p.close() login_key = login_key.decode() login_hash = Crypto.encrypt_password(login_key + p.server.config.auth_key) + login_key if credentials.client_key != login_hash: return await p.close() if login_key != credentials.login_key or confirmation_hash.decode( ) != credentials.confirmation_hash: return await p.close() data = await Penguin.get(credentials.id) p.login_key = login_key await world_login(p, data)
async def handle_login(p, credentials: WorldCredentials): tr = p.server.redis.multi_exec() tr.get(f'{credentials.username}.lkey') tr.get(f'{credentials.username}.ckey') tr.delete(f'{credentials.username}.lkey', f'{credentials.username}.ckey') login_key, confirmation_hash, _ = await tr.execute() if login_key is None or confirmation_hash is None: return await p.close() login_key = login_key.decode() login_hash = Crypto.encrypt_password( login_key + config.client['AuthStaticKey']) + login_key if credentials.client_key != login_hash: return await p.close() if login_key != credentials.login_key or confirmation_hash.decode( ) != credentials.confirmation_hash: return await p.close() data = await Penguin.get(credentials.id) p.login_key = login_key await world_login(p, data)
async def handle_login(p, credentials: WorldCredentials): if len(p.server.penguins_by_id) >= p.server.server_config['Capacity']: return await p.send_error_and_disconnect(103) tr = p.server.redis.multi_exec() tr.get('{}.lkey'.format(credentials.username)) tr.get('{}.ckey'.format(credentials.username)) tr.delete('{}.lkey'.format(credentials.username), '{}.ckey'.format(credentials.username)) login_key, confirmation_hash, _ = await tr.execute() if login_key is None or confirmation_hash is None: return await p.close() login_key = login_key.decode() login_hash = Crypto.encrypt_password( login_key + config.client['AuthStaticKey']) + login_key if credentials.client_key != login_hash: return await p.close() if login_key != credentials.login_key or confirmation_hash.decode( ) != credentials.confirmation_hash: return await p.close() data = await Penguin.get(credentials.id) if data is None: return await p.send_error_and_disconnect(100) if not data.active: return await p.close() if data.permaban: return await p.close() active_ban = await Ban.query.where((Ban.penguin_id == data.id) & ( Ban.expires >= datetime.now())).gino.scalar() if active_ban is not None: return await p.close() if data.id in p.server.penguins_by_id: await p.server.penguins_by_id[data.id].close() p.logger.info('{} logged in successfully'.format(data.username)) p.data = data p.login_key = login_key await p.send_xt('l')
async def handle_legacy_login(p, credentials: Credentials): tr = p.server.redis.multi_exec() tr.get(f'{credentials.username}.lkey') tr.delete(f'{credentials.username}.lkey', '{credentials.username}.ckey') login_key, _ = await tr.execute() login_key = login_key.decode() login_hash = Crypto.encrypt_password( login_key + config.client['AuthStaticKey']) + login_key if login_key is None or login_hash != credentials.password: return await p.close() data = await Penguin.query.where(Penguin.username == credentials.username ).gino.first() p.login_key = login_key await world_login(p, data)
async def handle_legacy_login(p, credentials: Credentials): async with p.server.redis.pipeline(transaction=True) as tr: tr.get(f'{credentials.username}.lkey') tr.delete(f'{credentials.username}.lkey', f'{credentials.username}.ckey') login_key, _ = await tr.execute() try: login_key = login_key.decode() except AttributeError: return await p.close() login_hash = Crypto.encrypt_password(login_key + p.server.config.auth_key) + login_key if login_key is None or login_hash != credentials.password: return await p.close() data = await Penguin.query.where(Penguin.username == credentials.username ).gino.first() p.login_key = login_key await world_login(p, data)
async def handle_login(p, credentials: Credentials): loop = asyncio.get_event_loop() username, password = credentials.username, credentials.password p.logger.info('{} is logging in!'.format(username)) data = await Penguin.query.where(Penguin.username == username).gino.first() if data is None: p.logger.info( '{} failed to login: penguin does not exist'.format(username)) return await p.send_error_and_disconnect(100) password_correct = await loop.run_in_executor( None, bcrypt.checkpw, password.encode('utf-8'), data.password.encode('utf-8')) ip_addr = p.peer_name[0] flood_key = '{}.flood'.format(ip_addr) if not password_correct: p.logger.info( '{} failed to login: incorrect password'.format(username)) if await p.server.redis.exists(flood_key): tr = p.server.redis.multi_exec() tr.incr(flood_key) tr.expire(flood_key, p.server.server_config['LoginFailureTimer']) failure_count, _ = await tr.execute() if failure_count >= p.server.server_config['LoginFailureLimit']: return await p.send_error_and_disconnect(150) else: await p.server.redis.setex( flood_key, p.server.server_config['LoginFailureTimer'], 1) return await p.send_error_and_disconnect(101) failure_count = await p.server.redis.get(flood_key) if failure_count: max_attempts_exceeded = int( failure_count) >= p.server.server_config['LoginFailureLimit'] if max_attempts_exceeded: return await p.send_error_and_disconnect(150) else: await p.server.redis.delete(flood_key) preactivation_hours = 0 if not data.active: preactivation_expiry = data.registration_date + timedelta(days=7) preactivation_expiry = preactivation_expiry - datetime.now() preactivation_hours = preactivation_expiry.total_seconds() // 3600 if preactivation_hours <= 0 or p.client_type == ClientType.Legacy: return await p.send_error_and_disconnect(900) if data.permaban: return await p.send_error_and_disconnect(603) if data.grounded: return await p.send_error_and_disconnect(913) if data.timer_active: if not data.timer_start < datetime.now().time() < data.timer_end: return await p.send_error_and_disconnect(911, data.timer_start, data.timer_end) if await data.minutes_played_today >= data.timer_total.total_seconds( ) // 60: return await p.send_error_and_disconnect(910, data.timer_total) active_ban = await Ban.query.where(Ban.penguin_id == data.id and Ban.expires >= datetime.now() ).gino.first() if active_ban is not None: hours_left = round( (active_ban.expires - datetime.now()).total_seconds() / 60 / 60) if hours_left == 0: return await p.send_error_and_disconnect(602) else: await p.send_error_and_disconnect(601, hours_left) p.logger.info('{} has logged in successfully'.format(username)) random_key = Crypto.generate_random_key() login_key = Crypto.hash(random_key[::-1]) confirmation_hash = Crypto.hash(os.urandom(24)) tr = p.server.redis.multi_exec() tr.setex('{}.lkey'.format(data.username), p.server.server_config['KeyTTL'], login_key) tr.setex('{}.ckey'.format(data.username), p.server.server_config['KeyTTL'], confirmation_hash) await tr.execute() world_populations, buddy_presence = await get_server_presence(p, data.id) if p.client_type == ClientType.Vanilla: raw_login_data = '|'.join([ str(data.id), str(data.id), data.username, login_key, str(data.approval), str(data.rejection) ]) if not data.active: await p.send_xt('l', raw_login_data, confirmation_hash, '', world_populations, buddy_presence, data.email, int(preactivation_hours)) else: await p.send_xt('l', raw_login_data, confirmation_hash, '', world_populations, buddy_presence, data.email) else: await p.send_xt('l', data.id, login_key, world_populations, buddy_presence)
def encode_music_track(track_pattern): encoded_track_pattern = track_pattern[::-1] encoded_track_pattern = Crypto.hash(encoded_track_pattern) return encoded_track_pattern[16:32] + encoded_track_pattern[0:16]
async def handle_login(p, credentials: Credentials): loop = asyncio.get_event_loop() username, password = credentials.username, credentials.password p.logger.info(f'{username} is logging in!') data = await Penguin.query.where(func.lower(Penguin.username) == username ).gino.first() if data is None: p.logger.info(f'{username} failed to login: penguin does not exist') return await p.send_error_and_disconnect(100) password_correct = await loop.run_in_executor( None, bcrypt.checkpw, password.encode('utf-8'), data.password.encode('utf-8')) ip_addr = p.peer_name[0] flood_key = f'{ip_addr}.flood' if not password_correct: p.logger.info(f'{username} failed to login: incorrect password') if await p.server.redis.exists(flood_key): async with p.server.redis.pipeline(transaction=True) as tr: tr.incr(flood_key) tr.expire(flood_key, p.server.config.login_failure_timer) failure_count, _ = await tr.execute() if failure_count >= p.server.config.login_failure_limit: return await p.send_error_and_disconnect(150) else: await p.server.redis.setex(flood_key, p.server.config.login_failure_timer, 1) return await p.send_error_and_disconnect(101) failure_count = await p.server.redis.get(flood_key) if failure_count: max_attempts_exceeded = int( failure_count) >= p.server.config.login_failure_limit if max_attempts_exceeded: return await p.send_error_and_disconnect(150) else: await p.server.redis.delete(flood_key) preactivation_hours = 0 if not data.active: preactivation_expiry = data.registration_date + timedelta( days=p.server.config.preactivation_days) preactivation_expiry = preactivation_expiry - datetime.now() preactivation_hours = preactivation_expiry.total_seconds() // 3600 if preactivation_hours <= 0 or p.client_type == ClientType.Legacy: return await p.send_error_and_disconnect(900) if data.permaban: return await p.send_error_and_disconnect(603) if data.grounded: return await p.send_error_and_disconnect(913) if data.timer_active: if not data.timer_start < datetime.now().time() < data.timer_end: return await p.send_error_and_disconnect(911, data.timer_start, data.timer_end) minutes_played_today = await get_minutes_played_today(p) if minutes_played_today >= data.timer_total.total_seconds() // 60: return await p.send_error_and_disconnect(910, data.timer_total) active_ban = await Ban.query.where((Ban.penguin_id == data.id) & ( Ban.expires >= datetime.now())).gino.first() if active_ban is not None: hours_left = round( (active_ban.expires - datetime.now()).total_seconds() / 60 / 60) if hours_left == 0: return await p.send_error_and_disconnect(602) else: return await p.send_error_and_disconnect(601, hours_left) p.logger.info(f'{username} has logged in successfully') random_key = Crypto.generate_random_key() login_key = Crypto.hash(random_key[::-1]) confirmation_hash = Crypto.hash(os.urandom(24)) async with p.server.redis.pipeline(transaction=True) as tr: tr.setex(f'{data.username}.lkey', p.server.config.auth_ttl, login_key) tr.setex(f'{data.username}.ckey', p.server.config.auth_ttl, confirmation_hash) await tr.execute() world_populations, buddy_presence = await get_server_presence(p, data) if p.client_type == ClientType.Vanilla: raw_login_data = f'{data.id}|{data.id}|{data.username}|{login_key}|houdini|{data.approval}|{data.rejection}' if not data.active: await p.send_xt('l', raw_login_data, confirmation_hash, '', world_populations, buddy_presence, data.email, int(preactivation_hours)) else: await p.send_xt('l', raw_login_data, confirmation_hash, '', world_populations, buddy_presence, data.email) else: await p.send_xt('l', data.id, login_key, buddy_presence, world_populations)