#! /usr/bin/env python3 import cgitb; cgitb.enable() import cgi import os import fcntl import re import sys import pointscli import teams import http.cookies from urllib.parse import quote, unquote ## ## This allows you to edit the URL and work on puzzles that haven't been ## unlocked yet. For now I think that's an okay vulnerability. It's a ## hacking contest, after all. ## cat_re = re.compile(r'^[a-z]+$') points_re = re.compile(r'^[0-9]+$') def dbg(*vals): print('Content-type: text/plain\n\n') print(*vals) points_by_cat = {} points_by_team = {} try: for line in open('/var/lib/ctf/puzzler.dat'): cat, team, pts = [unquote(v) for v in line.strip().split('\t')] pts = int(pts) points_by_cat[cat] = max(points_by_cat.get(cat, 0), pts) points_by_team.setdefault((team, cat), set()).add(pts) except IOError: pass c = http.cookies.SimpleCookie(os.environ.get('HTTP_COOKIE', '')) try: team = c['team'].value passwd = c['passwd'].value except KeyError: team, passwd = None, None f = cgi.FieldStorage() cat = f.getfirst('c') points = f.getfirst('p') team = f.getfirst('t', team) passwd = f.getfirst('w', passwd) key = f.getfirst('k') verboten = ['key', 'index.html'] def start_html(title): print('Content-type: text/html') if team or passwd: c = http.cookies.SimpleCookie() if team: c['team'] = team if passwd: c['passwd'] = passwd print(c) print() print('''
None (someone is slacking)
') end_html() def show_puzzle(cat, points, points_dir, team='', passwd=''): # Show puzzle in cat for points start_html('%s for %s points' % (cat, points)) fn = os.path.join(points_dir, 'index.html') if os.path.exists(fn): print('%d points for %s.
' % (points, team)) print('Back to %s.
' % (cat, cat)) end_html() def main(): cat_dir = safe_join('puzzles', cat) points_dir = safe_join('puzzles', cat, points) if not cat_dir: # Show categories show_cats() elif not points_dir: # Show available puzzles in category show_puzzles(cat, cat_dir) elif not (team and passwd and key): fn = f.getfirst('f') if fn in verboten: fn = None fn = safe_join('puzzles', cat, points, fn) if fn: # Provide a file from this directory print('Content-type: application/octet-stream') print() dump_file(fn) else: show_puzzle(cat, points, points_dir, team, passwd) else: try: thekey = open('%s/key' % points_dir, encoding='utf-8').read().strip() except IOError: # If there's no key, this can never be solved. thekey = False if not teams.chkpasswd(team, passwd): start_html('Wrong password') end_html() elif key != thekey: show_puzzle(cat, points, points_dir, team, passwd) elif int(points) in points_by_team.get((team, cat), set()): start_html('Greedy greedy') end_html() else: win(cat, team, points) main() # Local Variables: # mode: python # End: