Modularize + lots of fixes

This commit is contained in:
Neale Pickett 2010-09-23 18:23:00 -06:00
parent c246ad4d75
commit 48c6ca0aa2
33 changed files with 227 additions and 88 deletions

View File

@ -1,12 +0,0 @@
SUBDIRS = src
all: build
include $(addsuffix /*.mk, $(SUBDIRS))
test: build
./test.sh
build: $(addsuffix -build, $(SUBDIRS))
clean: $(addsuffix -clean, $(SUBDIRS))

View File

@ -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

32
mcp/Makefile Normal file
View File

@ -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)

View File

@ -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.

55
mcp/bin/run-ctf Executable file
View File

@ -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

View File

@ -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.
## ##
## ##

View File

@ -1,5 +1,7 @@
#! /bin/sh #! /bin/sh
cd /var/lib/ctf/teams/names
escape () { escape () {
sed 's/&/\&amp;/g;s/</\&lt;/g;s/>/\&gt;/g' sed 's/&/\&amp;/g;s/</\&lt;/g;s/>/\&gt;/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

5
mcp/service/eth0/run Executable file
View File

@ -0,0 +1,5 @@
#! /bin/sh -e
ifconfig eth0 10.0.0.1 netmask 255.0.0.0
exec inotifyd true $(pwd):x

View File

@ -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
}
}
}

3
mcp/service/mathopd/run Executable file
View File

@ -0,0 +1,3 @@
#! /bin/sh
exec mathopd -n -f ./mathopd.conf >> /var/log/mathopd.log 2>> /var/log/mathopd.error.log

3
mcp/service/mcp/log/run Executable file
View File

@ -0,0 +1,3 @@
#! /bin/sh
exec logger -t mcp

4
mcp/service/mcp/run Executable file
View File

@ -0,0 +1,4 @@
#! /bin/sh
exec 2>&1
exec /opt/mcp/bin/run-ctf

3
mcp/service/tokend/log/run Executable file
View File

@ -0,0 +1,3 @@
#! /bin/sh
exec logger -t tokend

4
mcp/service/tokend/run Executable file
View File

@ -0,0 +1,4 @@
#! /bin/sh
exec 2>&1
exec tcpsvd -u ctf 0 1 /opt/mcp/bin/in.tokend

8
mcp/setup Executable file
View File

@ -0,0 +1,8 @@
#! /bin/sh
## Set up this package
hostname mcp
cp -r service/* /var/service
cp -r www /var

View File

@ -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);
} }
} }

View File

@ -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,9 +419,9 @@ 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);
fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0666); fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0666);
if (-1 == fd) { if (-1 == fd) {
@ -424,11 +446,10 @@ 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 */
if (fgrepx(line, dbpath)) { if (fgrepx(line, dbpath)) {

View File

@ -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,

View File

@ -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);

View File

@ -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",

View File

@ -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;
} }

View File

@ -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

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -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>