def calcStats(): global solveCounts global scoreboard print("RECALCULATING STATS") with statsLock: solveCounts = dict([ ( chal.id, db.query(Solve).filter_by(challenge=chal.id).count() ) for chal in db.query(Challenge) ]) cscores = get_challenge_scores() board = [] for u in db.query(User): score = sum( cscores.get(x.challenge, 0) for x in db.query(Solve).filter_by(user=u.id) ) bisect.insort(board, (-score, max([ x.timestamp for x in db.query(Solve).filter_by(user=u.id) ] + [0]), u.name, u.id)) while len(board) > 10 and board[-1][0] != board[-2][0]: board.pop() scoreboard = [ {'username': n, 'score': -s, '_id': i} for s, _, n, i in board ]
def connectionMade(self): self.dbsession = DbSession() self.pong = pong.PongState(self) self.auth = Auth(self.dbsession, self.addr.host) print(f"{self.addr.host} connected.") self.send_message("Welcome", str(uuid.uuid4()))
def OtherUserInfo(): try: u = db.query(User).filter_by(id=request.args['uid']).one() except: return jsonify({'ok': False, 'txt': 'User not found'}) usolves = db.query(Challenge).filter( Challenge.id.in_([ x.challenge for x in db.query(Solve).filter_by(user=u.id) ]) ) return jsonify({'ok': True, 'data': { '_id': u.id, 'username': u.name, 'solves': [x.id for x in usolves], 'score': sum(x.points for x in usolves), }})
def MyUserInfo(): try: u = get_user_record() except: return jsonify(False) usolves = db.query(Challenge).filter( Challenge.id.in_([ x.challenge for x in db.query(Solve).filter_by(user=u.id) ]) ) return jsonify({ '_id': u.id, 'username': u.name, 'solves': [x.id for x in usolves], 'score': sum(x.points for x in usolves), 'email': u.email, })
def challenges(): chals = [ { '_id': chal.id, 'title': chal.title, 'category': chal.category, 'points': chal.points, 'text': chal.text, 'solves': solveCounts.get(chal.id, 0), } for chal in db.query(Challenge) ] return jsonify(chals)
def main(): db_session = DbSession() while True: try: user_input = raw_input() cmd_parts = user_input.split(' ') if cmd_parts[0]: if cmd_parts[0] == 'END': break # Determine the function to call based on the first part of the command fn_to_call = getattr(db_session, COMMAND_MAP[cmd_parts[0]]) # Execute the function with the remaining parts of the command acting as arguments fn_to_call(*cmd_parts[1:]) except KeyError as ex: print('Command {} not recognized.\nAvailable commands: {}'.format( ex[0], ', '.join(COMMAND_MAP.keys()))) except EOFError: break
def submitflag(): u = get_user_record() args = request.get_json() try: c = db.query(Challenge).filter_by(flag=args['flag']).one() except: return jsonify({'ok': False, 'msg': "Unknown flag."}) if db.query(Solve).filter_by(user=u.id, challenge=c.id).count(): return jsonify({'ok': False, 'msg': "You've already solved that one."}) db.add(Solve(user=u.id, challenge=c.id)) db.commit() calcStats() return jsonify({'ok': True, 'msg': 'Nice job!'})
def db_handler(*args, **kwargs): dbsession = DbSession() try: ret = cb(*args, **kwargs, dbsession=dbsession) except (ValidationError, NoResultFound): traceback.print_exc() return flask.Response(status=400) try: dbsession.commit() except IntegrityError as ex: # 1062 is the SQL error code for duplicate entry. # That's a user input error, but if we get some other kind # of integrity error, then it's a server error. if ex.orig.args[0] == 1062: return flask.Response(status=400) else: raise dbsession.close() return ret
def handle_authorize(remote, token, user_info): userid = remote.name + ',' + user_info['sub'] try: u = db.query(User).filter_by(id=userid).one() if user_info['name'] != u.name or user_info['email'] != u.email: u.name = user_info['name'] if user_info['email_verified']: u.email = user_info['email'] db.commit() except: u = User( id=userid, name=user_info['name'], email=user_info['email'] if user_info['email_verified'] else None ) db.add(u) db.commit() token = jwt.encode({'userid': u.id}, app.config['SECRET_KEY'], algorithm='HS256') return f'''
def shutdown_session(exception=None): db.remove()
def get_challenge_scores(): return dict([ (x.id, x.points) for x in db.query(Challenge) ])
def get_user_record(): auth = jwt.decode(request.headers['X-Sesid'], app.config['SECRET_KEY'], algorithms=['HS256']) return db.query(User).filter_by(id=auth['userid']).one()
#!/usr/bin/env python3 from secrets import token_hex from random import random from database import User, Challenge, Solve, DbSession def rand_chal(cat): t = token_hex(2+int(random()*8)) return Challenge( title=t, flag=t, category=cat, points=int(random()*100), text=' '.join([token_hex(int(random()*12)) for _ in range(10)]), ) s = DbSession() for cat in ['web', 'crypto', 'pwn', 'programming', 'forensics']: for n in range(int(4+4*random())): s.add(rand_chal(cat)) s.commit()
class MudConnection(ServerMessageStream): def __init__(self, factory, addr): self.factory = factory self.addr = addr self.authsession = None super().__init__() def connectionMade(self): self.dbsession = DbSession() self.pong = pong.PongState(self) self.auth = Auth(self.dbsession, self.addr.host) print(f"{self.addr.host} connected.") self.send_message("Welcome", str(uuid.uuid4())) # If the server shuts down, all the clients that were left open # will reconnect as soon as it comes back on. But, they don't # bother to re-authenticate on their own, so the server has to # prompt them to save to get the copy of the auth token that is # in the save. When the client joins on its own startup, # and authenticates anyway, hopefully this won't matter... #self.run_command("sos.save") # but it is commented out cause the lua script doesn't work def connectionLost(self, reason): print(f"{self.addr.host} disconnected.") self.closing = True self.pong.leave() self.dbsession.close() def serverMessageReceived(self, message): if message.Name not in ["pong_mp_setballpos", "pong_mp_setopponenty"]: print(f"{self.addr.host}: {message.Name}({repr(message.Contents)})") if message.Name in handlers: try: handlers[message.Name](self, message.Contents) self.dbsession.commit() except: self.dbsession.rollback() self.error(traceback.format_exc()) traceback.print_exc() else: self.error(f"Unimplemented message {message.Name}. Thanks for using Shift Gears!") def send_message(self, name, contents = None, guid = None): if contents is not None and not isinstance(contents, str): contents = jsonconverter.to_json(contents) guid = str(guid) self.sendServerMessage(ServerMessage(name, contents, guid)) def error(self, message): # The content of the Error message is deserialised at the other # end as an Exception, but only the Message member is read. self.send_message("Error", {"ClassName":"System.Exception","Message":message,"Data":None,"InnerException":None,"HelpURL":None,"StackTraceString":None,"RemoteStackTraceString":None,"RemoteStackIndex":0,"ExceptionMethod":None,"HResult":-2146233088,"Source":None}) # executes Lua code on the client...its that easy def run(self, script): self.send_message("run", {"script": script}) # executes a ShiftOS command on the client def run_command(self, cmd): # We don't use trm_invokecommand because it expects the prompt # to be sent to it before the command and it's not always # feasible to figure out what the prompt is. self.run(f"sos.runCommand({repr(cmd)})") def infobox(self, msg, title = "MUD"): self.invoke_command("infobox.show" + jsonconverter.to_json({"title": title, "msg": msg}))