installing okay now

This commit is contained in:
Neale Pickett 2015-04-10 16:37:21 -06:00
parent 23e750ed85
commit 4acc889c09
10 changed files with 539 additions and 491 deletions

View File

@ -1,58 +0,0 @@
#! /bin/sh
echo "Figuring out web user..."
for www in www-data http _; do
id $www && break
done
if [ $www = _ ]; then
echo "Unable to determine httpd user on this system. Dying."
exit 1
fi
initialize () {
for i in points.new points.tmp teams; do
mkdir -p state/$i
setfacl -m ${www}:rwx state/$i
done
>> state/points.log
hd < /dev/urandom | awk '{print $3 $4 $5 $6;}' | head -n 100 > state/teams/assigned.txt
}
once () {
if [ -f disabled ]; then
return
fi
if ! [ -d state ]; then
initialize $1
fi
# Collect new points
find state/points.new -type f | while read fn; do
cat $fn >> state/points.log
rm $fn
done
# Generate new puzzles.html
if $KOTH_BASE/puzzles.cgi > www/puzzles.new; then
mv www/puzzles.new www/puzzles.html
fi
# Generate new points.json
if $KOTH_BASE/points > www/points.new; then
mv www/points.new www/points.json
fi
}
cd $(basename $0)
KOTH_BASE=$(pwd)
while true; do
for dn in $KOTH_BASE/*; do
cd $dn
once
done
sleep 5
done

37
bin/new Executable file
View File

@ -0,0 +1,37 @@
#! /bin/sh
newdir=$1
if [ -z "$newdir" ]; then
echo "Usage: $0 NEWDIR"
exit 1
fi
KOTH_BASE=$(cd $(dirname $0)/.. && pwd)
echo "Figuring out web user..."
for www in www-data http _; do
id $www && break
done
if [ $www = _ ]; then
echo "Unable to determine httpd user on this system. Dying."
exit 1
fi
mkdir -p $newdir
cd $newdir
for i in points.new points.tmp teams; do
mkdir -p state/$i
setfacl -m ${www}:rwx state/$i
done
>> state/points.log
if ! [ -f assigned.txt ]; then
hd < /dev/urandom | awk '{print $3 $4 $5 $6;}' | head -n 100 > assigned.txt
fi
mkdir -p www
cp -r $KOTH_BASE/html/* www/
cp $KOTH_BASE/bin/*.cgi www/

30
bin/once Executable file
View File

@ -0,0 +1,30 @@
#! /bin/sh
cd $(dirname $0)
# Do nothing if `disabled` is present
if [ -f disabled ]; then
exit
fi
# Reset to initial state if `reset` is present
if [ -f reset ]; then
rm -f state/teams/* state/points.new/* state/points.tmp/*
> state/points.log
fi
# Collect new points
find state/points.new -type f | while read fn; do
cat $fn >> state/points.log
rm $fn
done
# Generate new puzzles.html
if $KOTH_BASE/puzzles.cgi > www/puzzles.new; then
mv www/puzzles.new www/puzzles.html
fi
# Generate new points.json
if $KOTH_BASE/points > www/points.new; then
mv www/points.new www/points.json
fi

View File

@ -40,7 +40,7 @@ EOF
if [ -z "$hash" ] || [ -z "$team" ]; then
echo "<p>Empty field, cannot complete request</p>"
elif ! grep -q "^$hash$" state/teams/assigned.txt; then
elif ! grep -q "^$hash$" assigned.txt; then
echo "<p>That hash has not been assigned.</p>"
elif [ -f state/teams/names/$hash ]; then
echo "<p>That hash has already been registered.</p>"

View File

@ -8,7 +8,7 @@
<h1>Credits</h1>
<section>
<p>Dirtbags King of the Hill was created by:</p>
<h2>Created By</h2>
<ul>
<li>Neale Pickett</li>
@ -26,16 +26,21 @@
<li>William Phillips</li>
<li>Should your name be here? Please remind me!</li>
</ul>
</section>
<p>Parts of this contest were inspired by contests from:</p>
<section>
<h2>Inspiration</h2>
<ul>
<li>DC949</li>
<li>Tube Warriors</li>
<li>Sandia National Laboratories</li>
</ul>
</section>
<section>
<h2>Thanks</h2>
<p>
Lastly, this contest would not exist were it not for hundreds of
This contest would not exist were it not for hundreds of
thousands of lines of code from free software authors around the
world, including:
</p>

View File

@ -6,7 +6,15 @@
<link rel="stylesheet" href="css/style.css" type="text/css">
</head>
<body>
<h1>Tracer FIRE 6</h1>
<h1>Tracer FIRE</h1>
<nav>
<ul>
<li><a href="register.html">Register</a></li>
<li><a href="puzzles.html">Puzzles</a></li>
<li><a href="scoreboard.html">Scoreboard</a></li>
</ul>
</nav>
<section>
<h2>Getting Started</h2>
@ -42,7 +50,7 @@
<h2>Reading Material</h2>
<p>
Stuck? Need a break? In the bathroom?
Stuck? Taking a break?
Here are some things to read.
</p>
@ -57,12 +65,5 @@
</ul>
</section>
<nav>
<ul>
<li><a href="register.html">Register</a></li>
<li><a href="puzzles.html">Puzzles</a></li>
<li><a href="scoreboard.html">Scoreboard</a></li>
</ul>
</nav>
</body>
</html>

View File

@ -2,10 +2,12 @@
<html>
<head>
<title>Team Registration</title>
<link rel="stylesheet" href="ctf.css" type="text/css">
<link rel="stylesheet" href="css/style.css" type="text/css">
</head>
<body>
<h1>Team Registration</h1>
<section>
<p>
Before you can use a token, you must choose a team name.
You can only do this once per token,
@ -21,5 +23,6 @@
<br>
<input type="submit" value="Register">
</form>
</section>
</body>
</html>

60
install
View File

@ -1,6 +1,11 @@
#! /bin/sh
DESTDIR=${1:-/opt/koth}
DESTDIR=$1
if [ -z "$DESTDIR" ]; then
echo "Usage: $0 DESTDIR"
exit
fi
cd $(dirname $0)
@ -14,15 +19,6 @@ older () {
return 1
}
html () {
target=$DESTDIR/${1%mdwn}html
if older $target $1 tmpl/*; then
echo "HTML $1"
mkdir -p $(dirname $target)
./tmpl/mdwntohtml < $1 > $target
fi
}
copy () {
target=$DESTDIR/$1
if older $target $1; then
@ -41,6 +37,41 @@ cc () {
fi
}
cgi () {
target=$DESTDIR/www/$(basename $1 .c)
if older $target $@; then
mkdir -p $(dirname $target)
src=$1; shift
echo "CC $src"
gcc -Wall -Werror -o $target $@ src/common.c $src
fi
}
setup() {
echo "SETUP"
for i in points.new points.tmp teams; do
dir=$DESTDIR/state/$i
mkdir -p $dir
setfacl -m ${www}:rwx $dir
done
>> $DESTDIR/state/points.log
if ! [ -f $DESTDIR/assigned.txt ]; then
hd </dev/urandom | awk '{print $3 $4 $5 $6;}' | head -n 100 > assigned.txt
fi
}
echo "Figuring out web user..."
for www in www-data http _; do
id $www && break
done
if [ $www = _ ]; then
echo "Unable to determine httpd user on this system. Dying."
exit 1
fi
mkdir -p $DESTDIR || exit 1
git ls-files | while read fn; do
case "$fn" in
install|.*)
@ -53,8 +84,13 @@ git ls-files | while read fn; do
bin/*)
copy $fn
;;
src/*.cgi.c|src/pointscli.c)
cc src/common.c $fn
src/common.c)
;;
src/pointscli.c)
cc $fn src/common.c
;;
src/*.cgi.c)
cgi $fn
;;
src/*.c)
cc $fn

View File

@ -12,9 +12,9 @@
#include "common.h"
#ifdef NODUMP
# define DUMPf(fmt, args...)
#define DUMPf(fmt, args...)
#else
# define DUMPf(fmt, args...) fprintf(stderr, "%s:%s:%d " fmt "\n", __FILE__, __FUNCTION__, __LINE__, ##args)
#define DUMPf(fmt, args...) fprintf(stderr, "%s:%s:%d " fmt "\n", __FILE__, __FUNCTION__, __LINE__, ##args)
#endif
#define DUMP() DUMPf("")
#define DUMP_d(v) DUMPf("%s = %d", #v, v)
@ -47,9 +47,9 @@ read_char_argv()
p = argv[1];
}
if (! p) {
if (!p) {
return EOF;
} else if (! *p) {
} else if (!*p) {
arg += 1;
p = argv[arg];
return '&';
@ -88,29 +88,29 @@ read_char_stdin()
static int
read_char_query_string()
{
static char *p = (char *)-1;
static char *p = (char *) -1;
if ((char *)-1 == p) {
if ((char *) -1 == p) {
p = getenv("QUERY_STRING");
}
if (! p) {
if (!p) {
return EOF;
} else if (! *p) {
} else if (!*p) {
return EOF;
} else {
return *(p++);
}
}
static int (* read_char)() = read_char_argv;
static int (*read_char) () = read_char_argv;
int
cgi_init(char *global_argv[])
{
char *rm = getenv("REQUEST_METHOD");
if (! rm) {
if (!rm) {
read_char = read_char_argv;
argv = global_argv;
} else if (0 == strcmp(rm, "POST")) {
@ -121,11 +121,7 @@ cgi_init(char *global_argv[])
is_cgi = 1;
} else {
printf(("405 Method not allowed\r\n"
"Allow: GET, POST\r\n"
"Content-type: text/plain\r\n"
"\r\n"
"%s is not allowed.\n"),
rm);
"Allow: GET, POST\r\n" "Content-type: text/plain\r\n" "\r\n" "%s is not allowed.\n"), rm);
return -1;
}
@ -153,12 +149,12 @@ read_hex()
int a = read_char();
int b = read_char();
return tonum(a)*16 + tonum(b);
return tonum(a) * 16 + tonum(b);
}
/* Read a key or a value. Since & and = aren't supposed to appear
outside of boundaries, we can use the same function for both.
*/
/*
* Read a key or a value. Since & and = aren't supposed to appear outside of boundaries, we can use the same function for both.
*/
size_t
cgi_item(char *str, size_t maxlen)
{
@ -197,19 +193,15 @@ cgi_head(char *title)
"<html>\n"
" <head>\n"
" <title>%s</title>\n"
" <link rel=\"stylesheet\" href=\"ctf.css\" type=\"text/css\">\n"
" <link rel=\"stylesheet\" href=\"css/style.css\">\n"
" </head>\n"
" <body>\n"
" <h1>%s</h1>\n"),
title, title);
" <body><h1>%s</h1><section>\n"), title, title);
}
void
cgi_foot()
{
printf("\n"
" </body>\n"
"</html>\n");
printf("\n</section></body></html>\n");
}
void
@ -237,7 +229,8 @@ cgi_fail(int err)
case ERR_NOTEAM:
cgi_result(409, "No such team", "<p>There is no team with that hash.</p>");
case ERR_CLAIMED:
cgi_result(409, "Already claimed", "<p>That is the correct answer, but your team has already claimed these points.</p>");
cgi_result(409, "Already claimed",
"<p>That is the correct answer, but your team has already claimed these points.</p>");
default:
cgi_result(409, "Failure", "<p>Failure code: %d</p>", err);
}
@ -267,7 +260,9 @@ cgi_error(char *text)
* Common routines
*/
/* cut -d$ANCHOR -f2- | grep -Fx "$NEEDLE" */
/*
* cut -d$ANCHOR -f2- | grep -Fx "$NEEDLE"
*/
int
anchored_search(char const *filename, char const *needle, char const anchor)
{
@ -283,10 +278,12 @@ anchored_search(char const *filename, char const *needle, char const anchor)
break;
}
/* Find anchor */
/*
* Find anchor
*/
if (anchor) {
p = strchr(line, anchor);
if (! p) {
if (!p) {
continue;
}
p += 1;
@ -294,17 +291,18 @@ anchored_search(char const *filename, char const *needle, char const anchor)
p = line;
}
/* Don't bother with strcmp if string lengths differ.
If this string is shorter than the previous, it's okay. This is
just a performance hack.
/*
* Don't bother with strcmp if string lengths differ. If this string is shorter than the previous, it's okay. This
* is just a performance hack.
*/
if ((p[nlen] != '\n') &&
(p[nlen] != '\0')) {
if ((p[nlen] != '\n') && (p[nlen] != '\0')) {
continue;
}
p[nlen] = 0;
/* Okay, now we can compare! */
/*
* Okay, now we can compare!
*/
if (0 == strcmp(p, needle)) {
ret = 1;
break;
@ -336,12 +334,14 @@ urandom(char *buf, size_t buflen)
}
}
/* Fall back to libc's crappy thing */
/*
* Fall back to libc's crappy thing
*/
{
int i;
for (i = 0; i < buflen; i += 1) {
buf[i] = (char)random();
buf[i] = (char) random();
}
}
}
@ -374,7 +374,9 @@ ctf_chdir()
}
initialized = 1;
/* chdir to $CTF_BASE */
/*
* chdir to $CTF_BASE
*/
{
char const *ctf_base = getenv("CTF_BASE");
@ -383,12 +385,13 @@ ctf_chdir()
}
}
/* Keep going up one directory until there's a packages directory */
/*
* Keep going up one directory until there's a packages directory
*/
for (i = 0; i < 5; i += 1) {
struct stat st;
if ((0 == stat("packages", &st)) &&
S_ISDIR(st.st_mode)) {
if ((0 == stat("packages", &st)) && S_ISDIR(st.st_mode)) {
return;
}
chdir("..");
@ -408,7 +411,9 @@ mkpath(char const *type, char const *fmt, va_list ap)
vsnprintf(relpath, sizeof(relpath) - 1, fmt, ap);
relpath[sizeof(relpath) - 1] = '\0';
/* $CTF_BASE/type/relpath */
/*
* $CTF_BASE/type/relpath
*/
my_snprintf(path, sizeof(path), "%s/%s", type, relpath);
return path;
}
@ -445,18 +450,22 @@ team_exists(char const *teamhash)
int ret;
int i;
if ((! teamhash) || (! *teamhash)) {
if ((!teamhash) || (!*teamhash)) {
return 0;
}
/* Check for invalid characters. */
/*
* Check for invalid characters.
*/
for (i = 0; teamhash[i]; i += 1) {
if (! isalnum(teamhash[i])) {
if (!isalnum(teamhash[i])) {
return 0;
}
}
/* stat seems to be the preferred way to check for existence. */
/*
* stat seems to be the preferred way to check for existence.
*/
ret = stat(state_path("teams/names/%s", teamhash), &buf);
if (-1 == ret) {
return 0;
@ -465,16 +474,11 @@ team_exists(char const *teamhash)
return 1;
}
/* Return values:
-1: general error
-2: no such team
-3: points already awarded
/*
* Return values: -1: general error -2: no such team -3: points already awarded
*/
int
award_points(char const *teamhash,
char const *category,
const long points,
char const *uid)
award_points(char const *teamhash, char const *category, const long points, char const *uid)
{
char line[100];
int linelen;
@ -482,13 +486,11 @@ award_points(char const *teamhash,
FILE *f;
time_t now = time(NULL);
if (! team_exists(teamhash)) {
if (!team_exists(teamhash)) {
return ERR_NOTEAM;
}
linelen = snprintf(line, sizeof(line),
"%s %s %ld %s",
teamhash, category, points, uid);
linelen = snprintf(line, sizeof(line), "%s %s %ld %s", teamhash, category, points, uid);
if (sizeof(line) <= linelen) {
return ERR_GENERAL;
}
@ -497,46 +499,39 @@ award_points(char const *teamhash,
return ERR_CLAIMED;
}
/* At one time I had this writing to a single log file, using lockf.
This works, as long as nobody ever tries to edit the log file.
Editing the log file would require locking it, which would block
everything trying to score, effectively taking down the entire
contest. If you can't lock it first--and nothing in busybox lets
you do this--you have to bring down pretty much everything manually
anyway.
By putting new scores into new files and periodically appending
those files to the main log file, it is possible to stop the thing
that appends, edit the file at leisure, and then start the appender
back up, all without affecting things trying to score: they're
still able to record their score and move on.
/*
* At one time I had this writing to a single log file, using lockf. This works, as long as nobody ever tries to edit the
* log file. Editing the log file would require locking it, which would block everything trying to score, effectively
* taking down the entire contest. If you can't lock it first--and nothing in busybox lets you do this--you have to bring
* down pretty much everything manually anyway.
*
* By putting new scores into new files and periodically appending those files to the main log file, it is possible to stop
* the thing that appends, edit the file at leisure, and then start the appender back up, all without affecting things
* trying to score: they're still able to record their score and move on.
*/
filename = state_path("points.tmp/%lu.%d.%s.%s.%ld",
(unsigned long)now, getpid(),
teamhash, category, points);
filename = state_path("points.tmp/%lu.%d.%s.%s.%ld", (unsigned long) now, getpid(), teamhash, category, points);
f = fopen(filename, "w");
if (! f) {
if (!f) {
return ERR_GENERAL;
}
if (EOF == fprintf(f, "%lu %s\n", (unsigned long)now, line)) {
if (EOF == fprintf(f, "%lu %s\n", (unsigned long) now, line)) {
return ERR_GENERAL;
}
fclose(f);
/* Rename into points.new */
/*
* Rename into points.new
*/
{
char ofn[PATH_MAX];
strncpy(ofn, filename, sizeof(ofn));
filename = state_path("points.new/%lu.%d.%s.%s.%ld",
(unsigned long)now, getpid(),
teamhash, category, points);
filename = state_path("points.new/%lu.%d.%s.%s.%ld", (unsigned long) now, getpid(), teamhash, category, points);
rename(ofn, filename);
}
return 0;
}

View File

@ -12,8 +12,7 @@ main(int argc, char *argv[])
char comment[512];
if (argc != 5) {
fprintf(stderr,
"Usage: pointscli TEAM CATEGORY POINTS 'COMMENT'\n");
fprintf(stderr, "Usage: pointscli TEAM CATEGORY POINTS 'COMMENT'\n");
return EX_USAGE;
}
ctf_chdir();