mirror of https://github.com/dirtbags/moth.git
Merge branch 'master' of cfl.lanl.gov:/var/projects/gctf
This commit is contained in:
commit
b0815fdb9f
|
@ -2,7 +2,9 @@
|
|||
*.pyc
|
||||
*.dat
|
||||
*.swp
|
||||
*.tce
|
||||
passwd
|
||||
fake
|
||||
target/
|
||||
puzzler/
|
||||
ctf.tce
|
||||
|
|
4
Makefile
4
Makefile
|
@ -17,6 +17,9 @@ all: ctf.tce
|
|||
|
||||
target: $(PYC)
|
||||
$(INSTALL) -d --mode=0755 --owner=100 $(DESTDIR)/var/lib/ctf
|
||||
|
||||
$(INSTALL) -d --mode=0755 --owner=100 $(DESTDIR)/var/lib/ctf/survey
|
||||
|
||||
$(INSTALL) -d $(DESTDIR)/var/lib/ctf/disabled
|
||||
touch $(DESTDIR)/var/lib/ctf/disabled/survey
|
||||
|
||||
|
@ -25,6 +28,7 @@ target: $(PYC)
|
|||
|
||||
$(INSTALL) -d $(DESTDIR)/usr/sbin
|
||||
$(INSTALL) ctfd.py $(DESTDIR)/usr/sbin
|
||||
$(INSTALL) new-contest $(DESTDIR)/usr/sbin
|
||||
|
||||
$(INSTALL) -d $(WWWDIR)
|
||||
$(INSTALL) index.html intro.html ctf.css grunge.png $(WWWDIR)
|
||||
|
|
|
@ -40,6 +40,7 @@ class Gyopi(irc.Bot):
|
|||
self._lvl = 0
|
||||
self._flag.set_flag( self.FLAG_DEFAULT )
|
||||
|
||||
self._tokens = []
|
||||
self._lastAttempt = {}
|
||||
self._affiliations = {}
|
||||
self._newPuzzle()
|
||||
|
@ -62,7 +63,7 @@ class Gyopi(irc.Bot):
|
|||
self.last_tb = '%s %s %s' % (t, v, infostr)
|
||||
print(self.last_tb)
|
||||
|
||||
def cmd_join(self, sender, forum, addl):
|
||||
def cmd_JOIN(self, sender, forum, addl):
|
||||
"""On join, announce who has the flag."""
|
||||
if sender.name() in self.nicks:
|
||||
self._tellFlag(forum)
|
||||
|
@ -150,11 +151,11 @@ class Gyopi(irc.Bot):
|
|||
self._tokens[user].remove(token)
|
||||
|
||||
|
||||
def cmd_privmsg(self, sender, forum, addl):
|
||||
def cmd_PRIVMSG(self, sender, forum, addl):
|
||||
text = addl[0]
|
||||
who = sender.name()
|
||||
if text.startswith('!'):
|
||||
parts = text[1:].lower().split(' ', 1)
|
||||
parts = text[1:].split(' ', 1)
|
||||
cmd = parts[0]
|
||||
if len(parts) > 1:
|
||||
args = parts[1]
|
||||
|
@ -179,6 +180,7 @@ class Gyopi(irc.Bot):
|
|||
elif cmd.startswith('h'):
|
||||
# Help
|
||||
forum.msg('Goal: Help me with my math homework, FROM ANOTHER DIMENSION!')
|
||||
forum.msg('Order of operations is always left to right.')
|
||||
#forum.msg('Goal: The current winner gets to control the contest music.')
|
||||
forum.msg('Commands: !help, !flag, !register [TEAM], !solve SOLUTION,!? EQUATION, !ops, !problem, !who')
|
||||
elif cmd.startswith('prob'):
|
||||
|
@ -208,11 +210,15 @@ class Gyopi(irc.Bot):
|
|||
# self._giveToken(who, sender)
|
||||
self._saveState()
|
||||
else:
|
||||
forum.msg('%s: %s != %s' % (who, attempt, answer))
|
||||
forum.msg('%s: That is not correct.' % who)
|
||||
|
||||
# Test a simple one op command.
|
||||
elif cmd.startswith('?'):
|
||||
if not args:
|
||||
forum.msg('%s: Give me an easier problem, and I\'ll '
|
||||
'give you the answer.' % who)
|
||||
return
|
||||
|
||||
try:
|
||||
tokens = badmath.parse(''.join(args))
|
||||
except (ValueError) as msg:
|
||||
|
@ -253,7 +259,7 @@ if __name__ == '__main__':
|
|||
help='Flag server password')
|
||||
p.add_option('-d', '--path', dest='path', default='/var/lib/badmath',
|
||||
help='Path to where we can store state info.')
|
||||
p.add_option('-c', '--channel', dest='channel', default='+badmath',
|
||||
p.add_option('-c', '--channel', dest='channel', default='#badmath',
|
||||
help='Which channel to join')
|
||||
|
||||
opts, args = p.parse_args()
|
||||
|
|
Binary file not shown.
|
@ -10,5 +10,6 @@ dev=16,ino=87557238,mode=40755,uid=0,gid=0,nlink=2,rdev=0
|
|||
dev=16,ino=87557239,mode=40755,uid=0,gid=0,nlink=2,rdev=0
|
||||
dev=16,ino=87557240,mode=40755,uid=0,gid=0,nlink=2,rdev=0
|
||||
dev=16,ino=87573208,mode=100755,uid=0,gid=0,nlink=1,rdev=0
|
||||
dev=16,ino=87573213,mode=100755,uid=0,gid=0,nlink=1,rdev=0
|
||||
dev=16,ino=87573285,mode=100755,uid=0,gid=0,nlink=1,rdev=0
|
||||
dev=16,ino=87573433,mode=100755,uid=0,gid=0,nlink=1,rdev=0
|
||||
dev=16,ino=87573456,mode=100755,uid=0,gid=0,nlink=1,rdev=0
|
||||
|
|
|
@ -5,4 +5,4 @@
|
|||
DATA_PATH=/var/lib/badmath
|
||||
mkdir -p $DATA_PATH
|
||||
|
||||
exec envuidgid ctf python3.0 usr/lib/ctf/badmath/Gyopi.py --data=$DATA_PATH
|
||||
exec envuidgid ctf python3 /usr/lib/ctf/badmath/Gyopi.py --path=$DATA_PATH
|
||||
|
|
16
ctf.css
16
ctf.css
|
@ -77,3 +77,19 @@ p {
|
|||
margin-bottom: 20px;
|
||||
color: #f4f4f4;
|
||||
}
|
||||
|
||||
.solved {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
table.pollster {
|
||||
margin-left: 5em;
|
||||
}
|
||||
|
||||
table.pollster td {
|
||||
padding: 2px 1em 2px 5px;
|
||||
}
|
||||
|
||||
table.pollster thead {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,10 @@ else:
|
|||
'house_team': 'dirtbags',
|
||||
'passwd': '/var/lib/ctf/passwd',
|
||||
'team_colors': team_colors,
|
||||
'poll_interval': 60,
|
||||
'poll_timeout': 0.5,
|
||||
'heartbeat_dir': '/var/lib/pollster',
|
||||
'poll_dir': '/var/lib/www',
|
||||
},
|
||||
'puzzler':
|
||||
{'dir': '/usr/lib/www/puzzler',
|
||||
|
@ -66,3 +70,23 @@ def datafile(filename):
|
|||
|
||||
def url(path):
|
||||
return base_url + path
|
||||
|
||||
def start_html(title):
|
||||
if os.environ.get('GATEWAY_INTERFACE'):
|
||||
print('Content-type: text/html')
|
||||
print()
|
||||
print('''<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE html PUBLIC
|
||||
"-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>%s</title>
|
||||
<link rel="stylesheet" href="%s" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>%s</h1>
|
||||
''' % (title, css, title))
|
||||
|
||||
def end_html():
|
||||
print('</body></html>')
|
||||
|
|
|
@ -142,6 +142,8 @@ class FlagServer(asynchat.async_chat):
|
|||
self.inbuf.append(data)
|
||||
|
||||
def set_flag(self, team):
|
||||
if not self.cat:
|
||||
return
|
||||
self.flag = team
|
||||
self.submitter.set_flag(self.cat, team)
|
||||
f = open(os.path.join(flags_dir, self.cat), 'w')
|
||||
|
|
|
@ -27,7 +27,7 @@ cat_re = re.compile(r'^[a-z]+$')
|
|||
points_re = re.compile(r'^[0-9]+$')
|
||||
|
||||
def dbg(*vals):
|
||||
print('<--: \nContent-type: text/html\n\n--><pre>')
|
||||
print('<!--: \nContent-type: text/html\n\n--><pre>')
|
||||
print(*vals)
|
||||
print('</pre>')
|
||||
|
||||
|
@ -59,32 +59,16 @@ passwd = f.getfirst('w', passwd)
|
|||
key = f.getfirst('k')
|
||||
|
||||
def start_html(title):
|
||||
if os.environ.get('GATEWAY_INTERFACE'):
|
||||
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('''<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE html PUBLIC
|
||||
"-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>%s</title>
|
||||
<link rel="stylesheet" href="%s" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>%s</h1>
|
||||
''' % (title, config.css, title))
|
||||
|
||||
def end_html():
|
||||
print('</body></html>')
|
||||
if team or passwd:
|
||||
c = http.cookies.SimpleCookie()
|
||||
if team:
|
||||
c['team'] = team
|
||||
if passwd:
|
||||
c['passwd'] = passwd
|
||||
print(c)
|
||||
config.start_html(title)
|
||||
|
||||
end_html = config.end_html
|
||||
|
||||
def safe_join(*args):
|
||||
safe = list(args[:1])
|
||||
|
@ -125,7 +109,17 @@ def show_puzzles(cat, cat_dir):
|
|||
if puzzles:
|
||||
print('<ul>')
|
||||
for p in puzzles:
|
||||
print('<li><a href="%s/%s/%d">%d</a></li>' % (base_url, cat, p, p))
|
||||
cls = ''
|
||||
try:
|
||||
if p in points_by_team[(team, cat)]:
|
||||
cls = 'solved'
|
||||
except KeyError:
|
||||
pass
|
||||
print('<li><a href="%(base)s/%(cat)s/%(points)d" class="%(class)s">%(points)d</a></li>' %
|
||||
{'base': base_url,
|
||||
'cat': cat,
|
||||
'points': p,
|
||||
'class': cls})
|
||||
if p > opened:
|
||||
break
|
||||
print('</ul>')
|
||||
|
|
|
@ -7,6 +7,22 @@ import string
|
|||
from . import teams
|
||||
from . import config
|
||||
|
||||
def head(title):
|
||||
return '''<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<title>Team Registration</title>
|
||||
<link rel="stylesheet" href="%s" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>%s</h1>
|
||||
''' % (config.css, title)
|
||||
|
||||
def foot():
|
||||
return '''</body></html>'''
|
||||
|
||||
def main():
|
||||
print('Content-type: text/html')
|
||||
print()
|
||||
|
@ -17,17 +33,8 @@ def main():
|
|||
pw = f.getfirst('pw')
|
||||
confirm_pw = f.getfirst('confirm_pw')
|
||||
|
||||
html = string.Template('''<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<title>Team Registration</title>
|
||||
<link rel="stylesheet" href="%s" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Team Registration</h1>
|
||||
|
||||
html = string.Template(config.start_html('Team Registration') +
|
||||
('''
|
||||
<p>
|
||||
Pick a short team name: you'll be typing it a lot.
|
||||
</p>
|
||||
|
@ -50,10 +57,8 @@ def main():
|
|||
|
||||
<input type="submit" value="Register" />
|
||||
</fieldset>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
''' % (config.css, config.url('register.cgi')))
|
||||
</form>''' % config.url('register.cgi')) +
|
||||
config.end_html())
|
||||
|
||||
if not (team and pw and confirm_pw): # If we're starting from the beginning?
|
||||
html = html.substitute(team_error='',
|
||||
|
@ -66,7 +71,9 @@ def main():
|
|||
pw_match_error='Passwords do not match')
|
||||
else:
|
||||
teams.add(team, pw)
|
||||
html = 'Team registered.'
|
||||
html = (config.start_html('Team registered') +
|
||||
('<p>Congratulations, <samp>%s</samp> is now registered. Go <a href="%s">back to the front page</a> and start playing!</p>' % (team, config.url(''))) +
|
||||
config.end_html())
|
||||
|
||||
print(html)
|
||||
|
||||
|
|
14
ctf/teams.py
14
ctf/teams.py
|
@ -28,9 +28,7 @@ def build_teams():
|
|||
f = open(passwdfn)
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
team, passwd = [unquote(v) for v in line.strip().split('\t')]
|
||||
color = team_colors.pop(0)
|
||||
team_colors.append(color)
|
||||
team, passwd, color = map(unquote, line.strip().split('\t'))
|
||||
teams[team] = (passwd, color)
|
||||
except IOError:
|
||||
pass
|
||||
|
@ -53,10 +51,15 @@ def exists(team):
|
|||
return team in teams
|
||||
|
||||
def add(team, passwd):
|
||||
build_teams()
|
||||
color = team_colors[len(teams)%len(team_colors)]
|
||||
|
||||
assert team not in teams, "Team already exists."
|
||||
|
||||
f = open(passwdfn, 'a')
|
||||
fcntl.lockf(f, fcntl.LOCK_EX)
|
||||
f.seek(0, 2)
|
||||
f.write('%s\t%s\n' % (quote(team), quote(passwd)))
|
||||
f.write('%s\t%s\t%s\n' % (quote(team), quote(passwd), quote(color)))
|
||||
|
||||
def color(team):
|
||||
t = teams.get(team)
|
||||
|
@ -66,6 +69,3 @@ def color(team):
|
|||
if not t:
|
||||
return '888888'
|
||||
return t[1]
|
||||
|
||||
|
||||
|
||||
|
|
2
ctfd.py
2
ctfd.py
|
@ -4,6 +4,7 @@ import asyncore
|
|||
import os
|
||||
import sys
|
||||
import optparse
|
||||
import signal
|
||||
from ctf import pointsd
|
||||
from ctf import flagd
|
||||
from ctf import histogram
|
||||
|
@ -38,6 +39,7 @@ def main():
|
|||
pointsrv = pointsd.start()
|
||||
flagsrv = flagd.start()
|
||||
|
||||
signal.signal(signal.SIGCHLD, sigchld)
|
||||
s = pointsrv.store
|
||||
slen = 0
|
||||
while True:
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<h1>Welcome</h1>
|
||||
|
||||
<ol>
|
||||
<li><a href="intro.html">Read the introduction</a> to this event</li>
|
||||
<li><a href="intro.html">Read the introduction and rules</a></li>
|
||||
<li><a href="register.cgi">Register</a> your team</li>
|
||||
<li><a href="scoreboard.cgi">View the score board</a></li>
|
||||
</ol>
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
#! /bin/sh -e
|
||||
|
||||
ctime () {
|
||||
stat -c %z $1 | awk '{ print $1; }'
|
||||
}
|
||||
|
||||
rotate () {
|
||||
mv $1 $1.$(ctime $1)
|
||||
}
|
||||
|
||||
rotate /var/lib/ctf/puzzler.dat
|
||||
rotate /var/lib/ctf/scores.dat
|
||||
rotate /var/lib/ctf/passwd
|
||||
rm -f /var/lib/ctf/flags/* || true
|
||||
|
||||
echo "Things you may want to tweak:"
|
||||
find /var/lib/ctf/disabled
|
||||
find /var/lib/kevin/tokens
|
|
@ -0,0 +1,8 @@
|
|||
#! /bin/sh
|
||||
|
||||
case "$REMOTEADDR" in
|
||||
10.0.0.[2-254])
|
||||
touch /var/lib/pollster/$REMOTEADDR
|
||||
;;
|
||||
esac
|
||||
|
|
@ -0,0 +1,249 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
import socket
|
||||
import traceback
|
||||
import threading
|
||||
import queue
|
||||
|
||||
from ctf import config
|
||||
from ctf import pointscli
|
||||
|
||||
DEBUG = False
|
||||
POLL_INTERVAL = config.get('poll_interval')
|
||||
IP_DIR = config.get('heartbeat_dir')
|
||||
REPORT_PATH = config.get('poll_dir')
|
||||
SOCK_TIMEOUT = config.get('poll_timeout')
|
||||
|
||||
class PointSubmitter(threading.Thread):
|
||||
''' Pulls point allocations from the queue and submits them. '''
|
||||
def __init__(self, point_queue):
|
||||
threading.Thread.__init__(self)
|
||||
self.point_queue = point_queue
|
||||
self.sock = pointscli.makesock('localhost')
|
||||
|
||||
def run(self):
|
||||
# loop forever
|
||||
while(True):
|
||||
cat, team, score = self.point_queue.get()
|
||||
if None in [cat, team, score]:
|
||||
continue
|
||||
|
||||
try:
|
||||
pointscli.submit(cat, team, score, sock=self.sock)
|
||||
except ValueError:
|
||||
print('pollster: error submitting score (%s, %s, %d)' % (cat, team, score))
|
||||
traceback.print_exc()
|
||||
|
||||
def socket_poll(ip, port, msg, prot, max_recv=1):
|
||||
''' Connect via socket to the specified <ip>:<port> using the
|
||||
specified <prot>, send the specified <msg> and return the
|
||||
response or None if something went wrong. <max_recvs> specifies
|
||||
how many times to read from the socket (default to once). '''
|
||||
|
||||
# create a socket
|
||||
try:
|
||||
sock = socket.socket(socket.AF_INET, prot)
|
||||
except Exception as e:
|
||||
print('pollster: create socket failed (%s)' % e)
|
||||
traceback.print_exc()
|
||||
return None
|
||||
|
||||
sock.settimeout(SOCK_TIMEOUT)
|
||||
|
||||
# connect
|
||||
try:
|
||||
sock.connect((ip, port))
|
||||
except socket.timeout as e:
|
||||
print('pollster: attempt to connect to %s:%d timed out (%s)' % (ip, port, e))
|
||||
traceback.print_exc()
|
||||
return None
|
||||
except Exception as e:
|
||||
print('pollster: attempt to connect to %s:%d failed (%s)' % (ip, port, e))
|
||||
traceback.print_exc()
|
||||
return None
|
||||
|
||||
# send something
|
||||
sock.send(msg)
|
||||
|
||||
# get a response
|
||||
resp = ''
|
||||
try:
|
||||
# first read
|
||||
data = sock.recv(1024)
|
||||
resp += data.decode('utf-8')
|
||||
max_recv -= 1
|
||||
|
||||
# remaining reads as necessary until timeout or socket closes
|
||||
while(len(data) > 0 and max_recv > 0):
|
||||
data = sock.recv(1024)
|
||||
resp += data.decode('utf-8')
|
||||
max_recv -= 1
|
||||
sock.close()
|
||||
|
||||
except socket.timeout as e:
|
||||
print('pollster: timed out waiting for a response from %s:%d (%s)' % (ip, port, e))
|
||||
traceback.print_exc()
|
||||
except Exception as e:
|
||||
print('pollster: receive from %s:%d failed (%s)' % (ip, port, e))
|
||||
traceback.print_exc()
|
||||
|
||||
if len(resp) == 0:
|
||||
return None
|
||||
|
||||
return resp
|
||||
|
||||
# PUT POLLS FUNCTIONS HERE
|
||||
# Each function should take an IP address and return a team name or None
|
||||
# if (a) the service is not up, (b) it doesn't return a valid team name.
|
||||
|
||||
def poll_fingerd(ip):
|
||||
''' Poll the fingerd service. Returns None or a team name. '''
|
||||
resp = socket_poll(ip, 79, b'flag\n', socket.SOCK_STREAM)
|
||||
if resp is None:
|
||||
return None
|
||||
return resp.strip('\r\n')
|
||||
|
||||
def poll_noted(ip):
|
||||
''' Poll the noted service. Returns None or a team name. '''
|
||||
resp = socket_poll(ip, 4000, b'rflag\n', socket.SOCK_STREAM)
|
||||
if resp is None:
|
||||
return None
|
||||
return resp.strip('\r\n')
|
||||
|
||||
def poll_catcgi(ip):
|
||||
''' Poll the cat.cgi web service. Returns None or a team name. '''
|
||||
request = bytes('GET /cat.cgi/flag HTTP/1.1\r\nHost: %s\r\n\r\n' % ip, 'ascii')
|
||||
resp = socket_poll(ip, 80, request, socket.SOCK_STREAM, 3)
|
||||
if resp is None:
|
||||
return None
|
||||
|
||||
content = resp.split('\r\n\r\n')
|
||||
if len(content) < 3:
|
||||
return None
|
||||
|
||||
content = content[1].split('\r\n')
|
||||
|
||||
try:
|
||||
content_len = int(content[0])
|
||||
except Exception as e:
|
||||
return None
|
||||
|
||||
if content_len <= 0:
|
||||
return None
|
||||
return content[1].strip('\r\n')
|
||||
|
||||
def poll_tftpd(ip):
|
||||
''' Poll the tftp service. Returns None or a team name. '''
|
||||
resp = socket_poll(ip, 69, b'\x00\x01' + b'flag' + b'\x00' + b'octet' + b'\x00', socket.SOCK_DGRAM)
|
||||
if resp is None:
|
||||
return None
|
||||
|
||||
if len(resp) <= 5:
|
||||
return None
|
||||
|
||||
resp = resp.split('\n')[0]
|
||||
return resp[4:].strip('\r\n')
|
||||
|
||||
# PUT POLL FUNCTIONS IN HERE OR THEY WONT BE POLLED
|
||||
POLLS = {
|
||||
'fingerd' : poll_fingerd,
|
||||
'noted' : poll_noted,
|
||||
'catcgi' : poll_catcgi,
|
||||
'tftpd' : poll_tftpd,
|
||||
}
|
||||
|
||||
ip_re = re.compile('(\d{1,3}\.){3}\d{1,3}')
|
||||
|
||||
# start point submitter thread
|
||||
point_queue = queue.Queue()
|
||||
t = PointSubmitter(point_queue)
|
||||
t.start()
|
||||
|
||||
# loop forever
|
||||
while True:
|
||||
|
||||
t_start = time.time()
|
||||
|
||||
# gather the list of IPs to poll
|
||||
try:
|
||||
ips = os.listdir(IP_DIR)
|
||||
except Exception as e:
|
||||
print('pollster: could not list dir %s (%s)' % (IP_DIR, e))
|
||||
traceback.print_exc()
|
||||
|
||||
try:
|
||||
os.remove(REPORT_PATH)
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
try:
|
||||
out = open(REPORT_PATH, 'w')
|
||||
except Exception as e:
|
||||
out = None
|
||||
pass
|
||||
|
||||
if out is not None:
|
||||
out.write('<html>\n<head>\n')
|
||||
out.write('<title>Pollster Results</title>\n')
|
||||
out.write('<link rel="stylesheet" href="ctf.css" type="text/css" media="all" />\n')
|
||||
out.write('</head><body>\n<h1>Polling Results</h1>\n')
|
||||
|
||||
for ip in ips:
|
||||
|
||||
# check file name format is ip
|
||||
if ip_re.match(ip) is None:
|
||||
continue
|
||||
|
||||
# remove the file
|
||||
try:
|
||||
os.remove(os.path.join(IP_DIR, ip))
|
||||
except Exception as e:
|
||||
print('pollster: could not remove %s' % os.path.join(IP_DIR, ip))
|
||||
traceback.print_exc()
|
||||
|
||||
results = {}
|
||||
|
||||
if DEBUG is True:
|
||||
print('ip: %s' % ip)
|
||||
|
||||
if out is not None:
|
||||
out.write('<h2>%s</h2>\n' % ip)
|
||||
out.write('<table class="pollster">\n<thead><tr><td>Service Name</td></td>')
|
||||
out.write('<td>Flag Holder</td></tr></thead>\n')
|
||||
|
||||
# perform polls
|
||||
for service,func in POLLS.items():
|
||||
team = func(ip)
|
||||
if team is None:
|
||||
team = 'dirtbags'
|
||||
|
||||
if DEBUG is True:
|
||||
print('\t%s - %s' % (service, team))
|
||||
|
||||
if out is not None:
|
||||
out.write('<tr><td>%s</td><td>%s</td>\n' % (service, team))
|
||||
|
||||
point_queue.put((service, team, 1))
|
||||
|
||||
if out is not None:
|
||||
out.write('</table>\n')
|
||||
|
||||
if DEBUG is True:
|
||||
print('+-----------------------------------------+')
|
||||
|
||||
t_end = time.time()
|
||||
exec_time = int(t_end - t_start)
|
||||
sleep_time = POLL_INTERVAL - exec_time
|
||||
|
||||
if out is not None:
|
||||
out.write('<p><b>Next poll in: %ds</b></p>\n' % sleep_time)
|
||||
out.write('</body>\n</html>\n')
|
||||
out.close()
|
||||
|
||||
# sleep until its time to poll again
|
||||
time.sleep(sleep_time)
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
#! /bin/sh
|
||||
|
||||
exec udpsvd 0 9 /usr/sbin/in.heartbeatd
|
|
@ -0,0 +1,108 @@
|
|||
Safe to ex<b>e</b>cute.
|
||||
|
||||
<img width="20" height="20" src="data:image;base64,
|
||||
cjd7PTw9PDw8DQ0NDQ0NDQ8PDA0MDAwMzE5KQnYNDQ1lYmJiYmJiDTk5GRke
|
||||
HjY2Kg0UFBISEhImJiYNObm9tYEBBQ3tDQ0N7e3t7ejo6A0JCQkJCgoKCh4M
|
||||
DAwYmZ2VgQAEBRYWFhYFBQUFAQ0NDQwMDAwNDQ0NDQ0NDQ2NiYGBjYmBAQUF
|
||||
BYWBgQ0ICAgICBgYGBkNDQ2NiYmJCZ2ZBYURFR0dHBwcGAwMDAoKCgoKGhoN
|
||||
Dw8PD5ufn58LmZ2VAZWRmVFRUQ3FxcXFw8PDw8cNDQ0JCQkJISAgDSWkoKiA
|
||||
AQUNLQ0NDS0tLS0pKSkNCQkJCVi9ya2tDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQsN
|
||||
DQ0JCQkJJkojb0AsSGUJYA57AyNQPxEjIyMnJycNHR0dHRwcHBxbQxYWFhYW
|
||||
FhQUFA0PDw8PCgoKCgkNDQ0LCwsLDg4ODQ8PDw8MDAwMDA0NDQ0NDQ0MDAwN
|
||||
DQ0NDQ0NDQ0JDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDSMNDQ0NDQ0Np6amDR8fHx9d
|
||||
XV1dXQ0NDdDQ0NDCwsINPj4+PmLm4uruDQ0NHBwSEhMTEw0NDQ0NDQ0NDS0N
|
||||
DQ0YGBgYGBgYDQ0NDQ0tLS0tLVIYbjFjBmEIew9oGlk1VCdUMUJCUg1qB2gG
|
||||
WSpeP38LVAsLZw5sDyF+ET8JCXkMeAsLUhtUC3gMaAFvMHgLbgoKVQpmD21u
|
||||
MUI2VyVRDmMCZAoKTQFICkkWJCMTExMTERETExINDQ0NDQ0NDAwNDSkpKSk5
|
||||
OTk5OQ0NDR10HRAQEBINWVlZWVlZWVkFmJyUkpeXl/tuagUCAwMDc+bi6u0P
|
||||
Dw9a0za1WVG5bGxsbIQwMDAw2IaHh4dOjY1yRyOYnJRrTiazt7+/DQ0N8te7
|
||||
LioiSg0NDQ3kBPsE+wQoWM3JwamhoaGh5DTLNMv6F0nAIY5qmsqezKRw8/cF
|
||||
be1uamIzZQ1ljoqCaqVapVquPp3IQaT3Hx8fHx9W1xRndXV1J6wv8Q7xDotL
|
||||
Pz3CElUOxwSUBJTBSK2OYmrq11fCxs7OeXadgg95efo6Pq7SR0NLtGbHuy4J
|
||||
AYqaH824U5WQjRgcFBXcH5ZgNYRh4g4Gpzejp6+ISDwlnZ2dnZ0YzbmpKsbK
|
||||
ojKmogX6KqltffCGhk/OXs6bEvd0mJAT6RmadmoCYubi6uXHOMc48TJn7gta
|
||||
DF/cMDzU1NTUDVbXFMbX19c/4fMM83793SLdIq+evkG+QciNfVSEPMoL8/HI
|
||||
Dn1r4tpTpVpO/Hc6yuP0snOKiLF/9gx+42CkqPOt8jv4cfuuJ8KVw5B4eHgN
|
||||
DVbXFJWEhIQJjq5RrlHcZ0e4R/LbI+IaGJt3e/Z9gmls/AMXoO5t8wx5jmZI
|
||||
SEhIy8nFnsCfVpUFlcCEYTJg21vPy8NijRkdFf70eQ8PjObiHc1GRcY+wbT5
|
||||
ofoz8KUsyZpyDQ0NDVbXFA8eHg1dtQP9Av2k/zbOzs7Nzc3NzMzODUQwEHkK
|
||||
KktrB2IUcR1kRCBBOBhiF2MQeR14eHh4DQ0N8g3yDQ0NDQ3yDfINDQ0NDQ0N
|
||||
DQ0MDAwMKCgoDQEBAQF5+//3+g0NDTG1sbm9vb0NRcTAyM3Nzc0ZjIiAhoaG
|
||||
hvJzdwUPDw8PUVFRUVoNDQ0dHR0dCAgIDQ0NDQ0ODg4ObpiclJaWlpaGhoYN
|
||||
GRkZGQgICAgfDQ0NZefj6/r6+g1t7+vj8fHx8fkNDQ0eHh4eFhYWDfMM85zc
|
||||
XlpSrfINYmNjY2OTbJNiUNLW3t7e3t7eDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0N
|
||||
DQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ2ZDQkFBQUFBQUFBQWjj4uDNbez
|
||||
u7u7uw0NDQ0NgRURGRlKCUpwUHg/cSQNLR4wBCocPA4+DjsLPw87GzNhBGAt
|
||||
ZQRwUGNNeVdhIBgxMTF2NXZMbCViLHlQcENtWXc7GykZKR8vGysfLQVXMlZ2
|
||||
Pl8rCz4QJAo8ESkAAABKCUpwUHg/cSQNLR4wBCocPA4+DjsLPw87GzNhBGAt
|
||||
ZQRwUGNNeVdhIBkwMDB3NHdNbSViLHlQcENtWXc7GykZKR8vGysfLQVXMlZ2
|
||||
Pl8rCz4QJAo8ESgBAQFKCUpwUHg/cSQNLR4wBCocPA4+DjsLPw87GzNhBGAt
|
||||
ZQRwUGNNeVdhIBkwMDB3NHdNbSViLHlQcENtWXc7GykZKR8vGysfLQVXMlZ2
|
||||
Pl8rCz4QJAo8ESkAAAAjUClEMFEzMx1ueQt/Hnx8UiFJOnkLfx58fFI7VSFo
|
||||
GmpqRCpFMVR6TA5Hah5/GBg2Xmwfd3dZPUQqWSBgYE4qUz1OOkhII0QqX3EH
|
||||
YhBjCmIMDCJFK15wBmN/DGUKZDtJSWcVaAQqTjdZWXcFYGFPP1MnJwlgDmd5
|
||||
eVcjRj5KSmQCZApjY00/UDRVIWxsQidPEHYEZQhoaEYlUT5MPz8RaR1yAHNz
|
||||
XTdUJg0jRz5QMVw1VlYjRCtfX3EWeQ0jfRFlZUsvTjpbWyNBMkFBbwxjDmNo
|
||||
BnJycnJycnJyDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0N
|
||||
DRYWFg0MDAwMDg4ODhqMiICUlZWVhoaGDQ0NDQ0NDQ0NDA0NDQ0NDQ0uLi4N
|
||||
CgoKCggICAggjIiAqKmpqYmJiQ0NDQ0NDQ0NDQkNDQ0NDQ0NPDw8DQgICAgK
|
||||
CgoKQoyIgMjJycnl5eUNCQkJCQkJCQkNDQ0NCQkJCT4+Pg0GBgYGBAQEBHCM
|
||||
iID09fX1lZWVDQgICAgJCQkJDQ0NDR0dHR0iIiINDg4ODgwMDAzYjIiAVFVV
|
||||
VQsLCw0NDQ0NDQ0NDQwNDQ0NDQ0NSkpKDfIN8p2fn5+frY+Lg7Gzs7O/v78N
|
||||
CQkJCQkJCQkLDQ0NDw8PD1tbWw3zDPOcnp6ent6Pi4PDwcHB4eHhDQgICAgJ
|
||||
CQkJDQ0NDQ0NDQ1ubm4NBAQEBAYGBgZmj4uD4+Hh4enp6Q0JCQkJCQkJCQ0N
|
||||
DQ0FBQUFaWlpDQQEBAQGBgYGbo+Lg+vp6en5+fkNCQkJCQICAgIGDQ0NBQUF
|
||||
BXBwcA0MDAwMCgoKCnKPi4P7+fn57u7uDQ0NDQ0NDQ0NCQ0NDQ0NDQ19fX0N
|
||||
DAwMDAoKCgqaj4uDExERESEhIQ0NDQ0NDQ0NDQkNDQ0JCQkJcnJyDQwMDAwK
|
||||
CgoKyo+Lg0NBQUE9PDwNDQ0NDQ0NDQ0JDQ0NDQ0NDYyMjA0MDAwMCgoKCjaJ
|
||||
jYW5vb29p6enDQ0NDQ0NDQ0NCQ0NDQ0NDQ2KiooNDAwMDA4ODg5WiY2F3dnZ
|
||||
2fr6+g0NDQ0NDQ0NDQkNDQ0NDQ0NgoKCDQwMDAwODg4OcomNhfn9/f35+fkN
|
||||
DQ0NDQ0NDQ0JDQ0NDQ0NDZSUlA0MDAwMDw8PD4+ZnZUVERERGRkZDQ0NDQ0N
|
||||
DQ0NCQ0NDQ0NDQ2tra0NDAwMDA8PDw+HmZ2VHRkZGREREQ0NDQ0NDQ0NDQkN
|
||||
DQ0NDQ0NqqqqDQwMDAwPDw8Pn5mdlQUBAQEFBQUNDQ0NDQ0NDQ0JDQ0NDQ0N
|
||||
DaGhoQ0LCwsLCAgICJyZnZUBBQUFzc3NDQgICAgICAgIDA0NDQUFBQWwsLAN
|
||||
DAwMDA8PDw9TmJyUyM3NzcnJyQ0NDQ0NDQ0NDQkNDQ0JCQkJs7OzDQwMDAwP
|
||||
Dw8Pb5iclPTx8fHl5eUNDQ0NDQ0NDQ0JDQ0NCQkJCcrKyg0MDAwMDw8PD3uY
|
||||
nJTg5eXl6enpDQ0NDQ0NDQ0NCQ0NDQ0NDQ3ExMQNBQUFBQYGBgaGmJyUFBER
|
||||
ERUVFQ0NDQ0NDQ0NDQkNDQ0NDQ0Nw8PDDQwMDAwMDAwMDA0NDY2IiIiGh4cN
|
||||
DQ0NDQ0NDQ0MDQ0NDQ0NDRwcHA0ODg4ODg4ODg4NDQ2DhYWFUlJSDQ0NDQ0N
|
||||
DQ0NDA0NDQ0NDQ0MDAwNDw8PDw8PDw8PDQ0Nxc7Ozq6qqg0WFhYWOjo6Oj4N
|
||||
DQ0dHR0dFBQUDQ4ODg4ODg4ODg0NDSU1NTUBAwMNDQ0NDQ0NDQ0MDQ0NDQ0N
|
||||
DQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NGZicBQUFBQUGBgcHBw0NDSWkoKioqKgN
|
||||
Dg4MDAwMDAxEjIiAgICAgIODgA0NDQ0Nefj89PQNDQ0ODgoKCgoKDdlYXFRU
|
||||
VFRUVw0ICAgICAg6uLwFBQUFBQYGAAAADQ0NTc/Lw8PDww0ODgkJCQkJCWmP
|
||||
i4ODg4ODgICIDQ0NDQ1l5+Pr6w0NDQ4OBwcHBwcNdffz+/v7+/v4DQcHBwcH
|
||||
B5cVEQUFBQUFBgYNDQ0NDQ3NT0tDQ0NDDQ4OAgICAgICPomNhYWFhYWGhosN
|
||||
DQ0NDVXR1d3dDQ0NDg4AAAAAAA1x9fH5+fn5+foNAgICAgICghYSBQUFBQUG
|
||||
BhYWFg0NDYURFR0dHR0NDg4fHx8fHx+PmZ2VlZWVlZaWhA0NDQ0NmQ0JAQEN
|
||||
DQ0ODh0dHR0dDVHEwMjIyMjIyw0ZGRkZGRl57OgFBQUFBQYGExMTDQ0Neezo
|
||||
4ODg4A0ODhgYGBgYGJiYnJSUlJSUl5eADQ0NDQ0NDQ0NDQ0NDQ4OFhYWFhYN
|
||||
DQ0NDQ0NDQ0ODRQUFBQUFBQUFA0NDQ0NDg4UFBQNDQ0NDQ0NDQ0NDQ4OFRUU
|
||||
FBQU8I+Lg4ODg4OBgY0NHBwcHBwcHBwcDQ0NCQn4BxsbGw2NGR0VFRUVFRQN
|
||||
HR03Nzc3vysvBQUFBQUEBBUVLQ0NDZ0JDQUFBQUNDAweHltbW1snmJyUlJSU
|
||||
lJWVgw1ERERExFFVXVwNDQ0MDBsbTk5ODQWGgoqKioqKiA0BAWpqampW1dEF
|
||||
BQUFBQcHCwsaDQ0NDQ0NDQ0NDQ0JCfgHcHBwcPSZnZWVlZWVlJSEDYmJiYkF
|
||||
kZWdnQ0NDQwMHR2MjIwNcfXx+fn5+fn4DQICnZ2dnQ2ZnQUFBQUFBAQWFr0N
|
||||
DQ0VkZWdnZ2dDQ8PAwPCwsLCwg0NDQ0NDQ0JCfjyOjo6Oq46PjY2DQ0NHBwP
|
||||
D97e3g1V0dXd2dnZ2cgNAwPb29vbW8/LBQUFBQUVF+YZ8A0NDXXg5Ozs7OwN
|
||||
HB4ICP7+/v4qjoqCwMDAwNLS3g0LCgoKCgoKCqAMDAweHh4eCAkJDXX38/v7
|
||||
+/v76Q0HBxsaGhraWFwFBQUFBRcXGxs4DAwMjBgcFBQUFA0dH+4RJyYmJqaO
|
||||
ioLQ0NDQwsLODUtKSkrKX1tTUw0NDR0d7BNBQEANZebi6vLy8vLgDQEBVldX
|
||||
V1dXVw3Q0NDQwsLCwrYMDAyMGBwUFBQUDR0f7hGUlZWV4ZiclJSUlJS0tKIN
|
||||
nZycnKAkICgoDQ0NHx8SEoSFhQ2NGR0VFRUVFQUP/gGrqqqqKr+7BQUFBQUV
|
||||
FeQbqgwMDGz5/fX19fUNHBwJCc7Pz89LmJyUlJSUlISEdfI+Pz8/vysvJycN
|
||||
DQ0dH+4Rzs/PDVHV0dnd3d3dzA0DA+3s7OyYDQkFBQUFBRUVAwP4DAwMDAwM
|
||||
DAwMDA0tLS0tIiAgIKCZnZWVlZWVhYd28tfV1dXV1dXV1Q0NDS0tLS0tTi9h
|
||||
DVI1WDdZBnUBbB5qagl7D3wIfWsNI0BAH0ADVxhfAEwFVgJdAgJdUhZCDV8A
|
||||
TAVWAlINDVINRwRWCUVEF0McQ0MzHS0tbgFsHHAVYQRgTjw8YzxYN2gPYwxv
|
||||
DmI9WS1CMEMcbBlhYQd1FHkcQ2kccRxlZTplJnJCEE8KRABfAABfUhZCDV8A
|
||||
RQtPEFJSDVIURgdKD1BIBkIdQkIdQghLXwBFC08QT08QT2kGWT5SPV8+Ug1u
|
||||
GnUHdCtKP0dHeRxvGzVWVglNFEMCTwZFRRp8DFNlEhJNEnQdcxpFbB5sDXQr
|
||||
TiBERFINaRp1KkIjTSlhBARbBGgBYwBfbh1oN1E4Vj8/T3gMfz9/OHQ9fzxS
|
||||
YE5+fiFIJk87DVIhVTRGMjJtMmsCbAVaO0k7WiNSIVU0RjIybTJeZAZlOlkq
|
||||
XwBpB2QQEE8QcgFyLV55GGoeHnMSexUVUg1hCGoJViVRMH8LVDlYMV8fXxhB
|
||||
CEoJVmRKenolUjtVPEgXdgR2F3QrTiBERCBBNVRSIVU0RjIybQtiYwoKVQp6
|
||||
CG0EamQQTy5cLk82aQxjBwdYPVk4TC0tUhVZFlQVWQZJD0sYXQlWAkMBTQhS
|
||||
Ug1oBmJiPWILYwp+IUAyQCFYB34KaxltbTJ7NGt+Cm4HaTZDMFUxDVINaQh8
|
||||
HUIxRWweamo1fwlWBGFqA3AEYRNQPF0ufhtoaDdoGGoPZmMKfiFAMkAhWAd+
|
||||
CmsZbW0ybQpnYgxTIFQ1RzNsMw0=" alt="Santa's helpers binary" />
|
|
@ -0,0 +1 @@
|
|||
It is a lovely day outside
|
|
@ -0,0 +1,2 @@
|
|||
Recovery, while not strictly necessary, may be tremendously helpful.
|
||||
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
This is our world now... the world of the electron and the switch, the beauty of the baud.
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
Actually, Werner, we're all tickled to here you say that. Frankly, watchin' Donny beat Nazis to death is is the closest we ever get to goin' to the movies.
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
extra special text
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
Now think real hard. You been bird-doggin' this township awhile now. They wouldn't mind a corpse of you. Now, you can luxuriate in a nice jail cell, but if your hand touches metal, I swear by my pretty floral bonnet, I will end you.
|
|
@ -1,6 +1,8 @@
|
|||
#! /usr/bin/env python3
|
||||
|
||||
import cgi
|
||||
import time
|
||||
import os
|
||||
|
||||
f = cgi.FieldStorage()
|
||||
if f.getfirst('submit'):
|
||||
|
@ -8,6 +10,13 @@ if f.getfirst('submit'):
|
|||
print()
|
||||
print('Thanks for filling in the survey.')
|
||||
print()
|
||||
try:
|
||||
fn = '/var/lib/ctf/survey/%s.%d.%d.txt' % (time.strftime('%Y-%m-%d'), time.time(), os.getpid())
|
||||
o = open(fn, 'w')
|
||||
for k in f.keys():
|
||||
o.write('%s: %r\n' % (k, f.getlist(k)))
|
||||
except IOError:
|
||||
pass
|
||||
print('The key is:')
|
||||
print(' quux blorb frotz')
|
||||
else:
|
|
@ -0,0 +1,44 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE html PUBLIC
|
||||
"-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Survey</title>
|
||||
<link rel="stylesheet" href="%s" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<form method="post" action=",submit.cgi">
|
||||
<ul>
|
||||
<li>
|
||||
Did you have any trouble figuring out how to play?
|
||||
<select name="getting-started">
|
||||
<option>A lot of trouble</option>
|
||||
<option selected="selected">Not much trouble</option>
|
||||
<option>No trouble</option>
|
||||
</select>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
How difficult were the puzzles?
|
||||
<select name="puzzle-strength">
|
||||
<option>Too hard</option>
|
||||
<option selected="selected">About right</option>
|
||||
<option>Too easy</option>
|
||||
</select>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Please use the provided space for any additional comments.
|
||||
</p>
|
||||
<textarea name="comments" style="height: 5em; width: 40em;"></textarea>
|
||||
<p>
|
||||
Thanks for your feedback! We hope you had fun and learned
|
||||
something!
|
||||
</p>
|
||||
<input type="submit" name="submit" value="Submit survey" />
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -4,38 +4,7 @@
|
|||
recieve a key redeemable for <b>ONE MILLION POINTS</b>.
|
||||
</p>
|
||||
|
||||
<fieldset>
|
||||
<legend>Survey</legend>
|
||||
|
||||
<form method="post" action="submit.cgi">
|
||||
<ul>
|
||||
<li>
|
||||
Did you have any trouble figuring out how to play?
|
||||
<select name="getting-started">
|
||||
<option>A lot of trouble</option>
|
||||
<option selected="selected">Not much trouble</option>
|
||||
<option>No trouble</option>
|
||||
</select>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
How difficult were the puzzles?
|
||||
<select name="puzzle-strength">
|
||||
<option>Too hard</option>
|
||||
<option selected="selected">About right</option>
|
||||
<option>Too easy</option>
|
||||
</select>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Please use the provided space for any additional comments.
|
||||
</p>
|
||||
<textarea name="comments" style="height: 5em; width: 40em;"></textarea>
|
||||
<p>
|
||||
Thanks for your feedback! We hope you had fun and learned
|
||||
something!
|
||||
</p>
|
||||
<input type="submit" name="submit" value="Submit survey" />
|
||||
</form>
|
||||
</fieldset>
|
||||
<object data=",survey.html" type="text/html"
|
||||
style="width: 100%; height: 40em;">
|
||||
<a href=",survey.html">Survey</a>
|
||||
</object>
|
||||
|
|
|
@ -5,9 +5,9 @@ TARGET = $(CURDIR)/target
|
|||
FAKE = fakeroot -s $(CURDIR)/fake -i $(CURDIR)/fake
|
||||
INSTALL = $(FAKE) install
|
||||
|
||||
all: 99-pwnables.tce
|
||||
all: pwnables.tce
|
||||
|
||||
99-pwnables.tce: target
|
||||
pwnables.tce: target
|
||||
$(FAKE) sh -c 'cd target && tar -czf - --exclude=placeholder --exclude=*~ .' > $@
|
||||
|
||||
target:
|
||||
|
@ -17,13 +17,5 @@ target:
|
|||
|
||||
$(MAKE) -C daemons TARGET=$(TARGET) install
|
||||
|
||||
$(INSTALL) -d $(TARGET)/usr/lib/www
|
||||
$(INSTALL) $(CGI) $(TARGET)/usr/lib/www
|
||||
|
||||
$(INSTALL) -D flag $(TARGET)/var/lib/tftp/flag
|
||||
$(INSTALL) -D flag $(TARGET)/var/lib/notes/flag
|
||||
$(INSTALL) -D flag $(TARGET)/home/flag/.plan
|
||||
|
||||
|
||||
clean:
|
||||
rm -rf target
|
||||
rm -rf target pwnables.tce
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
all: in.fingerd
|
|
@ -1,38 +0,0 @@
|
|||
#include <stdio.h>
|
||||
|
||||
int
|
||||
main(int argc, char *argv)
|
||||
{
|
||||
char user[256];
|
||||
char path[512];
|
||||
char *data;
|
||||
FILE *f;
|
||||
size_t count;
|
||||
int i;
|
||||
|
||||
if (NULL == gets(user)) {
|
||||
return 0;
|
||||
}
|
||||
for (data = user; *data; data += 1) {
|
||||
if ('\r' == *data) {
|
||||
*data = 0;
|
||||
}
|
||||
}
|
||||
if (0 == user[0]) {
|
||||
printf("Nobody's home.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
sprintf(path, "/home/%s/.plan", user);
|
||||
f = fopen(path, "r");
|
||||
if (NULL == f) {
|
||||
printf("No such user.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
data = path;
|
||||
while (count = fread(data, sizeof(*data), 1, f)) {
|
||||
fwrite(data, count, 1, stdout);
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/sh
|
||||
|
||||
exec tcpsvd 0 79 /usr/sbin/in.fingerd
|
|
@ -0,0 +1 @@
|
|||
dirtbags
|
|
@ -0,0 +1 @@
|
|||
/var/lib/cat/flag
|
|
@ -0,0 +1 @@
|
|||
dirtbags
|
|
@ -0,0 +1 @@
|
|||
dirtbags
|
|
@ -0,0 +1 @@
|
|||
dirtbags
|
|
@ -0,0 +1,9 @@
|
|||
#! /bin/sh
|
||||
|
||||
# Busybox netcat doesn't support UDP unless you compile in desktop mode.
|
||||
# No problem, traceroute can send a UDP packet too.
|
||||
while true; do
|
||||
# Apparently traceroute adds 1 to the base port (-p)
|
||||
traceroute -m 2 -q 1 -p 8 10.0.0.1 2>/dev/null >/dev/null
|
||||
sleep 10
|
||||
done
|
|
@ -1,3 +0,0 @@
|
|||
#! /bin/sh
|
||||
|
||||
exec udpsvd 0 69 tftpd /var/lib/tftp
|
|
@ -0,0 +1,3 @@
|
|||
#! /bin/sh
|
||||
|
||||
exec logger -t ctfd
|
|
@ -3,12 +3,16 @@ INSTALL = $(FAKE) install -o 100
|
|||
|
||||
all: tanks.tce
|
||||
|
||||
push: tanks.tce
|
||||
netcat -l -q 0 -p 3333 < tanks.tce
|
||||
|
||||
tanks.tce: target
|
||||
$(FAKE) sh -c 'cd target && tar -czf - .' > $@
|
||||
|
||||
target:
|
||||
$(INSTALL) -d target/var/lib/tanks/
|
||||
$(INSTALL) -d target/var/lib/tanks/results/
|
||||
$(INSTALL) -d target/var/lib/tanks/errors/
|
||||
$(INSTALL) -d target/var/lib/tanks/ai/easy
|
||||
$(INSTALL) -d target/var/lib/tanks/ai/medium
|
||||
$(INSTALL) -d target/var/lib/tanks/ai/hard
|
||||
|
@ -17,16 +21,17 @@ target:
|
|||
$(INSTALL) AI/medium/* target/var/lib/tanks/ai/medium/
|
||||
$(INSTALL) AI/hard/* target/var/lib/tanks/ai/hard/
|
||||
|
||||
$(INSTALL) -d target/var/lib/www/tanks/
|
||||
$(INSTALL) www/* target/var/lib/www/tanks/
|
||||
$(FAKE) ln -s target/var/lib/tanks/ target/var/lib/www/data
|
||||
$(INSTALL) -d target/usr/lib/www/tanks/
|
||||
$(INSTALL) www/* target/usr/lib/www/tanks/
|
||||
|
||||
ln -s /var/lib/tanks/results target/usr/lib/www/tanks/results
|
||||
|
||||
$(INSTALL) -d target/usr/lib/python2.6/site-packages/tanks/
|
||||
$(INSTALL) lib/* target/usr/lib/python2.6/site-packages/tanks/
|
||||
|
||||
$(INSTALL) -d target/var/service/tanks
|
||||
$(INSTALL) run target/var/service/tanks/run
|
||||
|
||||
$(INSTALL) run run_tanks.py target/var/service/tanks/
|
||||
|
||||
$(INSTALL) -d target/var/service/tanks/log/
|
||||
$(INSTALL) log.run target/var/service/tanks/log/run
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ def displacePoly(points, disp, limits, coordSequence=False):
|
|||
maxX, maxY = limits
|
||||
basePoints = []
|
||||
for point in points:
|
||||
x,y = point[0] + disp[0], point[1] + disp[1]
|
||||
x,y = int(point[0] + disp[0]), int(point[1] + disp[1])
|
||||
|
||||
# Check if duplication is needed on each axis
|
||||
if x > maxX:
|
||||
|
|
|
@ -9,19 +9,12 @@ from urllib import unquote, quote
|
|||
|
||||
from PIL import Image, ImageColor, ImageDraw
|
||||
|
||||
try:
|
||||
from ctf import teams
|
||||
except:
|
||||
import sys
|
||||
path = '/home/pflarr/repos/gctf/'
|
||||
sys.path.append(path)
|
||||
from ctf import teams
|
||||
teams.build_teams()
|
||||
|
||||
import Tank
|
||||
|
||||
class Pflanzarr:
|
||||
|
||||
TEAMS_FILE = '/var/lib/ctf/passwd'
|
||||
|
||||
FRAME_DELAY = 15
|
||||
|
||||
SPACING = 150
|
||||
|
@ -42,12 +35,14 @@ class Pflanzarr:
|
|||
if not os.path.exists(self._gameDir):
|
||||
os.mkdir(self._gameDir)
|
||||
|
||||
colors = self._getColors()
|
||||
|
||||
tmpPlayers = os.listdir(self._playerDir)
|
||||
players = []
|
||||
for p in tmpPlayers:
|
||||
p = unquote(p)
|
||||
if not (p.startswith('.') or p.endswith('#') or p.endswith('~'))\
|
||||
and p in teams.teams:
|
||||
and p in colors:
|
||||
players.append(p)
|
||||
|
||||
AIs = {}
|
||||
|
@ -73,7 +68,7 @@ class Pflanzarr:
|
|||
self._board = (cols*self.SPACING, rows*self.SPACING)
|
||||
|
||||
while len(players) < cols*rows:
|
||||
players.append('#default')
|
||||
players.append(None)
|
||||
|
||||
self._tanks = []
|
||||
for i in range(cols):
|
||||
|
@ -82,13 +77,13 @@ class Pflanzarr:
|
|||
startY = j*self.SPACING + self.SPACING/2
|
||||
player = random.choice(players)
|
||||
players.remove(player)
|
||||
if player == '#default':
|
||||
if player == None:
|
||||
color = '#a0a0a0'
|
||||
else:
|
||||
color = '#%s' % teams.teams[player][1]
|
||||
color = colors[player]
|
||||
tank = Tank.Tank( player, (startX, startY), color,
|
||||
self._board, testMode=True)
|
||||
if player == '#default':
|
||||
if player == None:
|
||||
tank.program(random.choice(defaultAIs))
|
||||
else:
|
||||
tank.program(AIs[player])
|
||||
|
@ -156,10 +151,12 @@ class Pflanzarr:
|
|||
if tank in kills[tank]:
|
||||
kills[tank].remove(tank)
|
||||
|
||||
self._saveResults(kills)
|
||||
for tank in self._tanks:
|
||||
self._outputErrors(tank)
|
||||
self._makeMovie()
|
||||
# This needs to go after _makeMovie; the web scripts look for these
|
||||
# files to see if the game has completed.
|
||||
self._saveResults(kills)
|
||||
|
||||
def _killTanks(self, tanks, reason):
|
||||
for tank in tanks:
|
||||
|
@ -204,22 +201,32 @@ class Pflanzarr:
|
|||
break
|
||||
winner = random.choice(winners)
|
||||
|
||||
html = ['<html><body>',
|
||||
html = ['<html>',
|
||||
'<head><title>Game %d results</title>',
|
||||
'<link href="/ctf.css" rel="stylesheet" type="text/css">',
|
||||
'</head>',
|
||||
'<body>',
|
||||
'<table><tr><th>Team<th>Kills<th>Cause of Death']
|
||||
for tank in tanks:
|
||||
if tank is winner:
|
||||
rowStyle = 'style="color:red;"'
|
||||
rowStyle = 'style="font-weight:bold; '\
|
||||
'background-color:%s"' % tank.color
|
||||
else:
|
||||
rowStyle = ''
|
||||
rowStyle = 'style="background-color:%s"' % tank.color
|
||||
if tank.name:
|
||||
name = xml.sax.saxutils.escape(tank.name)
|
||||
else:
|
||||
name = '#default'
|
||||
html.append('<tr %s><td>%s<td>%d<td>%s' %
|
||||
(rowStyle,
|
||||
xml.sax.saxutils.escape(tank.name),
|
||||
name,
|
||||
len(kills[tank]),
|
||||
xml.sax.saxutils.escape(tank.deathReason)))
|
||||
|
||||
html.append('</table><body></html>')
|
||||
|
||||
if winner.name != '#default':
|
||||
# Write a blank file if the winner is a default tank..
|
||||
if winner.name != None:
|
||||
winnerFile.write(tanks[0].name)
|
||||
winnerFile.close()
|
||||
|
||||
|
@ -243,14 +250,14 @@ class Pflanzarr:
|
|||
clearFrames = ['rm', '-rf', '%s' % self._imageDir]
|
||||
|
||||
print 'Making Movie'
|
||||
subprocess.call(movieCmd)
|
||||
# subprocess.call(movieCmd, stderr=open('/dev/null', 'w'),
|
||||
# stdout=open('/dev/null', 'w'))
|
||||
# subprocess.call(movieCmd)
|
||||
subprocess.call(movieCmd, stderr=open('/dev/null', 'w'),
|
||||
stdout=open('/dev/null', 'w'))
|
||||
subprocess.call(clearFrames)
|
||||
|
||||
def _outputErrors(self, tank):
|
||||
"""Output errors for each team."""
|
||||
if tank.name == '#default':
|
||||
if tank.name == None:
|
||||
return
|
||||
|
||||
if tank._program.errors:
|
||||
|
@ -378,7 +385,27 @@ class Pflanzarr:
|
|||
defaultAIs.append( file.read() )
|
||||
|
||||
return defaultAIs
|
||||
|
||||
|
||||
def _getColors(self):
|
||||
"""Get the team colors from the passwd file. The passwd file location
|
||||
is set by self.TEAMS_FILE. Returns a dictionary of players->color"""
|
||||
errorColor = '#ffffff'
|
||||
|
||||
try:
|
||||
file = open(self.TEAMS_FILE)
|
||||
except:
|
||||
return {}.fromkeys(players, errorColor)
|
||||
|
||||
colors = {}
|
||||
for line in file:
|
||||
try:
|
||||
team, passwd, color = map(unquote, line.split('\t'))
|
||||
colors[team] = '#%s' % color
|
||||
except:
|
||||
colors[team] = errorColor
|
||||
|
||||
return colors
|
||||
|
||||
def _getGameNum(self):
|
||||
"""Figure out what game number this is from the past games played."""
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ class Tank(object):
|
|||
else:
|
||||
self._tAngle = tAngle
|
||||
|
||||
self._color = color
|
||||
self.color = color
|
||||
|
||||
# You can't fire until fireReady is 0.
|
||||
self._fireReady = self.FIRE_RATE
|
||||
|
@ -466,7 +466,7 @@ class Tank(object):
|
|||
|
||||
# The base body rectangle.
|
||||
for poly in gm.displacePoly(hood, self.pos, self._limits):
|
||||
d.polygon( poly, fill=self._color )
|
||||
d.polygon( poly, fill=self.color )
|
||||
|
||||
# The treads
|
||||
for poly in gm.displacePoly(tread1, self.pos, self._limits) + \
|
||||
|
@ -475,7 +475,7 @@ class Tank(object):
|
|||
|
||||
# The turret circle
|
||||
for poly in gm.displacePoly(self.body, self.pos, self._limits):
|
||||
d.ellipse( poly, fill=self._color, outline='black')
|
||||
d.ellipse( poly, fill=self.color, outline='black')
|
||||
|
||||
self._drawLaser(d)
|
||||
|
||||
|
@ -491,7 +491,7 @@ class Tank(object):
|
|||
if self._fired:
|
||||
laser = gm.rotatePoly( self.laser, self._angle + self._tAngle )
|
||||
for poly in gm.displacePoly(laser, self.pos, self._limits):
|
||||
drawing.polygon(poly, fill=self._color)
|
||||
drawing.polygon(poly, fill=self.color)
|
||||
|
||||
self._fired = False
|
||||
|
||||
|
@ -522,7 +522,7 @@ class Tank(object):
|
|||
if self._sensorState[i]:
|
||||
color = '#000000'
|
||||
else:
|
||||
color = self._color
|
||||
color = self.color
|
||||
|
||||
r, angle, width, tAttached = self._sensors[i]
|
||||
r = int(r)
|
||||
|
|
|
@ -2,5 +2,5 @@
|
|||
|
||||
[ -f /var/lib/ctf/disabled/tanks ] && exit 0
|
||||
|
||||
envuidgid ctf python2.6 run_tanks.py /var/lib/tanks/ easy 100 &
|
||||
envuidgid ctf report_score.py
|
||||
exec envuidgid ctf python2.6 run_tanks.py /var/lib/tanks/ easy 100 2>&1
|
||||
#envuidgid ctf report_score.py 2>&1
|
||||
|
|
|
@ -1,20 +1,93 @@
|
|||
#! /usr/bin/python
|
||||
|
||||
import asynchat
|
||||
import asyncore
|
||||
import optparse
|
||||
import os
|
||||
import shutil
|
||||
import socket
|
||||
import time
|
||||
from tanks import Pflanzarr
|
||||
import sys
|
||||
|
||||
T = 60*5
|
||||
MAX_HIST = 30
|
||||
HIST_STEP = 100
|
||||
key = 'tanks:::2bac5e912ff2e1ad559b177eb5aeecca'
|
||||
|
||||
try:
|
||||
while 1:
|
||||
start = time.time()
|
||||
p = Pflanzarr(sys.argv[1], sys.argv[2])
|
||||
p.run(int(sys.argv[3]))
|
||||
|
||||
diff = time.time() - start
|
||||
if diff - T > 0:
|
||||
time.sleep( diff - T )
|
||||
class Flagger(asynchat.async_chat):
|
||||
"""Use to connect to flagd and submit the current flag holder."""
|
||||
|
||||
except:
|
||||
print 'Usage: python2.6 run_tanks.py data_dir easy|medium|hard max_turns'
|
||||
def __init__(self, addr, auth):
|
||||
asynchat.async_chat.__init__(self)
|
||||
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.connect((addr, 6668))
|
||||
self.push(auth + '\n')
|
||||
self.flag = None
|
||||
|
||||
|
||||
def handle_read(self):
|
||||
msg = self.recv(4096)
|
||||
raise ValueError("Flagger died: %r" % msg)
|
||||
|
||||
def handle_error(self):
|
||||
# If we lose the connection to flagd, nobody can score any
|
||||
# points. Terminate everything.
|
||||
asyncore.close_all()
|
||||
asynchat.async_chat.handle_error(self)
|
||||
|
||||
def set_flag(self, team):
|
||||
if team:
|
||||
eteam = team
|
||||
else:
|
||||
eteam = ''
|
||||
self.push(eteam + '\n')
|
||||
self.flag = team
|
||||
|
||||
|
||||
def run_tanks(args, turns, flagger):
|
||||
p = Pflanzarr.Pflanzarr(args[0], args[1])
|
||||
p.run(turns)
|
||||
|
||||
path = os.path.join(args[0], 'results')
|
||||
files = os.listdir(path)
|
||||
gameNums = []
|
||||
for file in files:
|
||||
try:
|
||||
gameNums.append( int(file) )
|
||||
except:
|
||||
continue
|
||||
|
||||
gameNums.sort(reverse=True)
|
||||
highest = gameNums[0]
|
||||
for num in gameNums:
|
||||
if highest - MAX_HIST > num and not (num % HIST_STEP == 0):
|
||||
shutil.rmtree(os.path.join(path, str(num)))
|
||||
|
||||
try:
|
||||
winner = open('/var/lib/tanks/winner').read().strip()
|
||||
except:
|
||||
winner = None
|
||||
flagger.set_flag(winner)
|
||||
|
||||
|
||||
def main():
|
||||
parser = optparse.OptionParser('DATA_DIR easy|medium|hard MAX_TURNS')
|
||||
opts, args = parser.parse_args()
|
||||
if (len(args) != 3) or (args[1] not in ('easy', 'medium', 'hard')):
|
||||
parser.error('Wrong number of arguments')
|
||||
try:
|
||||
turns = int(args[2])
|
||||
except:
|
||||
parser.error('Invalid number of turns')
|
||||
|
||||
|
||||
flagger = Flagger('localhost', key)
|
||||
lastrun = 0
|
||||
while True:
|
||||
asyncore.loop(60, count=1)
|
||||
now = time.time()
|
||||
if now - lastrun >= 60:
|
||||
run_tanks(args, turns, flagger)
|
||||
lastrun = now
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
import sys
|
||||
|
||||
print >> sys.stderr, 'hello'
|
|
@ -7,7 +7,7 @@ import os
|
|||
import sys
|
||||
|
||||
try:
|
||||
from Tanks import Program, setup, conditions, actions, docs
|
||||
from tanks import Program, setup, conditions, actions, docs
|
||||
except:
|
||||
path = os.getcwd().split('/')
|
||||
path.pop()
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
#!/usr/bin/python
|
||||
#!/usr/bin/python3
|
||||
|
||||
print """Content-Type: text/html\n\n"""
|
||||
print """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN">\n\n"""
|
||||
print("""Content-Type: text/html\n\n""")
|
||||
print("""<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN">\n\n""")
|
||||
import cgi
|
||||
import cgitb; cgitb.enable()
|
||||
import sys
|
||||
import os
|
||||
|
||||
import Config
|
||||
|
@ -16,18 +17,17 @@ except:
|
|||
try:
|
||||
from ctf import teams
|
||||
except:
|
||||
import sys
|
||||
path = '/home/pflarr/repos/gctf/'
|
||||
sys.path.append(path)
|
||||
from ctf import teams
|
||||
teams.build_teams()
|
||||
|
||||
head = open('head.html').read() % "Error Report"
|
||||
print head
|
||||
print open('links.html').read()
|
||||
print(head)
|
||||
print(open('links.html').read())
|
||||
|
||||
def done():
|
||||
print '</body></html>'
|
||||
print('</body></html>')
|
||||
sys.exit(0)
|
||||
|
||||
fields = cgi.FieldStorage()
|
||||
|
@ -38,25 +38,25 @@ if team and passwd and \
|
|||
path = os.path.join(Config.DATA_PATH, 'errors', quote(team))
|
||||
if os.path.isfile(path):
|
||||
errors = open(path).readlines()
|
||||
print '<p>Your latest errors:'
|
||||
print '<div class=errors>'
|
||||
print('<p>Your latest errors:')
|
||||
print('<div class=errors>')
|
||||
if errors:
|
||||
print '<BR>\n'.join(errors)
|
||||
print('<BR>\n'.join(errors))
|
||||
else:
|
||||
print 'There were no errors.'
|
||||
print '</div>'
|
||||
print('There were no errors.')
|
||||
print('</div>')
|
||||
else:
|
||||
print '<p>No error file found.'
|
||||
print('<p>No error file found.')
|
||||
|
||||
done()
|
||||
|
||||
if team and team not in teams.teams:
|
||||
print '<p>Invalid team.'
|
||||
print('<p>Invalid team.')
|
||||
|
||||
if team and team in teams.teams and passwd != teams.teams[team][0]:
|
||||
print '<p>Invalid password.'
|
||||
print('<p>Invalid password.')
|
||||
|
||||
print '''
|
||||
print('''
|
||||
<form action="errors.cgi" method="get">
|
||||
<fieldset>
|
||||
<legend>Error report request:</legend>
|
||||
|
@ -64,6 +64,6 @@ print '''
|
|||
Password: <input type="text" name="passwd"><BR>
|
||||
<button type="get my errors">Submit</button>
|
||||
</fieldset>
|
||||
</form>'''
|
||||
</form>''')
|
||||
|
||||
done()
|
||||
|
|
|
@ -28,22 +28,28 @@ except:
|
|||
|
||||
if not games:
|
||||
print "<p>No games have occurred yet."
|
||||
|
||||
gameNums = []
|
||||
for game in games:
|
||||
try:
|
||||
num = int(game)
|
||||
path = os.path.join( 'results', game, 'results.html')
|
||||
if os.path.exists( path ):
|
||||
gameNums.append( int(num) )
|
||||
else:
|
||||
continue
|
||||
|
||||
gameNums.append( int(game) )
|
||||
except:
|
||||
continue
|
||||
|
||||
gameNums.sort(reverse=True)
|
||||
|
||||
# Don't include games that haven't completed
|
||||
i = 0
|
||||
num = str(gameNums[i])
|
||||
for i in range(len(gameNums)):
|
||||
path = os.path.join( 'results', str(gameNums[i]), 'results.html') )
|
||||
if os.path.exists( path ):
|
||||
break
|
||||
gameNums = gameNums[i:]
|
||||
|
||||
for num in gameNums:
|
||||
print '<p>%d - ' % num,
|
||||
print '<a href="results/%d/game.avi">v</a>' % num,
|
||||
print '<a href="results/%d/results.html">r</a>' % num
|
||||
|
||||
print '</body></html>'
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
#!/usr/bin/python
|
||||
#!/usr/bin/python3
|
||||
|
||||
print("Content-Type: text/html\n\n")
|
||||
print("""<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN">\n\n""")
|
||||
import cgi
|
||||
import cgitb; cgitb.enable()
|
||||
import os
|
||||
import sys
|
||||
|
||||
import Config
|
||||
|
||||
|
@ -14,21 +17,18 @@ except:
|
|||
try:
|
||||
from ctf import teams
|
||||
except:
|
||||
import sys
|
||||
path = '/home/pflarr/repos/gctf/'
|
||||
sys.path.append(path)
|
||||
from ctf import teams
|
||||
teams.build_teams()
|
||||
|
||||
print """Content-Type: text/html\n\n"""
|
||||
print """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN">\n\n"""
|
||||
head = open('head.html').read() % "Submission Results"
|
||||
print head
|
||||
print "<H1>Results</H1>"
|
||||
print open('links.html').read()
|
||||
print(head)
|
||||
print("<H1>Results</H1>")
|
||||
print(open('links.html').read())
|
||||
|
||||
def done():
|
||||
print '</body></html>'
|
||||
print('</body></html>')
|
||||
sys.exit(0)
|
||||
|
||||
fields = cgi.FieldStorage()
|
||||
|
@ -36,21 +36,23 @@ team = fields.getfirst('team', '').strip()
|
|||
passwd = fields.getfirst('passwd', '').strip()
|
||||
code = fields.getfirst('code', '')
|
||||
if not team:
|
||||
print '<p>No team specified'; done()
|
||||
print('<p>No team specified'); done()
|
||||
elif not passwd:
|
||||
print '<p>No password given'; done()
|
||||
print('<p>No password given'); done()
|
||||
elif not code:
|
||||
print '<p>No program given.'; done()
|
||||
print('<p>No program given.'); done()
|
||||
|
||||
if team not in teams.teams:
|
||||
print '<p>Team is not registered.'; done()
|
||||
print('<p>Team is not registered.'); done()
|
||||
|
||||
if passwd != teams.teams[team][0]:
|
||||
print '<p>Invalid password.'; done()
|
||||
print('<p>Invalid password.'); done()
|
||||
|
||||
path = os.path.join(Config.DATA_PATH, 'ai/players', encode(team) )
|
||||
path = os.path.join(Config.DATA_PATH, 'ai/players', quote(team) )
|
||||
file = open(path, 'w')
|
||||
file.write(code)
|
||||
file.close()
|
||||
|
||||
print("<P>Submission Successful")
|
||||
|
||||
done()
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
FAKE = fakeroot -s fake -i fake
|
||||
INSTALL = $(FAKE) install -o 100
|
||||
|
||||
all: tanksFlagger.tce
|
||||
|
||||
push: tanksFlagger.tce
|
||||
netcat -l -q 0 -p 3333 < tanksFlagger.tce
|
||||
|
||||
tanksFlagger.tce: target
|
||||
$(FAKE) sh -c 'cd target && tar -czf - .' > $@
|
||||
|
||||
target:
|
||||
$(INSTALL) -d target/var/service/tanksFlagger
|
||||
$(INSTALL) run report_score.py target/var/service/tanksFlagger/
|
||||
|
||||
$(INSTALL) -d target/var/service/tanksFlagger/log/
|
||||
$(INSTALL) log.run target/var/service/tanksFlagger/log/run
|
||||
|
||||
clean:
|
||||
rm -rf target tanksFlagger.tce fake
|
|
@ -0,0 +1,3 @@
|
|||
#! /bin/sh
|
||||
|
||||
exec logger -t tanksFlagger
|
|
@ -0,0 +1,5 @@
|
|||
#! /bin/sh
|
||||
|
||||
[ -f /var/lib/ctf/disabled/tanks ] && exit 0
|
||||
|
||||
exec envuidgid ctf python3 report_score.py 2>&1
|
Loading…
Reference in New Issue