Merge branch 'master' of ssh://cfl.lanl.gov/var/projects/gctf
4
Makefile
|
@ -26,6 +26,10 @@ target: $(PYC)
|
||||||
$(INSTALL) -d $(PYCDIR)/ctf
|
$(INSTALL) -d $(PYCDIR)/ctf
|
||||||
$(INSTALL) $(PYC) $(PYCDIR)/ctf
|
$(INSTALL) $(PYC) $(PYCDIR)/ctf
|
||||||
|
|
||||||
|
$(INSTALL) -d $(DESTDIR)/usr/lib/python2.6/site-packages/ctf
|
||||||
|
$(INSTALL) ctf/__init__.py $(DESTDIR)/usr/lib/python2.6/site-packages/ctf
|
||||||
|
$(INSTALL) ctf/config.py $(DESTDIR)/usr/lib/python2.6/site-packages/ctf
|
||||||
|
|
||||||
$(INSTALL) -d $(DESTDIR)/usr/sbin
|
$(INSTALL) -d $(DESTDIR)/usr/sbin
|
||||||
$(INSTALL) ctfd.py $(DESTDIR)/usr/sbin
|
$(INSTALL) ctfd.py $(DESTDIR)/usr/sbin
|
||||||
$(INSTALL) new-contest $(DESTDIR)/usr/sbin
|
$(INSTALL) new-contest $(DESTDIR)/usr/sbin
|
||||||
|
|
91
ctf.css
|
@ -7,7 +7,7 @@ html {
|
||||||
body {
|
body {
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
margin: 50px 0 0 100px;
|
margin: 50px 0 0 110px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
max-width: 700px;
|
max-width: 700px;
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,54 @@ h1:first-child:before {
|
||||||
content: "Capture The Flag: ";
|
content: "Capture The Flag: ";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*** left side bar ***/
|
||||||
|
|
||||||
|
#navigation {
|
||||||
|
position: absolute;
|
||||||
|
background: #222;
|
||||||
|
opacity: 0.9;
|
||||||
|
top: 80px;
|
||||||
|
left: 0px;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation h3 {
|
||||||
|
font-size: 100%;
|
||||||
|
border-bottom: 2px solid #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation li a {
|
||||||
|
display: block;
|
||||||
|
height: 25px;
|
||||||
|
width: 90px;
|
||||||
|
padding: 5px;
|
||||||
|
margin: 5px;
|
||||||
|
background: inherit;
|
||||||
|
border-right: 4px solid #444;
|
||||||
|
color: #999;
|
||||||
|
text-transform: lowercase;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation li a:hover {
|
||||||
|
color: #f4f4f4;
|
||||||
|
background: #333;
|
||||||
|
border-right: 4px solid #2a2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation li .active {
|
||||||
|
color: #999;
|
||||||
|
background: #333;
|
||||||
|
border-right: 4px solid #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**** body ****/
|
/**** body ****/
|
||||||
|
|
||||||
a img {
|
a img {
|
||||||
|
@ -64,6 +112,39 @@ th, td {
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
line-height: 1.4em;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
color: #f4f4f4;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: 1px solid #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
dt {
|
||||||
|
white-space: pre;
|
||||||
|
background-color: #333;
|
||||||
|
padding: 5px;
|
||||||
|
border: 2px solid green;
|
||||||
|
border-bottom: none;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd {
|
||||||
|
border: 2px solid green;
|
||||||
|
margin: 0px;
|
||||||
|
padding: 5px;
|
||||||
|
background-color: #282828;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**** special cases ****/
|
||||||
|
|
||||||
|
.wide {
|
||||||
|
max-width: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
.scoreboard {
|
.scoreboard {
|
||||||
background: #222;
|
background: #222;
|
||||||
}
|
}
|
||||||
|
@ -72,12 +153,6 @@ th, td {
|
||||||
height: 400px;
|
height: 400px;
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
|
||||||
line-height: 1.4em;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
color: #f4f4f4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.solved {
|
.solved {
|
||||||
text-decoration: line-through;
|
text-decoration: line-through;
|
||||||
}
|
}
|
||||||
|
@ -93,3 +168,5 @@ table.pollster td {
|
||||||
table.pollster thead {
|
table.pollster thead {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,8 +28,10 @@ if 'home' in os.environ.get('SCRIPT_FILENAME', ''):
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
# An actual installation
|
# An actual installation
|
||||||
config = {'global':
|
config = {
|
||||||
{'data_dir': '/var/lib/ctf',
|
'global':
|
||||||
|
{
|
||||||
|
'data_dir': '/var/lib/ctf',
|
||||||
'base_url': '/',
|
'base_url': '/',
|
||||||
'css_url': '/ctf.css',
|
'css_url': '/ctf.css',
|
||||||
'disabled_dir': '/var/lib/ctf/disabled',
|
'disabled_dir': '/var/lib/ctf/disabled',
|
||||||
|
@ -37,13 +39,17 @@ else:
|
||||||
'house_team': 'dirtbags',
|
'house_team': 'dirtbags',
|
||||||
'passwd': '/var/lib/ctf/passwd',
|
'passwd': '/var/lib/ctf/passwd',
|
||||||
'team_colors': team_colors,
|
'team_colors': team_colors,
|
||||||
|
},
|
||||||
|
'pollster':
|
||||||
|
{
|
||||||
'poll_interval': 60,
|
'poll_interval': 60,
|
||||||
'poll_timeout': 0.5,
|
'poll_timeout': 0.5,
|
||||||
'heartbeat_dir': '/var/lib/pollster',
|
'heartbeat_dir': '/var/lib/pollster',
|
||||||
'poll_dir': '/var/lib/www',
|
'results': '/var/lib/pollster/status.html',
|
||||||
},
|
},
|
||||||
'puzzler':
|
'puzzler':
|
||||||
{'dir': '/usr/lib/www/puzzler',
|
{
|
||||||
|
'dir': '/usr/lib/www/puzzler',
|
||||||
'cgi_url': '/puzzler.cgi',
|
'cgi_url': '/puzzler.cgi',
|
||||||
'base_url': '/puzzler',
|
'base_url': '/puzzler',
|
||||||
'keys_file': '/usr/lib/ctf/puzzler.keys',
|
'keys_file': '/usr/lib/ctf/puzzler.keys',
|
||||||
|
@ -71,22 +77,45 @@ def datafile(filename):
|
||||||
def url(path):
|
def url(path):
|
||||||
return base_url + path
|
return base_url + path
|
||||||
|
|
||||||
def start_html(title):
|
def start_html(title, hdr='', cls='', links=[], links_title=None):
|
||||||
|
ret = []
|
||||||
if os.environ.get('GATEWAY_INTERFACE'):
|
if os.environ.get('GATEWAY_INTERFACE'):
|
||||||
print('Content-type: text/html')
|
ret.append('Content-type: text/html')
|
||||||
print()
|
ret.append('')
|
||||||
print('''<?xml version="1.0" encoding="UTF-8"?>
|
ret.append('''<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE html PUBLIC
|
<!DOCTYPE html PUBLIC
|
||||||
"-//W3C//DTD XHTML 1.0 Strict//EN"
|
"-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
<head>
|
<head>
|
||||||
<title>%s</title>
|
<title>%(title)s</title>
|
||||||
<link rel="stylesheet" href="%s" type="text/css" />
|
<link rel="stylesheet" href="%(css)s" type="text/css" />
|
||||||
|
%(hdr)s
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body class="%(class)s">
|
||||||
<h1>%s</h1>
|
<h1>%(title)s</h1>
|
||||||
''' % (title, css, title))
|
<div id="navigation">
|
||||||
|
<ul>
|
||||||
|
<li><a href="%(base)sintro.html">Intro/Rules</a></li>
|
||||||
|
<li><a href="%(base)sservices.html">Svc flags</a></li>
|
||||||
|
<li><a href="%(base)stanks/results.cgi">Tanks</a></li>
|
||||||
|
<li><a href="%(base)spuzzler.cgi">Puzzles</a></li>
|
||||||
|
<li><a href="%(base)sscoreboard.cgi">Scoreboard</a></li>
|
||||||
|
</ul>
|
||||||
|
''' % {'title': title,
|
||||||
|
'css': css,
|
||||||
|
'hdr': hdr,
|
||||||
|
'base': base_url,
|
||||||
|
'class': cls})
|
||||||
|
if links:
|
||||||
|
if links_title:
|
||||||
|
ret.append('<h3>%s</h3>' % links_title)
|
||||||
|
else:
|
||||||
|
ret.append('<hr/>')
|
||||||
|
for url, name in links:
|
||||||
|
ret.append('<li><a href="%s">%s</a></li>' % (url, name))
|
||||||
|
ret.append(' </div>')
|
||||||
|
return '\n'.join(ret)
|
||||||
|
|
||||||
def end_html():
|
def end_html():
|
||||||
print('</body></html>')
|
return '</body></html>'
|
||||||
|
|
|
@ -59,12 +59,13 @@ set xtics nomirror
|
||||||
set ytics nomirror
|
set ytics nomirror
|
||||||
set nokey
|
set nokey
|
||||||
set terminal png transparent size 640,200 x000000 xffffff
|
set terminal png transparent size 640,200 x000000 xffffff
|
||||||
set output "%(pngout)s"
|
set output "%(pngout)s,tmp"
|
||||||
plot %(plot)s\n''' % {'plot': ','.join(plotparts),
|
plot %(plot)s\n''' % {'plot': ','.join(plotparts),
|
||||||
'pngout': pngout})
|
'pngout': pngout})
|
||||||
instructions.flush()
|
instructions.flush()
|
||||||
|
|
||||||
gp = os.system('gnuplot %s 2>/dev/null </dev/null' % instructions.name)
|
gp = os.system('gnuplot %s 2>/dev/null </dev/null' % instructions.name)
|
||||||
|
os.rename("%s,tmp" % pngout, pngout)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -66,9 +66,10 @@ def start_html(title):
|
||||||
if passwd:
|
if passwd:
|
||||||
c['passwd'] = passwd
|
c['passwd'] = passwd
|
||||||
print(c)
|
print(c)
|
||||||
config.start_html(title)
|
print(config.start_html(title))
|
||||||
|
|
||||||
end_html = config.end_html
|
def end_html():
|
||||||
|
print(config.end_html())
|
||||||
|
|
||||||
def safe_join(*args):
|
def safe_join(*args):
|
||||||
safe = list(args[:1])
|
safe = list(args[:1])
|
||||||
|
@ -156,7 +157,7 @@ def main():
|
||||||
# Show available puzzles in category
|
# Show available puzzles in category
|
||||||
show_puzzles(cat, cat_dir)
|
show_puzzles(cat, cat_dir)
|
||||||
else:
|
else:
|
||||||
thekey = get_key(cat, points)
|
thekeys = get_key(cat, points)
|
||||||
if not teams.chkpasswd(team, passwd):
|
if not teams.chkpasswd(team, passwd):
|
||||||
start_html('Wrong password')
|
start_html('Wrong password')
|
||||||
end_html()
|
end_html()
|
||||||
|
|
|
@ -7,26 +7,7 @@ import string
|
||||||
from . import teams
|
from . import teams
|
||||||
from . import config
|
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():
|
def main():
|
||||||
print('Content-type: text/html')
|
|
||||||
print()
|
|
||||||
|
|
||||||
f = cgi.FieldStorage()
|
f = cgi.FieldStorage()
|
||||||
|
|
||||||
team = f.getfirst('team', '')
|
team = f.getfirst('team', '')
|
||||||
|
|
|
@ -15,20 +15,8 @@ def main():
|
||||||
|
|
||||||
categories = [(cat, s.cat_points(cat)) for cat in s.categories()]
|
categories = [(cat, s.cat_points(cat)) for cat in s.categories()]
|
||||||
|
|
||||||
print('Content-type: text/html')
|
|
||||||
print('Refresh: 10')
|
print('Refresh: 10')
|
||||||
print()
|
print(config.start_html('Scoreboard', cls='wide'))
|
||||||
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" xml:lang="en" lang="en">
|
|
||||||
<head>
|
|
||||||
<title>Scoreboard</title>
|
|
||||||
<link rel="stylesheet" href="%sctf.css" type="text/css" />
|
|
||||||
</head>
|
|
||||||
<body style="max-width: inherit;">
|
|
||||||
<h1>Scoreboard</h1>
|
|
||||||
''' % config.base_url)
|
|
||||||
print('<table class="scoreboard">')
|
print('<table class="scoreboard">')
|
||||||
print('<tr>')
|
print('<tr>')
|
||||||
print('<th>Overall</th>')
|
print('<th>Overall</th>')
|
||||||
|
@ -71,9 +59,8 @@ def main():
|
||||||
<p class="histogram">
|
<p class="histogram">
|
||||||
<img src="histogram.png" alt="scores over time" />
|
<img src="histogram.png" alt="scores over time" />
|
||||||
</p>
|
</p>
|
||||||
|
''')
|
||||||
</body>
|
print(config.end_html())
|
||||||
</html>''')
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
11
ctfd.py
|
@ -20,13 +20,12 @@ def chart(s):
|
||||||
def reap():
|
def reap():
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
os.waitpid(0, os.WNOHANG)
|
pid, ret = os.waitpid(0, os.WNOHANG)
|
||||||
|
if not pid:
|
||||||
|
break
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def sigchld(signum, frame):
|
|
||||||
do_reap = True
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
p = optparse.OptionParser()
|
p = optparse.OptionParser()
|
||||||
p.add_option('-p', '--genpass', dest='cat', default=None,
|
p.add_option('-p', '--genpass', dest='cat', default=None,
|
||||||
|
@ -39,13 +38,11 @@ def main():
|
||||||
pointsrv = pointsd.start()
|
pointsrv = pointsd.start()
|
||||||
flagsrv = flagd.start()
|
flagsrv = flagd.start()
|
||||||
|
|
||||||
signal.signal(signal.SIGCHLD, sigchld)
|
|
||||||
s = pointsrv.store
|
s = pointsrv.store
|
||||||
slen = 0
|
slen = 0
|
||||||
while True:
|
while True:
|
||||||
if do_reap:
|
|
||||||
reap()
|
|
||||||
asyncore.loop(timeout=30, use_poll=True, count=1)
|
asyncore.loop(timeout=30, use_poll=True, count=1)
|
||||||
|
reap()
|
||||||
if len(s) > slen:
|
if len(s) > slen:
|
||||||
slen = len(s)
|
slen = len(s)
|
||||||
chart(s)
|
chart(s)
|
||||||
|
|
76
mkpuzzles.py
|
@ -17,6 +17,37 @@ opts, args = p.parse_args()
|
||||||
|
|
||||||
keys = []
|
keys = []
|
||||||
|
|
||||||
|
js = '''
|
||||||
|
<script type="text/javascript">
|
||||||
|
function readCookie(key) {
|
||||||
|
var s = key + '=';
|
||||||
|
var toks = document.cookie.split(';');
|
||||||
|
for (var i = 0; i < toks.length; i++) {
|
||||||
|
var tok = toks[i];
|
||||||
|
while (tok.charAt(0) == ' ') {
|
||||||
|
tok = tok.substring(1, tok.length);
|
||||||
|
}
|
||||||
|
if (tok.indexOf(s) == 0) {
|
||||||
|
return tok.substring(s.length, tok.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTeamInfo() {
|
||||||
|
team = readCookie('team');
|
||||||
|
passwd = readCookie('passwd');
|
||||||
|
if (team != null) {
|
||||||
|
document.getElementById("form").t.value = team;
|
||||||
|
}
|
||||||
|
if (passwd != null) {
|
||||||
|
document.getElementById("form").w.value = passwd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.onload = getTeamInfo;
|
||||||
|
</script>
|
||||||
|
'''
|
||||||
|
|
||||||
for cat in os.listdir(opts.puzzles):
|
for cat in os.listdir(opts.puzzles):
|
||||||
dirname = os.path.join(opts.puzzles, cat)
|
dirname = os.path.join(opts.puzzles, cat)
|
||||||
for points in os.listdir(dirname):
|
for points in os.listdir(dirname):
|
||||||
|
@ -46,47 +77,7 @@ for cat in os.listdir(opts.puzzles):
|
||||||
|
|
||||||
title = '%s for %s points' % (cat, points)
|
title = '%s for %s points' % (cat, points)
|
||||||
f = open(os.path.join(outdir, 'index.html'), 'w', encoding='utf-8')
|
f = open(os.path.join(outdir, 'index.html'), 'w', encoding='utf-8')
|
||||||
f.write('''<?xml version="1.0" encoding="UTF-8"?>
|
f.write(config.start_html(title, js))
|
||||||
<!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>%(title)s</title>
|
|
||||||
<link rel="stylesheet" href="%(css)s" type="text/css" />
|
|
||||||
<script type="text/javascript">
|
|
||||||
function readCookie(key) {
|
|
||||||
var s = key + '=';
|
|
||||||
var toks = document.cookie.split(';');
|
|
||||||
for (var i = 0; i < toks.length; i++) {
|
|
||||||
var tok = toks[i];
|
|
||||||
while (tok.charAt(0) == ' ') {
|
|
||||||
tok = tok.substring(1, tok.length);
|
|
||||||
}
|
|
||||||
if (tok.indexOf(s) == 0) {
|
|
||||||
return tok.substring(s.length, tok.length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTeamInfo() {
|
|
||||||
team = readCookie('team');
|
|
||||||
passwd = readCookie('passwd');
|
|
||||||
if (team != null) {
|
|
||||||
document.getElementById("form").t.value = team;
|
|
||||||
}
|
|
||||||
if (passwd != null) {
|
|
||||||
document.getElementById("form").w.value = passwd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
window.onload = getTeamInfo;
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>%(title)s</h1>
|
|
||||||
''' % {'title': title,
|
|
||||||
'css': config.css})
|
|
||||||
if readme:
|
if readme:
|
||||||
f.write('<div class="readme">%s</div>\n' % readme)
|
f.write('<div class="readme">%s</div>\n' % readme)
|
||||||
if files:
|
if files:
|
||||||
|
@ -108,11 +99,10 @@ for cat in os.listdir(opts.puzzles):
|
||||||
<input type="submit" />
|
<input type="submit" />
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</form>
|
</form>
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
''' % {'cgi': config.get('puzzler', 'cgi_url'),
|
''' % {'cgi': config.get('puzzler', 'cgi_url'),
|
||||||
'cat': cat,
|
'cat': cat,
|
||||||
'points': points})
|
'points': points})
|
||||||
|
f.write(config.end_html())
|
||||||
|
|
||||||
f = open(opts.keyfile, 'w', encoding='utf-8')
|
f = open(opts.keyfile, 'w', encoding='utf-8')
|
||||||
for key in keys:
|
for key in keys:
|
||||||
|
|
|
@ -13,6 +13,8 @@ rotate /var/lib/ctf/scores.dat
|
||||||
rotate /var/lib/ctf/passwd
|
rotate /var/lib/ctf/passwd
|
||||||
rm -f /var/lib/ctf/flags/* || true
|
rm -f /var/lib/ctf/flags/* || true
|
||||||
|
|
||||||
|
sv restart /var/service/ctf
|
||||||
|
|
||||||
echo "Things you may want to tweak:"
|
echo "Things you may want to tweak:"
|
||||||
find /var/lib/ctf/disabled
|
find /var/lib/ctf/disabled
|
||||||
find /var/lib/kevin/tokens
|
find /var/lib/kevin/tokens
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
|
|
||||||
case "$REMOTEADDR" in
|
ip=$(echo $UDPREMOTEADDR | cut -d: -f1)
|
||||||
10.0.0.[2-254])
|
case "$ip" in
|
||||||
touch /var/lib/pollster/$REMOTEADDR
|
10.0.0.*)
|
||||||
|
touch /var/lib/pollster/$ip
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
echo 'Hello.'
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
exec logger -t pollster
|
|
@ -2,41 +2,21 @@
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import io
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import socket
|
import socket
|
||||||
import traceback
|
import traceback
|
||||||
import threading
|
|
||||||
import queue
|
|
||||||
|
|
||||||
from ctf import config
|
from ctf import config
|
||||||
from ctf import pointscli
|
from ctf import pointscli
|
||||||
|
|
||||||
DEBUG = False
|
DEBUG = False
|
||||||
POLL_INTERVAL = config.get('poll_interval')
|
POLL_INTERVAL = config.get('pollster', 'poll_interval')
|
||||||
IP_DIR = config.get('heartbeat_dir')
|
IP_DIR = config.get('pollster', 'heartbeat_dir')
|
||||||
REPORT_PATH = config.get('poll_dir')
|
REPORT_PATH = config.get('pollster', 'results')
|
||||||
SOCK_TIMEOUT = config.get('poll_timeout')
|
SOCK_TIMEOUT = config.get('pollster', '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):
|
def socket_poll(ip, port, msg, prot, max_recv=1):
|
||||||
''' Connect via socket to the specified <ip>:<port> using the
|
''' Connect via socket to the specified <ip>:<port> using the
|
||||||
|
@ -70,19 +50,16 @@ def socket_poll(ip, port, msg, prot, max_recv=1):
|
||||||
sock.send(msg)
|
sock.send(msg)
|
||||||
|
|
||||||
# get a response
|
# get a response
|
||||||
resp = ''
|
resp = []
|
||||||
try:
|
try:
|
||||||
# first read
|
# read from the socket until <max_recv> responses or read,
|
||||||
|
# a timeout occurs, the socket closes, or some other exception
|
||||||
|
# is raised
|
||||||
|
for i in range(max_recv):
|
||||||
data = sock.recv(1024)
|
data = sock.recv(1024)
|
||||||
resp += data.decode('utf-8')
|
if len(data) == 0:
|
||||||
max_recv -= 1
|
break
|
||||||
|
resp.append(data)
|
||||||
# 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:
|
except socket.timeout as e:
|
||||||
print('pollster: timed out waiting for a response from %s:%d (%s)' % (ip, port, e))
|
print('pollster: timed out waiting for a response from %s:%d (%s)' % (ip, port, e))
|
||||||
|
@ -91,10 +68,12 @@ def socket_poll(ip, port, msg, prot, max_recv=1):
|
||||||
print('pollster: receive from %s:%d failed (%s)' % (ip, port, e))
|
print('pollster: receive from %s:%d failed (%s)' % (ip, port, e))
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
|
sock.close()
|
||||||
|
|
||||||
if len(resp) == 0:
|
if len(resp) == 0:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return resp
|
return b''.join(resp)
|
||||||
|
|
||||||
# PUT POLLS FUNCTIONS HERE
|
# PUT POLLS FUNCTIONS HERE
|
||||||
# Each function should take an IP address and return a team name or None
|
# Each function should take an IP address and return a team name or None
|
||||||
|
@ -105,14 +84,14 @@ def poll_fingerd(ip):
|
||||||
resp = socket_poll(ip, 79, b'flag\n', socket.SOCK_STREAM)
|
resp = socket_poll(ip, 79, b'flag\n', socket.SOCK_STREAM)
|
||||||
if resp is None:
|
if resp is None:
|
||||||
return None
|
return None
|
||||||
return resp.strip('\r\n')
|
return resp.strip(b'\r\n')
|
||||||
|
|
||||||
def poll_noted(ip):
|
def poll_noted(ip):
|
||||||
''' Poll the noted service. Returns None or a team name. '''
|
''' Poll the noted service. Returns None or a team name. '''
|
||||||
resp = socket_poll(ip, 4000, b'rflag\n', socket.SOCK_STREAM)
|
resp = socket_poll(ip, 4000, b'rflag\n', socket.SOCK_STREAM)
|
||||||
if resp is None:
|
if resp is None:
|
||||||
return None
|
return None
|
||||||
return resp.strip('\r\n')
|
return resp.strip(b'\r\n')
|
||||||
|
|
||||||
def poll_catcgi(ip):
|
def poll_catcgi(ip):
|
||||||
''' Poll the cat.cgi web service. Returns None or a team name. '''
|
''' Poll the cat.cgi web service. Returns None or a team name. '''
|
||||||
|
@ -121,11 +100,11 @@ def poll_catcgi(ip):
|
||||||
if resp is None:
|
if resp is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
content = resp.split('\r\n\r\n')
|
content = resp.split(b'\r\n\r\n')
|
||||||
if len(content) < 3:
|
if len(content) < 3:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
content = content[1].split('\r\n')
|
content = content[1].split(b'\r\n')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
content_len = int(content[0])
|
content_len = int(content[0])
|
||||||
|
@ -134,7 +113,7 @@ def poll_catcgi(ip):
|
||||||
|
|
||||||
if content_len <= 0:
|
if content_len <= 0:
|
||||||
return None
|
return None
|
||||||
return content[1].strip('\r\n')
|
return content[1].strip(b'\r\n')
|
||||||
|
|
||||||
def poll_tftpd(ip):
|
def poll_tftpd(ip):
|
||||||
''' Poll the tftp service. Returns None or a team name. '''
|
''' Poll the tftp service. Returns None or a team name. '''
|
||||||
|
@ -145,8 +124,12 @@ def poll_tftpd(ip):
|
||||||
if len(resp) <= 5:
|
if len(resp) <= 5:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
resp = resp.split('\n')[0]
|
resp = resp.split(b'\n')[0]
|
||||||
return resp[4:].strip('\r\n')
|
|
||||||
|
# ack
|
||||||
|
_ = socket_poll(ip, 69, b'\x00\x04' + resp[2:4], socket.SOCK_DGRAM, 0)
|
||||||
|
|
||||||
|
return resp[4:].strip(b'\r\n')
|
||||||
|
|
||||||
# PUT POLL FUNCTIONS IN HERE OR THEY WONT BE POLLED
|
# PUT POLL FUNCTIONS IN HERE OR THEY WONT BE POLLED
|
||||||
POLLS = {
|
POLLS = {
|
||||||
|
@ -158,42 +141,17 @@ POLLS = {
|
||||||
|
|
||||||
ip_re = re.compile('(\d{1,3}\.){3}\d{1,3}')
|
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
|
# loop forever
|
||||||
while True:
|
while True:
|
||||||
|
|
||||||
t_start = time.time()
|
t_start = time.time()
|
||||||
|
|
||||||
# gather the list of IPs to poll
|
# gather the list of IPs to poll
|
||||||
try:
|
|
||||||
ips = os.listdir(IP_DIR)
|
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')
|
|
||||||
|
|
||||||
|
out = io.StringIO()
|
||||||
|
out.write(config.start_html('Team Service Availability'))
|
||||||
for ip in ips:
|
for ip in ips:
|
||||||
|
|
||||||
# check file name format is ip
|
# check file name format is ip
|
||||||
if ip_re.match(ip) is None:
|
if ip_re.match(ip) is None:
|
||||||
continue
|
continue
|
||||||
|
@ -217,7 +175,7 @@ while True:
|
||||||
|
|
||||||
# perform polls
|
# perform polls
|
||||||
for service,func in POLLS.items():
|
for service,func in POLLS.items():
|
||||||
team = func(ip)
|
team = func(ip).decode('utf-8')
|
||||||
if team is None:
|
if team is None:
|
||||||
team = 'dirtbags'
|
team = 'dirtbags'
|
||||||
|
|
||||||
|
@ -227,7 +185,7 @@ while True:
|
||||||
if out is not None:
|
if out is not None:
|
||||||
out.write('<tr><td>%s</td><td>%s</td>\n' % (service, team))
|
out.write('<tr><td>%s</td><td>%s</td>\n' % (service, team))
|
||||||
|
|
||||||
point_queue.put((service, team, 1))
|
pointscli.submit('svc.' + service, team, 1)
|
||||||
|
|
||||||
if out is not None:
|
if out is not None:
|
||||||
out.write('</table>\n')
|
out.write('</table>\n')
|
||||||
|
@ -240,9 +198,9 @@ while True:
|
||||||
sleep_time = POLL_INTERVAL - exec_time
|
sleep_time = POLL_INTERVAL - exec_time
|
||||||
|
|
||||||
if out is not None:
|
if out is not None:
|
||||||
out.write('<p><b>Next poll in: %ds</b></p>\n' % sleep_time)
|
out.write(config.end_html())
|
||||||
out.write('</body>\n</html>\n')
|
|
||||||
out.close()
|
open(REPORT_PATH, 'w').write(out.getvalue())
|
||||||
|
|
||||||
# sleep until its time to poll again
|
# sleep until its time to poll again
|
||||||
time.sleep(sleep_time)
|
time.sleep(sleep_time)
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
|
|
||||||
exec udpsvd 0 9 /usr/sbin/in.heartbeatd
|
exec udpsvd 0 9 envuidgid ctf /usr/sbin/in.heartbeatd
|
||||||
|
|
Before Width: | Height: | Size: 184 KiB After Width: | Height: | Size: 184 KiB |
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
‽
|
Before Width: | Height: | Size: 362 KiB After Width: | Height: | Size: 362 KiB |
|
@ -0,0 +1 @@
|
||||||
|
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
Give the <b>entire sequence</b>. The symbols are here, in no particular order, for you to copy and paste.<br />
|
||||||
|
Make sure to include spaces between symbols (but no leading or trailing spaces).<br /><br />
|
||||||
|
◕ ⚑ ♥ ◢ ★
|
|
@ -0,0 +1 @@
|
||||||
|
The "hispaniola" category requires contenstants to treasure-hunt for tangible items to learn the keys to each puzzle.
|
|
@ -1 +0,0 @@
|
||||||
You're well on your way :)
|
|
|
@ -1 +0,0 @@
|
||||||
‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽‽
|
|
|
@ -1 +0,0 @@
|
||||||
-462766
|
|
|
@ -1 +0,0 @@
|
||||||
3acd767f2717b84076cdcd18e882f01d
|
|
|
@ -1 +0,0 @@
|
||||||
⚑ _ _ _ _ ◢ _ _ _ _ ♥ _ _ _ _ ★ _ _ _ _ ◕ _ _ _ _
|
|
|
@ -3,7 +3,7 @@ html,body {
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
background-color: #000000;
|
background-color: #000000;
|
||||||
background-image: url(",binary.png");
|
background-image: url(",binary.png");
|
||||||
background-repeat: repeat-x repeat-y;
|
background-repeat: repeat;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
@ -52,3 +52,11 @@ h1,h2,h3,h4 {
|
||||||
margin: 2em auto 2em auto;
|
margin: 2em auto 2em auto;
|
||||||
border-bottom: 1px dotted #222;
|
border-bottom: 1px dotted #222;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
padding: 1em;
|
||||||
|
background: #fff;
|
||||||
|
color: red;
|
||||||
|
border: 1px solid red;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
../1/,binary.png
|
../10/,binary.png
|
|
@ -1 +1 @@
|
||||||
../1/,ctf.css
|
../10/,ctf.css
|
|
@ -1 +1 @@
|
||||||
../1/,binary.png
|
../10/,binary.png
|
|
@ -1 +1 @@
|
||||||
../1/,ctf.css
|
../10/,ctf.css
|
Before Width: | Height: | Size: 626 B After Width: | Height: | Size: 17 B |
|
@ -0,0 +1 @@
|
||||||
|
../10/,binary.png
|
Before Width: | Height: | Size: 626 B After Width: | Height: | Size: 17 B |
|
@ -1,54 +0,0 @@
|
||||||
html,body {
|
|
||||||
height: 100%;
|
|
||||||
min-height: 100%;
|
|
||||||
background-color: #000000;
|
|
||||||
background-image: url(",binary.png");
|
|
||||||
background-repeat: repeat-x repeat-y;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#wrapper {
|
|
||||||
min-height: 100%;
|
|
||||||
height: 100%;
|
|
||||||
width: 800px;
|
|
||||||
margin: 0 auto;
|
|
||||||
border-left: 2px solid #009900;
|
|
||||||
border-right: 2px solid #009900;
|
|
||||||
font: .9em monospace;
|
|
||||||
color: #009900;
|
|
||||||
padding: 0;
|
|
||||||
background: #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
#content {
|
|
||||||
padding: 2em 1.5em 2em 1.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#footer {
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
height: 2em;
|
|
||||||
line-height: 2em;
|
|
||||||
width: 800px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
input {
|
|
||||||
background-color: #222;
|
|
||||||
color: #fff;
|
|
||||||
border: 1px solid #009900;
|
|
||||||
padding: 1px 2px 1px 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1,h2,h3,h4 {
|
|
||||||
padding-bottom: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vertsep {
|
|
||||||
width: 100%;
|
|
||||||
height: 1px;
|
|
||||||
padding: 0;
|
|
||||||
margin: 2em auto 2em auto;
|
|
||||||
border-bottom: 1px dotted #222;
|
|
||||||
}
|
|
|
@ -0,0 +1 @@
|
||||||
|
../10/,ctf.css
|
|
@ -0,0 +1 @@
|
||||||
|
../10/,binary.png
|
|
@ -0,0 +1 @@
|
||||||
|
../10/,ctf.css
|
|
@ -0,0 +1,89 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
import os
|
||||||
|
import cgi
|
||||||
|
import cgitb
|
||||||
|
cgitb.enable(context=10)
|
||||||
|
|
||||||
|
if os.environ.has_key('QUERY_STRING'):
|
||||||
|
os.environ['QUERY_STRING'] = ''
|
||||||
|
|
||||||
|
fields = cgi.FieldStorage()
|
||||||
|
|
||||||
|
print 'Content-Type: text/html'
|
||||||
|
print ''
|
||||||
|
|
||||||
|
print '''
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>5</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href=",ctf.css" media="all" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="wrapper">
|
||||||
|
<div id="content">
|
||||||
|
<h1>Web Application Challenge 5</h1>
|
||||||
|
<p>Through some manipulation or interpretation of this CGI script
|
||||||
|
and the HTML page(s) that it generates, a 10 character key can be
|
||||||
|
found.</p>
|
||||||
|
<p><strong>Find the key!</strong></p>
|
||||||
|
|
||||||
|
<div class="vertsep"></div>
|
||||||
|
'''
|
||||||
|
|
||||||
|
PRODUCT_NAME = "Alex Brugh"
|
||||||
|
QUANT_LIMIT = 1
|
||||||
|
|
||||||
|
def purchase_success(quantity):
|
||||||
|
print '''
|
||||||
|
<p>Congratulations, your order for %d "%s" has been placed.</p>
|
||||||
|
''' % (quantity, PRODUCT_NAME)
|
||||||
|
|
||||||
|
class InvalidQuantityError(Exception):
|
||||||
|
def __init__(self, value):
|
||||||
|
self.value = value
|
||||||
|
def __str__(self):
|
||||||
|
return repr(self.value)
|
||||||
|
|
||||||
|
quantity = None
|
||||||
|
if fields.has_key('quantity') and fields.has_key('product') and fields['product'].value == PRODUCT_NAME:
|
||||||
|
product = fields['product'].value
|
||||||
|
try:
|
||||||
|
quantity = int(fields['quantity'].value)
|
||||||
|
if quantity > QUANT_LIMIT:
|
||||||
|
# key = eVkIwHzOok
|
||||||
|
raise InvalidQuantityError("%d is not a valid quantity (limit %d)" % (quantity, QUANT_LIMIT))
|
||||||
|
except ValueError:
|
||||||
|
print '''
|
||||||
|
<p class="error">There was an error with your order request. Sorry.</p>
|
||||||
|
'''
|
||||||
|
quantity = None
|
||||||
|
|
||||||
|
if quantity is not None:
|
||||||
|
purchase_success(quantity)
|
||||||
|
else:
|
||||||
|
print '''
|
||||||
|
|
||||||
|
<h2>SALE: %s</h2>
|
||||||
|
<p>Use the order form below to place an order.</p>
|
||||||
|
|
||||||
|
<form method="post" action="5.cgi">
|
||||||
|
<em>Orders for "%s" are limited to 1 per customer.</em>
|
||||||
|
<br /><br />
|
||||||
|
<input type="submit" value="Order!" />
|
||||||
|
<input type="hidden" name="product" value="%s" />
|
||||||
|
<input type="hidden" name="quantity" value="1" />
|
||||||
|
</form>
|
||||||
|
''' % (PRODUCT_NAME, PRODUCT_NAME, PRODUCT_NAME)
|
||||||
|
|
||||||
|
print '''
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div id="footer">
|
||||||
|
<p>Copyright © 2009 LANS, LLC.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
'''
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
eVkIwHzOok
|
|
@ -0,0 +1 @@
|
||||||
|
../10/,binary.png
|
|
@ -0,0 +1 @@
|
||||||
|
../10/,ctf.css
|
|
@ -0,0 +1,72 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
import os
|
||||||
|
import cgi
|
||||||
|
import cgitb
|
||||||
|
cgitb.enable(context=10)
|
||||||
|
|
||||||
|
#if os.environ.has_key('QUERY_STRING'):
|
||||||
|
# os.environ['QUERY_STRING'] = ''
|
||||||
|
|
||||||
|
fields = cgi.FieldStorage()
|
||||||
|
|
||||||
|
import Cookie
|
||||||
|
c = Cookie.SimpleCookie()
|
||||||
|
c['key'] = 'QJebByJaKX'
|
||||||
|
c['content'] = '<p><em>Maybe I should have used sessions...</em></p>'
|
||||||
|
|
||||||
|
print 'Content-Type: text/html\n%s\n\n\n' % c
|
||||||
|
print ''
|
||||||
|
|
||||||
|
print '''
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>6</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href=",ctf.css" media="all" />
|
||||||
|
<script type="text/javascript">
|
||||||
|
function readCookie(key) {
|
||||||
|
var s = key + '=';
|
||||||
|
var toks = document.cookie.split(';');
|
||||||
|
for (var i = 0; i < toks.length; i++) {
|
||||||
|
var tok = toks[i];
|
||||||
|
while (tok.charAt(0) == ' ') {
|
||||||
|
tok = tok.substring(1, tok.length);
|
||||||
|
}
|
||||||
|
if (tok.indexOf(s) == 0) {
|
||||||
|
return tok.substring(s.length, tok.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setContent() {
|
||||||
|
content = readCookie("content");
|
||||||
|
document.getElementById("stuff").innerHTML = content.substring(1, content.length-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.onload = setContent;
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="wrapper">
|
||||||
|
<div id="content">
|
||||||
|
<h1>Web Application Challenge 6</h1>
|
||||||
|
<p>Through some manipulation or interpretation of this CGI script
|
||||||
|
and the HTML page(s) that it generates, a 10 character key can be
|
||||||
|
found.</p>
|
||||||
|
<p><strong>Find the key!</strong></p>
|
||||||
|
|
||||||
|
<div class="vertsep"></div>
|
||||||
|
<div id="stuff"></div>
|
||||||
|
'''
|
||||||
|
|
||||||
|
print '''
|
||||||
|
</div>
|
||||||
|
<div id="footer">
|
||||||
|
<p>Copyright © 2009 LANS, LLC.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
'''
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
QJebByJaKX
|
|
@ -0,0 +1 @@
|
||||||
|
../10/,binary.png
|
|
@ -0,0 +1 @@
|
||||||
|
../10/,ctf.css
|
|
@ -0,0 +1,86 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
import os
|
||||||
|
import cgi
|
||||||
|
import cgitb
|
||||||
|
cgitb.enable(context=10)
|
||||||
|
|
||||||
|
#if os.environ.has_key('QUERY_STRING'):
|
||||||
|
# os.environ['QUERY_STRING'] = ''
|
||||||
|
|
||||||
|
fields = cgi.FieldStorage()
|
||||||
|
|
||||||
|
import Cookie
|
||||||
|
c = Cookie.SimpleCookie(os.environ.get('HTTP_COOKIE', ''))
|
||||||
|
|
||||||
|
content = {
|
||||||
|
'joke1' : '<p>An infinite number of mathematicians walk into a bar. The first one orders a beer. The second orders half a beer. The third, a quarter of a beer. The bartender says <em>You are all idiots!</em> and pours two beers.<p>',
|
||||||
|
'joke2' : '<p>Two atoms are talking. One of them says <em>I think I lost an electron!</em> and the other says <em>Are you sure?</em> The first replies <em>Yeah, I am positive!</em></p>',
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.has_key('content_name') and c.has_key('content'):
|
||||||
|
k = c['content_name'].value
|
||||||
|
try:
|
||||||
|
c['content'] = content[k]
|
||||||
|
except KeyError:
|
||||||
|
c['content'] = '<p><em>key = s4nNlaMScV</em></p>'
|
||||||
|
else:
|
||||||
|
c['content_name'] = 'joke1';
|
||||||
|
c['content'] = content['joke1']
|
||||||
|
|
||||||
|
|
||||||
|
print 'Content-Type: text/html\n%s\n\n\n' % c
|
||||||
|
print ''
|
||||||
|
|
||||||
|
print '''
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>7</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href=",ctf.css" media="all" />
|
||||||
|
<script type="text/javascript">
|
||||||
|
function readCookie(key) {
|
||||||
|
var s = key + '=';
|
||||||
|
var toks = document.cookie.split(';');
|
||||||
|
for (var i = 0; i < toks.length; i++) {
|
||||||
|
var tok = toks[i];
|
||||||
|
while (tok.charAt(0) == ' ') {
|
||||||
|
tok = tok.substring(1, tok.length);
|
||||||
|
}
|
||||||
|
if (tok.indexOf(s) == 0) {
|
||||||
|
return tok.substring(s.length, tok.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getContent() {
|
||||||
|
content = readCookie("content");
|
||||||
|
document.getElementById("stuff").innerHTML = content.substring(1, content.length-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.onload = getContent;
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="wrapper">
|
||||||
|
<div id="content">
|
||||||
|
<h1>Web Application Challenge 7</h1>
|
||||||
|
<p>Through some manipulation or interpretation of this CGI script
|
||||||
|
and the HTML page(s) that it generates, a 10 character key can be
|
||||||
|
found.</p>
|
||||||
|
<p><strong>Find the key!</strong></p>
|
||||||
|
|
||||||
|
<div class="vertsep"></div>
|
||||||
|
<div id="stuff"></div>
|
||||||
|
'''
|
||||||
|
|
||||||
|
print '''
|
||||||
|
</div>
|
||||||
|
<div id="footer">
|
||||||
|
<p>Copyright © 2009 LANS, LLC.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
'''
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
s4nNlaMScV
|
|
@ -0,0 +1,14 @@
|
||||||
|
10: the key is in the generated source.
|
||||||
|
20: enter a non-integer into form field and submit. the key is in the resulting
|
||||||
|
traceback.
|
||||||
|
30: change the value in the GET request to a non-integer. the key is in the
|
||||||
|
resulting traceback.
|
||||||
|
40: change the value in the POST request to a non-integer. the key is in the
|
||||||
|
resulting traceback.
|
||||||
|
50: change the quantity value (hidden form field) to something greater than the
|
||||||
|
stated quantity limit. the key is in the resulting traceback. entering non-
|
||||||
|
integers is caught and handled, so that no longer works.
|
||||||
|
60: the key is in the cookie. note the javascript that reads a value from the
|
||||||
|
cookie, hopefully causing the player to take a look at the cookie.
|
||||||
|
70: modify the cookie's content_name field to something invalid, reload the page
|
||||||
|
and the key will be printed on the page.
|
|
@ -7,7 +7,7 @@ skills at designing those wits to survive.
|
||||||
|
|
||||||
<H2>Programming Your Tank</H2>
|
<H2>Programming Your Tank</H2>
|
||||||
Your tanks are programmed using the Super Useful Command and Kontrol language,
|
Your tanks are programmed using the Super Useful Command and Kontrol language,
|
||||||
the very best in laser tank AI languages. It includes amazing feature such
|
the very best in laser tank AI languages. It includes amazing features such
|
||||||
as comments (Started by a #, ended at EOL), logic, versatility, and
|
as comments (Started by a #, ended at EOL), logic, versatility, and
|
||||||
semi-colons (all lines must end in one). As with all new military systems
|
semi-colons (all lines must end in one). As with all new military systems
|
||||||
it utilizes only integers; we must never rest in our
|
it utilizes only integers; we must never rest in our
|
||||||
|
|
|
@ -4,9 +4,8 @@ def mkDocTable(objects):
|
||||||
objects.sort(lambda o1, o2: cmp(o1.__doc__, o2.__doc__))
|
objects.sort(lambda o1, o2: cmp(o1.__doc__, o2.__doc__))
|
||||||
|
|
||||||
for object in objects:
|
for object in objects:
|
||||||
print '<table class="docs">'
|
|
||||||
if object.__doc__ is None:
|
if object.__doc__ is None:
|
||||||
print '<tr><th>%s<tr><td colspan=2>Bad object' % \
|
print '<table><tr><th>%s<tr><td colspan=2>Bad object</table>' % \
|
||||||
xml.sax.saxutils.escape(str(object))
|
xml.sax.saxutils.escape(str(object))
|
||||||
continue
|
continue
|
||||||
text = object.__doc__
|
text = object.__doc__
|
||||||
|
@ -23,5 +22,5 @@ def mkDocTable(objects):
|
||||||
body = '\n'.join(body)
|
body = '\n'.join(body)
|
||||||
print '<DL><DT><DIV class="tab">%s</DIV></DT><DD>%s</DD></DL>' % (head, body)
|
print '<DL><DT><DIV class="tab">%s</DIV></DT><DD>%s</DD></DL>' % (head, body)
|
||||||
#print '<tr><th>%s<th>Intentionally blank<th><tr><td colspan=3>%s' % (head, body)
|
#print '<tr><th>%s<th>Intentionally blank<th><tr><td colspan=3>%s' % (head, body)
|
||||||
print '</table>'
|
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,8 @@ MAX_HIST = 30
|
||||||
HIST_STEP = 100
|
HIST_STEP = 100
|
||||||
key = 'tanks:::2bac5e912ff2e1ad559b177eb5aeecca'
|
key = 'tanks:::2bac5e912ff2e1ad559b177eb5aeecca'
|
||||||
|
|
||||||
|
running = True
|
||||||
|
|
||||||
class Flagger(asynchat.async_chat):
|
class Flagger(asynchat.async_chat):
|
||||||
"""Use to connect to flagd and submit the current flag holder."""
|
"""Use to connect to flagd and submit the current flag holder."""
|
||||||
|
|
||||||
|
@ -31,6 +33,7 @@ class Flagger(asynchat.async_chat):
|
||||||
def handle_error(self):
|
def handle_error(self):
|
||||||
# If we lose the connection to flagd, nobody can score any
|
# If we lose the connection to flagd, nobody can score any
|
||||||
# points. Terminate everything.
|
# points. Terminate everything.
|
||||||
|
running = False
|
||||||
asyncore.close_all()
|
asyncore.close_all()
|
||||||
asynchat.async_chat.handle_error(self)
|
asynchat.async_chat.handle_error(self)
|
||||||
|
|
||||||
|
@ -84,6 +87,8 @@ def main():
|
||||||
lastrun = 0
|
lastrun = 0
|
||||||
while True:
|
while True:
|
||||||
asyncore.loop(60, count=1)
|
asyncore.loop(60, count=1)
|
||||||
|
if not running:
|
||||||
|
break
|
||||||
now = time.time()
|
now = time.time()
|
||||||
if now - lastrun >= 60:
|
if now - lastrun >= 60:
|
||||||
run_tanks(args, turns, flagger)
|
run_tanks(args, turns, flagger)
|
||||||
|
|
|
@ -1,104 +0,0 @@
|
||||||
/**** document ****/
|
|
||||||
|
|
||||||
html {
|
|
||||||
background: #222 url(grunge.png) repeat-x;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
font-family: sans-serif;
|
|
||||||
color: #eee;
|
|
||||||
margin: 50px 0 0 100px;
|
|
||||||
padding: 10px;
|
|
||||||
max-width: 700px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**** heading ****/
|
|
||||||
|
|
||||||
h1:first-child {
|
|
||||||
text-transform: lowercase;
|
|
||||||
font-size: 1.6em;
|
|
||||||
/* background-color: #222; */
|
|
||||||
/* opacity: 0.9; */
|
|
||||||
padding: 3px;
|
|
||||||
color: #2a2;
|
|
||||||
margin: 0 0 1em 70px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1:first-child:before {
|
|
||||||
color: #fff;
|
|
||||||
letter-spacing: -0.1em;
|
|
||||||
content: "Capture The Flag: ";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**** body ****/
|
|
||||||
|
|
||||||
a img {
|
|
||||||
border: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
text-decoration: none;
|
|
||||||
color: #2a2;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:hover {
|
|
||||||
color: #fff;
|
|
||||||
background: #2a2;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
h1, h2, h3 {
|
|
||||||
color: #999;
|
|
||||||
letter-spacing: -0.05em;
|
|
||||||
}
|
|
||||||
|
|
||||||
code, pre, .readme, div.errors {
|
|
||||||
color: #fff;
|
|
||||||
background-color: #555;
|
|
||||||
margin: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
th, td {
|
|
||||||
vertical-align: top;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scoreboard td {
|
|
||||||
height: 400px;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
line-height: 1.4em;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
color: #f4f4f4;
|
|
||||||
}
|
|
||||||
|
|
||||||
dt {
|
|
||||||
white-space: pre;
|
|
||||||
}
|
|
||||||
|
|
||||||
dt div.tab {
|
|
||||||
background-color: #333;
|
|
||||||
display: inline-block;
|
|
||||||
padding: 5px;
|
|
||||||
border: 3px solid green;
|
|
||||||
border-bottom: none;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
dd {
|
|
||||||
border: 3px solid green;
|
|
||||||
margin: 0px;
|
|
||||||
padding: 5px;
|
|
||||||
background-color: #282828;
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldset * {
|
|
||||||
margin: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.results td, th{
|
|
||||||
padding : 3px;
|
|
||||||
font-weight : bold;
|
|
||||||
}
|
|
|
@ -1,10 +1,9 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
|
|
||||||
print """Content-Type: text/html\n\n"""
|
|
||||||
print """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">\n\n"""
|
|
||||||
import cgitb; cgitb.enable()
|
import cgitb; cgitb.enable()
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
from ctf import config
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from tanks import Program, setup, conditions, actions, docs
|
from tanks import Program, setup, conditions, actions, docs
|
||||||
|
@ -15,10 +14,13 @@ except:
|
||||||
sys.path.append(os.path.join('/', *path))
|
sys.path.append(os.path.join('/', *path))
|
||||||
import Program, setup, conditions, actions, docs
|
import Program, setup, conditions, actions, docs
|
||||||
|
|
||||||
print open('head.html').read() % "Documentation"
|
print(config.start_html('Tanks Documentation',
|
||||||
print '<BODY>'
|
links_title='Tanks',
|
||||||
print '<H1>Pflanzarr Documentation</H1>'
|
links=[('docs.cgi', 'Docs'),
|
||||||
print open('links.html').read()
|
('results.cgi', 'Results'),
|
||||||
|
('submit.html', 'Submit'),
|
||||||
|
('errors.cgi', 'My Errors')]))
|
||||||
|
|
||||||
print Program.__doc__
|
print Program.__doc__
|
||||||
|
|
||||||
print '<H3>Setup Actions:</H3>'
|
print '<H3>Setup Actions:</H3>'
|
||||||
|
@ -34,4 +36,4 @@ print '<H3>Actions:</H3>'
|
||||||
print 'These actions are not for cowards. Remember, if actions contradict, your tank will simply do the last thing it was told in a turn. If ordered to hop on a plane to hell it will gladly do so. If order to make tea shortly afterwards, it will serve it politely and with cookies instead.<P>'
|
print 'These actions are not for cowards. Remember, if actions contradict, your tank will simply do the last thing it was told in a turn. If ordered to hop on a plane to hell it will gladly do so. If order to make tea shortly afterwards, it will serve it politely and with cookies instead.<P>'
|
||||||
docs.mkDocTable(actions.actions.values())
|
docs.mkDocTable(actions.actions.values())
|
||||||
|
|
||||||
print '</body></html>'
|
print(config.end_html())
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
#!/usr/bin/python3
|
#!/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 cgi
|
||||||
import cgitb; cgitb.enable()
|
import cgitb; cgitb.enable()
|
||||||
import sys
|
import sys
|
||||||
|
@ -20,15 +18,18 @@ except:
|
||||||
path = '/home/pflarr/repos/gctf/'
|
path = '/home/pflarr/repos/gctf/'
|
||||||
sys.path.append(path)
|
sys.path.append(path)
|
||||||
from ctf import teams
|
from ctf import teams
|
||||||
|
from ctf import config
|
||||||
teams.build_teams()
|
teams.build_teams()
|
||||||
|
|
||||||
head = open('head.html').read() % "Error Report"
|
print(config.start_html('Tanks Errors',
|
||||||
print(head)
|
links_title='Tanks',
|
||||||
print('<H1>Your Errors</H1>')
|
links=[('docs.cgi', 'Docs'),
|
||||||
print(open('links.html').read())
|
('results.cgi', 'Results'),
|
||||||
|
('submit.html', 'Submit'),
|
||||||
|
('errors.cgi', 'My Errors')]))
|
||||||
|
|
||||||
def done():
|
def done():
|
||||||
print('</body></html>')
|
print(config.end_html())
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
fields = cgi.FieldStorage()
|
fields = cgi.FieldStorage()
|
||||||
|
|
Before Width: | Height: | Size: 5.8 KiB |
|
@ -1,5 +0,0 @@
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<link href="ctf.css" rel="stylesheet" type="text/css">
|
|
||||||
<title>%s</title>
|
|
||||||
</head>
|
|
|
@ -1,4 +0,0 @@
|
||||||
<a href="docs.cgi">Documentation</a> |
|
|
||||||
<a href="results.cgi">Results</a> |
|
|
||||||
<a href="submit.html">Submit</a> |
|
|
||||||
<a href="errors.cgi">My Errors</a>
|
|
|
@ -2,16 +2,16 @@
|
||||||
|
|
||||||
import cgitb; cgitb.enable()
|
import cgitb; cgitb.enable()
|
||||||
import os
|
import os
|
||||||
|
from ctf import config
|
||||||
|
|
||||||
import Config
|
import Config
|
||||||
|
|
||||||
print """Content-Type: text/html\n\n"""
|
print(config.start_html('Tanks Results',
|
||||||
print """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">\n\n"""
|
links_title='Tanks',
|
||||||
head = open('head.html').read() % "Pflanzarr Results"
|
links=[('docs.cgi', 'Docs'),
|
||||||
print head
|
('results.cgi', 'Results'),
|
||||||
print "<H1>Results</H1>"
|
('submit.html', 'Submit'),
|
||||||
print open('links.html').read()
|
('errors.cgi', 'My Errors')]))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
winner = open(os.path.join(Config.DATA_PATH, 'winner')).read()
|
winner = open(os.path.join(Config.DATA_PATH, 'winner')).read()
|
||||||
except:
|
except:
|
||||||
|
@ -52,4 +52,4 @@ for num in gameNums:
|
||||||
print '<a href="results/%d/game.avi">v</a>' % num,
|
print '<a href="results/%d/game.avi">v</a>' % num,
|
||||||
print '<a href="results/%d/results.html">r</a>' % num
|
print '<a href="results/%d/results.html">r</a>' % num
|
||||||
|
|
||||||
print '</body></html>'
|
print(config.end_html())
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
#!/usr/bin/python3
|
#!/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 cgi
|
||||||
import cgitb; cgitb.enable()
|
import cgitb; cgitb.enable()
|
||||||
import os
|
import os
|
||||||
|
@ -20,15 +18,18 @@ except:
|
||||||
path = '/home/pflarr/repos/gctf/'
|
path = '/home/pflarr/repos/gctf/'
|
||||||
sys.path.append(path)
|
sys.path.append(path)
|
||||||
from ctf import teams
|
from ctf import teams
|
||||||
|
from ctf import config
|
||||||
teams.build_teams()
|
teams.build_teams()
|
||||||
|
|
||||||
head = open('head.html').read() % "Submission Results"
|
print(config.start_html('Tanks Submission',
|
||||||
print(head)
|
links_title='Tanks',
|
||||||
print("<H1>Results</H1>")
|
links=[('docs.cgi', 'Docs'),
|
||||||
print(open('links.html').read())
|
('results.cgi', 'Results'),
|
||||||
|
('submit.html', 'Submit'),
|
||||||
|
('errors.cgi', 'My Errors')]))
|
||||||
|
|
||||||
def done():
|
def done():
|
||||||
print('</body></html>')
|
print(config.end_html())
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
fields = cgi.FieldStorage()
|
fields = cgi.FieldStorage()
|
||||||
|
@ -36,23 +37,23 @@ team = fields.getfirst('team', '').strip()
|
||||||
passwd = fields.getfirst('passwd', '').strip()
|
passwd = fields.getfirst('passwd', '').strip()
|
||||||
code = fields.getfirst('code', '')
|
code = fields.getfirst('code', '')
|
||||||
if not team:
|
if not team:
|
||||||
print('<p>No team specified'); done()
|
print('<p>No team specified</p>'); done()
|
||||||
elif not passwd:
|
elif not passwd:
|
||||||
print('<p>No password given'); done()
|
print('<p>No password given</p>'); done()
|
||||||
elif not code:
|
elif not code:
|
||||||
print('<p>No program given.'); done()
|
print('<p>No program given.</p>'); done()
|
||||||
|
|
||||||
if team not in teams.teams:
|
if team not in teams.teams:
|
||||||
print('<p>Team is not registered.'); done()
|
print('<p>Team is not registered.</p>'); done()
|
||||||
|
|
||||||
if passwd != teams.teams[team][0]:
|
if passwd != teams.teams[team][0]:
|
||||||
print('<p>Invalid password.'); done()
|
print('<p>Invalid password.</p>'); done()
|
||||||
|
|
||||||
path = os.path.join(Config.DATA_PATH, 'ai/players', quote(team) )
|
path = os.path.join(Config.DATA_PATH, 'ai/players', quote(team) )
|
||||||
file = open(path, 'w')
|
file = open(path, 'w')
|
||||||
file.write(code)
|
file.write(code)
|
||||||
file.close()
|
file.close()
|
||||||
|
|
||||||
print("<P>Submission Successful")
|
print("<p>Submission successful.</p>")
|
||||||
|
|
||||||
done()
|
done()
|
||||||
|
|
|
@ -1,16 +1,33 @@
|
||||||
<html>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<head>
|
<!DOCTYPE html PUBLIC
|
||||||
<link href="ctf.css" rel="stylesheet" type="text/css">'
|
"-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||||
<title>Program Submission</title>"
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
</head>
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<title>Tanks Submission</title>
|
||||||
|
<link rel="stylesheet" href="/ctf.css" type="text/css" />
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body class="">
|
||||||
|
<h1>Tanks Submission</h1>
|
||||||
|
|
||||||
|
<div id="navigation">
|
||||||
|
<ul>
|
||||||
|
<li><a href="/">Home</a></li>
|
||||||
|
<li><a href="/intro.html">Intro/Rules</a></li>
|
||||||
|
<li><a href="/services.html">Svc flags</a></li>
|
||||||
|
<li><a href="/puzzler.cgi">Puzzles</a></li>
|
||||||
|
<li><a href="/scoreboard.cgi">Scoreboard</a></li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Tanks</h3>
|
||||||
|
<li><a href="docs.cgi">Docs</a></li>
|
||||||
|
<li><a href="results.cgi">Results</a></li>
|
||||||
|
<li><a href="submit.html">Submit</a></li>
|
||||||
|
<li><a href="errors.cgi">My Errors</a></li>
|
||||||
|
</div>
|
||||||
|
|
||||||
<body>
|
|
||||||
<H1>Program Submission</H1>
|
|
||||||
<p>
|
|
||||||
<a href="docs.cgi">Documentation</a> |
|
|
||||||
<a href="results.cgi">Results</a> |
|
|
||||||
<a href="submit.html">Submit</a> |
|
|
||||||
<a href="errors.cgi">My Errors</a>
|
|
||||||
<form action="submit.cgi" method="post">
|
<form action="submit.cgi" method="post">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Your program:</legend>
|
<legend>Your program:</legend>
|
||||||
|
|