mirror of https://github.com/dirtbags/moth.git
Modularize + lots of fixes
This commit is contained in:
parent
c246ad4d75
commit
48c6ca0aa2
12
Makefile
12
Makefile
|
@ -1,12 +0,0 @@
|
||||||
SUBDIRS = src
|
|
||||||
|
|
||||||
all: build
|
|
||||||
|
|
||||||
include $(addsuffix /*.mk, $(SUBDIRS))
|
|
||||||
|
|
||||||
test: build
|
|
||||||
./test.sh
|
|
||||||
|
|
||||||
build: $(addsuffix -build, $(SUBDIRS))
|
|
||||||
clean: $(addsuffix -clean, $(SUBDIRS))
|
|
||||||
|
|
37
bin/run-ctf
37
bin/run-ctf
|
@ -1,37 +0,0 @@
|
||||||
#! /bin/sh
|
|
||||||
|
|
||||||
# First argument is seconds between running everything
|
|
||||||
period=${1:-60}
|
|
||||||
|
|
||||||
CTF_BASE=${CTF_BASE:-/srv/ctf} export CTF_BASE
|
|
||||||
|
|
||||||
POINTS=$CTF_BASE/points.log
|
|
||||||
SCOREBOARD=$CTF_BASE/www/scoreboard.html
|
|
||||||
PUZZLES=$CTF_BASE/www/puzzles.html
|
|
||||||
|
|
||||||
while true; do
|
|
||||||
start=$(date +%s)
|
|
||||||
next=$(expr $start + $period)
|
|
||||||
|
|
||||||
# Collect any new points
|
|
||||||
for fn in $CTF_BASE/points.new/*; do
|
|
||||||
[ -f $fn ] || continue
|
|
||||||
cat $fn >> $POINTS || break
|
|
||||||
rm $fn
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ $POINTS -nt $SCOREBOARD ]; then
|
|
||||||
$CTF_BASE/sbin/scoreboard < $POINTS > $SCOREBOARD.new
|
|
||||||
mv $SCOREBOARD.new $SCOREBOARD
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ $CTF_BASE/puzzler.db -nt $PUZZLES ]; then
|
|
||||||
$CTF_BASE/sbin/puzzles.cgi > $PUZZLES.new
|
|
||||||
mv $PUZZLES.new $PUZZLES
|
|
||||||
fi
|
|
||||||
|
|
||||||
now=$(date +%s)
|
|
||||||
if [ $now -lt $next ]; then
|
|
||||||
sleep $(expr $next - $now)
|
|
||||||
fi
|
|
||||||
done
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
SUBDIRS = src
|
||||||
|
PKGDIR = pkg
|
||||||
|
PACKAGE = mcp.pkg
|
||||||
|
|
||||||
|
all: package
|
||||||
|
|
||||||
|
package: $(PACKAGE)
|
||||||
|
|
||||||
|
$(PACKAGE): build
|
||||||
|
mkdir -p $(PKGDIR)
|
||||||
|
|
||||||
|
cp setup $(PKGDIR)
|
||||||
|
|
||||||
|
find bin -not -name '*~' | cpio -p $(PKGDIR)
|
||||||
|
cp src/in.tokend src/pointscli $(PKGDIR)/bin
|
||||||
|
|
||||||
|
find service -not -name '*~' -not -name '#*' | cpio -p $(PKGDIR)
|
||||||
|
|
||||||
|
find www -not -name '*~' -not -name '#*' | cpio -p $(PKGDIR)
|
||||||
|
cp src/puzzler.cgi src/puzzles.cgi src/claim.cgi $(PKGDIR)/www
|
||||||
|
|
||||||
|
mksquashfs $(PKGDIR) $(PACKAGE) -all-root -noappend
|
||||||
|
|
||||||
|
|
||||||
|
include $(addsuffix /*.mk, $(SUBDIRS))
|
||||||
|
|
||||||
|
test: build
|
||||||
|
./test.sh
|
||||||
|
|
||||||
|
build: $(addsuffix -build, $(SUBDIRS))
|
||||||
|
clean: $(addsuffix -clean, $(SUBDIRS))
|
||||||
|
rm -rf $(PKGDIR) $(PACKAGE)
|
|
@ -8,7 +8,7 @@ fi
|
||||||
# Don't overwrite files
|
# Don't overwrite files
|
||||||
set -C
|
set -C
|
||||||
|
|
||||||
base=${CTF_BASE:-/srv/ctf}
|
base=${CTF_BASE:-/var/lib/ctf}
|
||||||
|
|
||||||
# Assign a color. I spent two days selecting this color pallette for
|
# Assign a color. I spent two days selecting this color pallette for
|
||||||
# people with protanopia. Please don't change these colors.
|
# people with protanopia. Please don't change these colors.
|
|
@ -0,0 +1,55 @@
|
||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
# First argument is seconds between running everything
|
||||||
|
period=${1:-60}
|
||||||
|
|
||||||
|
BIN=${CTF_BASE:-/opt/mcp}/bin
|
||||||
|
WWW=${CTF_BASE:-/var}/www
|
||||||
|
STATE=${CTF_BASE:-/var/lib/ctf}
|
||||||
|
|
||||||
|
NEWPOINTS=$STATE/points.new
|
||||||
|
POINTS=$STATE/points.log
|
||||||
|
SCOREBOARD=$WWW/scoreboard.html
|
||||||
|
PUZZLES=$WWW/puzzles.html
|
||||||
|
TEAMS=$WWW/teams.html
|
||||||
|
|
||||||
|
mkdir -p $NEWPOINTS $STATE/teams/names $STATE/teams/colors
|
||||||
|
touch $POINTS
|
||||||
|
if ! [ -f $SCOREBOARD ]; then
|
||||||
|
$BIN/scoreboard < $POINTS > $SCOREBOARD
|
||||||
|
done
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
start=$(date +%s)
|
||||||
|
next=$(expr $start + $period)
|
||||||
|
|
||||||
|
# Collect any new points
|
||||||
|
for fn in $NEWPOINTS/*; do
|
||||||
|
[ -f $fn ] || continue
|
||||||
|
cat $fn >> $POINTS || break
|
||||||
|
rm $fn
|
||||||
|
done
|
||||||
|
|
||||||
|
# Render scoreboard
|
||||||
|
if [ $POINTS -nt $SCOREBOARD ]; then
|
||||||
|
$BIN/scoreboard < $POINTS > $SCOREBOARD.new
|
||||||
|
mv $SCOREBOARD.new $SCOREBOARD
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Render puzzles list
|
||||||
|
if [ $STATE/puzzler.db -nt $PUZZLES ]; then
|
||||||
|
$WWW/puzzles.cgi > $PUZZLES.new
|
||||||
|
mv $PUZZLES.new $PUZZLES
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Render team names
|
||||||
|
if [ $STATE/teams/names -nt $TEAMS ]; then
|
||||||
|
$BIN/teams.sh > $TEAMS.new
|
||||||
|
mv $TEAMS.new $TEAMS
|
||||||
|
fi
|
||||||
|
|
||||||
|
now=$(date +%s)
|
||||||
|
if [ $now -lt $next ]; then
|
||||||
|
sleep $(expr $next - $now)
|
||||||
|
fi
|
||||||
|
done
|
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
##
|
##
|
||||||
##
|
##
|
||||||
## I'm not happy with how this code looks. I've
|
## I'm not super happy with how this code looks. Rest assured, though,
|
||||||
|
## the C version would look far, far worse.
|
||||||
##
|
##
|
||||||
##
|
##
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
|
|
||||||
|
cd /var/lib/ctf/teams/names
|
||||||
|
|
||||||
escape () {
|
escape () {
|
||||||
sed 's/&/\&/g;s/</\</g;s/>/\>/g'
|
sed 's/&/\&/g;s/</\</g;s/>/\>/g'
|
||||||
}
|
}
|
||||||
|
@ -27,6 +29,7 @@ done
|
||||||
echo "</table>"
|
echo "</table>"
|
||||||
|
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
|
<p>Use your team's token to claim points.</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
EOF
|
EOF
|
|
@ -0,0 +1,5 @@
|
||||||
|
#! /bin/sh -e
|
||||||
|
|
||||||
|
ifconfig eth0 10.0.0.1 netmask 255.0.0.0
|
||||||
|
|
||||||
|
exec inotifyd true $(pwd):x
|
|
@ -0,0 +1,41 @@
|
||||||
|
Umask 026
|
||||||
|
|
||||||
|
Log /dev/stdout
|
||||||
|
ErrorLog /dev/stderr
|
||||||
|
|
||||||
|
User nobody
|
||||||
|
StayRoot On
|
||||||
|
|
||||||
|
Tuning {
|
||||||
|
Timeout 5
|
||||||
|
ScriptTimeout 5
|
||||||
|
}
|
||||||
|
|
||||||
|
Control {
|
||||||
|
ScriptUser ctf
|
||||||
|
|
||||||
|
Types {
|
||||||
|
application/javascript { .js }
|
||||||
|
text/html { .html }
|
||||||
|
text/plain { .txt }
|
||||||
|
text/css { .css }
|
||||||
|
image/png { .png }
|
||||||
|
image/jpeg { .jpg }
|
||||||
|
image/gif { .gif }
|
||||||
|
application/octet-stream { * }
|
||||||
|
}
|
||||||
|
Specials {
|
||||||
|
CGI { .cgi }
|
||||||
|
}
|
||||||
|
IndexNames { index.html }
|
||||||
|
}
|
||||||
|
|
||||||
|
Server {
|
||||||
|
Virtual {
|
||||||
|
AnyHost
|
||||||
|
Control {
|
||||||
|
Alias /
|
||||||
|
Location /var/www
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
exec mathopd -n -f ./mathopd.conf >> /var/log/mathopd.log 2>> /var/log/mathopd.error.log
|
|
@ -0,0 +1,3 @@
|
||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
exec logger -t mcp
|
|
@ -0,0 +1,4 @@
|
||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
exec 2>&1
|
||||||
|
exec /opt/mcp/bin/run-ctf
|
|
@ -0,0 +1,3 @@
|
||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
exec logger -t tokend
|
|
@ -0,0 +1,4 @@
|
||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
exec 2>&1
|
||||||
|
exec tcpsvd -u ctf 0 1 /opt/mcp/bin/in.tokend
|
|
@ -0,0 +1,8 @@
|
||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
## Set up this package
|
||||||
|
|
||||||
|
hostname mcp
|
||||||
|
|
||||||
|
cp -r service/* /var/service
|
||||||
|
cp -r www /var
|
|
@ -48,7 +48,7 @@ main(int argc, char *argv[])
|
||||||
|
|
||||||
|
|
||||||
/* Does the token exist? */
|
/* Does the token exist? */
|
||||||
if (! fgrepx(token, srv_path("tokens.db"))) {
|
if (! fgrepx(token, state_path("tokens.db"))) {
|
||||||
cgi_page("Token does not exist", "");
|
cgi_page("Token does not exist", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ main(int argc, char *argv[])
|
||||||
my_snprintf(line, sizeof(line),
|
my_snprintf(line, sizeof(line),
|
||||||
"%s %s", team, token);
|
"%s %s", team, token);
|
||||||
award_and_log_uniquely(team, category, 1,
|
award_and_log_uniquely(team, category, 1,
|
||||||
"tokens.db", line);
|
state_path("tokens.db"), line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -299,29 +299,51 @@ my_snprintf(char *buf, size_t buflen, char *fmt, ...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
static char *
|
||||||
srv_path(char const *fmt, ...)
|
mkpath(char const *base, char const *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
char relpath[PATH_MAX];
|
char relpath[PATH_MAX];
|
||||||
static char path[PATH_MAX];
|
static char path[PATH_MAX];
|
||||||
char *srv;
|
char const *var;
|
||||||
int len;
|
int len;
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
len = vsnprintf(relpath, sizeof(relpath) - 1, fmt, ap);
|
len = vsnprintf(relpath, sizeof(relpath) - 1, fmt, ap);
|
||||||
va_end(ap);
|
|
||||||
relpath[sizeof(relpath) - 1] = '\0';
|
relpath[sizeof(relpath) - 1] = '\0';
|
||||||
|
|
||||||
srv = getenv("CTF_BASE");
|
var = getenv("CTF_BASE");
|
||||||
if (! srv) {
|
if (! var) {
|
||||||
srv = "/srv/ctf";
|
var = base;
|
||||||
}
|
}
|
||||||
|
|
||||||
my_snprintf(path, sizeof(path), "%s/%s", srv, relpath);
|
my_snprintf(path, sizeof(path), "%s/%s", var, relpath);
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
state_path(char const *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
char *ret;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
ret = mkpath("/var/lib/ctf", fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
package_path(char const *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
char *ret;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
ret = mkpath("/opt", fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
team_exists(char const *teamhash)
|
team_exists(char const *teamhash)
|
||||||
{
|
{
|
||||||
|
@ -341,7 +363,7 @@ team_exists(char const *teamhash)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* stat seems to be the preferred way to check for existence. */
|
/* stat seems to be the preferred way to check for existence. */
|
||||||
ret = stat(srv_path("teams/names/%s", teamhash), &buf);
|
ret = stat(state_path("teams/names/%s", teamhash), &buf);
|
||||||
if (-1 == ret) {
|
if (-1 == ret) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -397,7 +419,7 @@ award_points(char const *teamhash,
|
||||||
token log.
|
token log.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
filename = srv_path("points.new/%d.%d.%s.%s.%ld",
|
filename = state_path("points.new/%d.%d.%s.%s.%ld",
|
||||||
now, getpid(),
|
now, getpid(),
|
||||||
teamhash, category, points);
|
teamhash, category, points);
|
||||||
|
|
||||||
|
@ -424,10 +446,9 @@ void
|
||||||
award_and_log_uniquely(char const *team,
|
award_and_log_uniquely(char const *team,
|
||||||
char const *category,
|
char const *category,
|
||||||
long points,
|
long points,
|
||||||
char const *dbfile,
|
char const *dbpath,
|
||||||
char const *line)
|
char const *line)
|
||||||
{
|
{
|
||||||
char *dbpath = srv_path(dbfile);
|
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
/* Make sure they haven't already claimed these points */
|
/* Make sure they haven't already claimed these points */
|
|
@ -7,6 +7,7 @@
|
||||||
#define CAT_MAX 40
|
#define CAT_MAX 40
|
||||||
#define TOKEN_MAX 40
|
#define TOKEN_MAX 40
|
||||||
|
|
||||||
|
|
||||||
int cgi_init(char *global_argv[]);
|
int cgi_init(char *global_argv[]);
|
||||||
size_t cgi_item(char *str, size_t maxlen);
|
size_t cgi_item(char *str, size_t maxlen);
|
||||||
void cgi_head(char *title);
|
void cgi_head(char *title);
|
||||||
|
@ -17,7 +18,8 @@ void cgi_error(char *fmt, ...);
|
||||||
|
|
||||||
int fgrepx(char const *needle, char const *filename);
|
int fgrepx(char const *needle, char const *filename);
|
||||||
int my_snprintf(char *buf, size_t buflen, char *fmt, ...);
|
int my_snprintf(char *buf, size_t buflen, char *fmt, ...);
|
||||||
char *srv_path(char const *fmt, ...);
|
char *state_path(char const *fmt, ...);
|
||||||
|
char *package_path(char const *fmt, ...);
|
||||||
int team_exists(char const *teamhash);
|
int team_exists(char const *teamhash);
|
||||||
int award_points(char const *teamhacsh,
|
int award_points(char const *teamhacsh,
|
||||||
char const *category,
|
char const *category,
|
|
@ -94,7 +94,7 @@ main(int argc, char *argv[])
|
||||||
int fd;
|
int fd;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
fd = open(srv_path("token.keys/%s", service), O_RDONLY);
|
fd = open(state_path("token.keys/%.*s", (int)servicelen, service), O_RDONLY);
|
||||||
if (-1 == fd) {
|
if (-1 == fd) {
|
||||||
write(1, "!nosvc", 6);
|
write(1, "!nosvc", 6);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -123,8 +123,8 @@ main(int argc, char *argv[])
|
||||||
|
|
||||||
/* Append digest to service name. */
|
/* Append digest to service name. */
|
||||||
tokenlen = (size_t)snprintf(token, sizeof(token),
|
tokenlen = (size_t)snprintf(token, sizeof(token),
|
||||||
"%*s:%s",
|
"%.*s:%s",
|
||||||
servicelen, service, digest);
|
(int)servicelen, service, digest);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write that token out now. */
|
/* Write that token out now. */
|
||||||
|
@ -133,7 +133,7 @@ main(int argc, char *argv[])
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
fd = open(srv_path("tokens.db"), O_WRONLY | O_CREAT, 0666);
|
fd = open(state_path("tokens.db"), O_WRONLY | O_CREAT, 0666);
|
||||||
if (-1 == fd) break;
|
if (-1 == fd) break;
|
||||||
|
|
||||||
ret = lockf(fd, F_LOCK, 0);
|
ret = lockf(fd, F_LOCK, 0);
|
|
@ -59,10 +59,9 @@ main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char needle[400];
|
char needle[400];
|
||||||
|
|
||||||
my_snprintf(needle, sizeof(needle),
|
my_snprintf(needle, sizeof(needle), "%ld %s", points, answer);
|
||||||
"%ld %s", points, answer);
|
|
||||||
if (! fgrepx(needle,
|
if (! fgrepx(needle,
|
||||||
srv_path("packages/%s/answers.txt", category))) {
|
package_path("%s/answers.txt", category))) {
|
||||||
cgi_page("Wrong answer", "");
|
cgi_page("Wrong answer", "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,7 +72,7 @@ main(int argc, char *argv[])
|
||||||
my_snprintf(line, sizeof(line),
|
my_snprintf(line, sizeof(line),
|
||||||
"%s %s %ld", team, category, points);
|
"%s %s %ld", team, category, points);
|
||||||
award_and_log_uniquely(team, category, points,
|
award_and_log_uniquely(team, category, points,
|
||||||
"puzzler.db", line);
|
state_path("puzzler.db"), line);
|
||||||
}
|
}
|
||||||
|
|
||||||
cgi_page("Points awarded",
|
cgi_page("Points awarded",
|
|
@ -58,7 +58,7 @@ main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
FILE *f = fopen(srv_path("puzzler.db"), "r");
|
FILE *f = fopen(state_path("puzzler.db"), "r");
|
||||||
char cat[CAT_MAX];
|
char cat[CAT_MAX];
|
||||||
char points_str[11];
|
char points_str[11];
|
||||||
long points;
|
long points;
|
||||||
|
@ -91,7 +91,7 @@ main(int argc, char *argv[])
|
||||||
if (f) fclose(f);
|
if (f) fclose(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
srv = opendir(srv_path("packages"));
|
srv = opendir(package_path(""));
|
||||||
if (NULL == srv) {
|
if (NULL == srv) {
|
||||||
cgi_error("Cannot opendir(\"/srv\")");
|
cgi_error("Cannot opendir(\"/srv\")");
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ main(int argc, char *argv[])
|
||||||
well just barge ahead and watch for errors. */
|
well just barge ahead and watch for errors. */
|
||||||
|
|
||||||
/* Open /srv/ctf/$cat/puzzles/ */
|
/* Open /srv/ctf/$cat/puzzles/ */
|
||||||
puzzles = opendir(srv_path("packages/%s/puzzles", cat));
|
puzzles = opendir(package_path("%s/puzzles", cat));
|
||||||
if (NULL == puzzles) {
|
if (NULL == puzzles) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
|
@ -14,14 +14,14 @@ mkdir -p $CTF_BASE/points.new
|
||||||
|
|
||||||
# Set up some packages
|
# Set up some packages
|
||||||
for cat in cat1 cat2 cat3; do
|
for cat in cat1 cat2 cat3; do
|
||||||
mkdir -p $CTF_BASE/packages/$cat
|
mkdir -p $CTF_BASE/$cat
|
||||||
cat >$CTF_BASE/packages/$cat/answers.txt <<EOF
|
cat >$CTF_BASE/$cat/answers.txt <<EOF
|
||||||
10 ${cat}answer10
|
10 ${cat}answer10
|
||||||
20 ${cat}answer20
|
20 ${cat}answer20
|
||||||
30 ${cat}answer30
|
30 ${cat}answer30
|
||||||
EOF
|
EOF
|
||||||
for i in 10 20 30; do
|
for i in 10 20 30; do
|
||||||
mkdir -p $CTF_BASE/packages/$cat/puzzles/$i
|
mkdir -p $CTF_BASE/$cat/puzzles/$i
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
@ -13,7 +13,10 @@
|
||||||
<a href="scoreboard.html">Scoreboard</a>
|
<a href="scoreboard.html">Scoreboard</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="puzzles.html">Puzzles</a>
|
<a href="puzzles.cgi">Puzzles</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="teams.html">Teams</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="irc://10.0.0.1/ctf"
|
<a href="irc://10.0.0.1/ctf"
|
||||||
|
@ -24,8 +27,9 @@
|
||||||
<h2>Claim Token</h2>
|
<h2>Claim Token</h2>
|
||||||
<form action="claim.cgi" method="post">
|
<form action="claim.cgi" method="post">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
team: <input name="t" size="8"><br>
|
team:<input name="t" size="8">
|
||||||
token:<input name="k" size="20">
|
token:<input name="k" size="20">
|
||||||
|
<input type="submit" value="claim">
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</form>
|
</form>
|
||||||
|
|
Loading…
Reference in New Issue