mirror of https://github.com/dirtbags/moth.git
Many changes, unit test
* Everything in /srv/ctf now, set $CTF_BASE to override that * CGI now accepts parms in argv * Fix bug with uninitialized CGI vars
This commit is contained in:
parent
507dd93d88
commit
8d47593986
|
@ -1,11 +1,11 @@
|
|||
TARGETS = in.tokend claim.cgi puzzler.cgi pointscli puzzles
|
||||
TARGETS = in.tokend pointscli claim.cgi puzzler.cgi puzzles.cgi
|
||||
|
||||
all: $(TARGETS)
|
||||
|
||||
in.tokend: in.tokend.o xxtea.o
|
||||
puzzles: puzzles.o common.o
|
||||
in.tokend: in.tokend.o xxtea.o common.o
|
||||
pointscli: pointscli.o common.o
|
||||
|
||||
puzzles.cgi: puzzles.cgi.o common.o
|
||||
claim.cgi: claim.cgi.o common.o
|
||||
puzzler.cgi: puzzler.cgi.o common.o
|
||||
|
||||
|
|
|
@ -1,19 +1,16 @@
|
|||
#include <stdlib.h>
|
||||
#include "common.h"
|
||||
|
||||
char const *tokenlog = "/var/lib/ctf/tokend/tokens.log";
|
||||
char const *claimlog = "/var/lib/ctf/tokend/claim.log";
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
char team[9];
|
||||
char token[100];
|
||||
|
||||
/* XXX: This code needs to be tested */
|
||||
return 1;
|
||||
team[0] = 0;
|
||||
token[0] = 0;
|
||||
|
||||
if (-1 == cgi_init()) {
|
||||
if (-1 == cgi_init(argv)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -53,7 +50,7 @@ main(int argc, char *argv[])
|
|||
|
||||
|
||||
/* Does the token exist? */
|
||||
if (! fgrepx(token, tokenlog)) {
|
||||
if (! fgrepx(token, srv_path("tokens.db"))) {
|
||||
cgi_page("Token does not exist", "");
|
||||
}
|
||||
|
||||
|
@ -69,7 +66,8 @@ main(int argc, char *argv[])
|
|||
category[i] = '\0';
|
||||
|
||||
award_and_log_uniquely(team, category, 1,
|
||||
claimlog, "%s %s", team, token);
|
||||
"tokens.db",
|
||||
"%s %s", team, token);
|
||||
}
|
||||
|
||||
|
||||
|
|
159
src/common.c
159
src/common.c
|
@ -6,39 +6,56 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <values.h>
|
||||
#include <time.h>
|
||||
#include "common.h"
|
||||
|
||||
/*
|
||||
* CGI
|
||||
*/
|
||||
static size_t inlen = 0;
|
||||
static int is_cgi = 0;
|
||||
static char **argv = NULL;
|
||||
|
||||
int
|
||||
cgi_init()
|
||||
static int
|
||||
read_char_argv()
|
||||
{
|
||||
char *rm = getenv("REQUEST_METHOD");
|
||||
static int arg = 0;
|
||||
static char *p;
|
||||
|
||||
if (! (rm && (0 == strcmp(rm, "POST")))) {
|
||||
printf("405 Method not allowed\r\n"
|
||||
"Allow: POST\r\n"
|
||||
"Content-type: text/html\r\n"
|
||||
"\r\n"
|
||||
"<h1>Method not allowed</h1>\n"
|
||||
"<p>I only speak POST. Sorry.</p>\n");
|
||||
return -1;
|
||||
if (NULL == argv) {
|
||||
return EOF;
|
||||
}
|
||||
|
||||
inlen = atoi(getenv("CONTENT_LENGTH"));
|
||||
is_cgi = 1;
|
||||
if (0 == arg) {
|
||||
arg = 1;
|
||||
p = argv[1];
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (! p) {
|
||||
return EOF;
|
||||
} else if (! *p) {
|
||||
arg += 1;
|
||||
p = argv[arg];
|
||||
return '&';
|
||||
}
|
||||
|
||||
return *(p++);
|
||||
}
|
||||
|
||||
static int
|
||||
read_char()
|
||||
read_char_stdin()
|
||||
{
|
||||
static int inlen = -1;
|
||||
|
||||
if (-1 == inlen) {
|
||||
char *p = getenv("CONTENT_LENGTH");
|
||||
if (p) {
|
||||
inlen = atoi(p);
|
||||
} else {
|
||||
inlen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (inlen) {
|
||||
inlen -= 1;
|
||||
return getchar();
|
||||
|
@ -46,6 +63,53 @@ read_char()
|
|||
return EOF;
|
||||
}
|
||||
|
||||
static int
|
||||
read_char_query_string()
|
||||
{
|
||||
static char *p = (char *)-1;
|
||||
|
||||
if ((char *)-1 == p) {
|
||||
p = getenv("QUERY_STRING");
|
||||
}
|
||||
|
||||
if (! p) {
|
||||
return EOF;
|
||||
} else if (! *p) {
|
||||
return EOF;
|
||||
} else {
|
||||
return *(p++);
|
||||
}
|
||||
}
|
||||
|
||||
static int (* read_char)() = read_char_argv;
|
||||
|
||||
int
|
||||
cgi_init(char *global_argv[])
|
||||
{
|
||||
char *rm = getenv("REQUEST_METHOD");
|
||||
|
||||
if (! rm) {
|
||||
read_char = read_char_argv;
|
||||
argv = global_argv;
|
||||
} else if (0 == strcmp(rm, "POST")) {
|
||||
read_char = read_char_stdin;
|
||||
is_cgi = 1;
|
||||
} else if (0 == strcmp(rm, "GET")) {
|
||||
read_char = read_char_query_string;
|
||||
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);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char
|
||||
tonum(int c)
|
||||
{
|
||||
|
@ -207,22 +271,48 @@ my_snprintf(char *buf, size_t buflen, char *fmt, ...)
|
|||
va_start(ap, fmt);
|
||||
len = vsnprintf(buf, buflen - 1, fmt, ap);
|
||||
va_end(ap);
|
||||
if (len >= 0) {
|
||||
buf[len] = '\0';
|
||||
return len;
|
||||
buf[buflen] = '\0';
|
||||
if (len >= buflen) {
|
||||
return buflen - 1;
|
||||
} else {
|
||||
return -1;
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
srv_path(char const *fmt, ...)
|
||||
{
|
||||
char relpath[PATH_MAX];
|
||||
static char path[PATH_MAX];
|
||||
char *srv;
|
||||
int len;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
len = vsnprintf(relpath, sizeof(relpath) - 1, fmt, ap);
|
||||
va_end(ap);
|
||||
relpath[sizeof(relpath) - 1] = '\0';
|
||||
|
||||
srv = getenv("CTF_BASE");
|
||||
if (! srv) {
|
||||
srv = "/srv/ctf";
|
||||
}
|
||||
|
||||
my_snprintf(path, sizeof(path), "%s/%s", srv, relpath);
|
||||
return path;
|
||||
}
|
||||
|
||||
int
|
||||
team_exists(char const *teamhash)
|
||||
{
|
||||
struct stat buf;
|
||||
char filename[100];
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if ((! teamhash) || (! *teamhash)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check for invalid characters. */
|
||||
for (i = 0; teamhash[i]; i += 1) {
|
||||
if (! isalnum(teamhash[i])) {
|
||||
|
@ -230,15 +320,8 @@ team_exists(char const *teamhash)
|
|||
}
|
||||
}
|
||||
|
||||
/* Build filename. */
|
||||
ret = snprintf(filename, sizeof(filename),
|
||||
"%s/%s", teamdir, teamhash);
|
||||
if (sizeof(filename) <= ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* lstat seems to be the preferred way to check for existence. */
|
||||
ret = lstat(filename, &buf);
|
||||
ret = lstat(srv_path("teams/names/%s", teamhash), &buf);
|
||||
if (-1 == ret) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -253,8 +336,7 @@ award_points(char const *teamhash,
|
|||
{
|
||||
char line[100];
|
||||
int linelen;
|
||||
char filename[100];
|
||||
int filenamelen;
|
||||
char *filename;
|
||||
int fd;
|
||||
int ret;
|
||||
time_t now = time(NULL);
|
||||
|
@ -296,13 +378,9 @@ award_points(char const *teamhash,
|
|||
token log.
|
||||
*/
|
||||
|
||||
filenamelen = snprintf(filename, sizeof(filename),
|
||||
"%s/%d.%d.%s.%s.%ld",
|
||||
pointsdir, now, getpid(),
|
||||
filename = srv_path("points.new/%d.%d.%s.%s.%ld",
|
||||
now, getpid(),
|
||||
teamhash, category, points);
|
||||
if (sizeof(filename) <= filenamelen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0666);
|
||||
if (-1 == fd) {
|
||||
|
@ -322,9 +400,10 @@ void
|
|||
award_and_log_uniquely(char const *team,
|
||||
char const *category,
|
||||
long points,
|
||||
char const *logfile,
|
||||
char const *dbfile,
|
||||
char const *fmt, ...)
|
||||
{
|
||||
char *dbpath = srv_path(dbfile);
|
||||
char line[200];
|
||||
int len;
|
||||
int ret;
|
||||
|
@ -338,13 +417,13 @@ award_and_log_uniquely(char const *team,
|
|||
if (sizeof(line) <= len) {
|
||||
cgi_error("Log line too long");
|
||||
}
|
||||
if (fgrepx(line, logfile)) {
|
||||
if (fgrepx(line, dbpath)) {
|
||||
cgi_page("Already claimed",
|
||||
"<p>Your team has already claimed these points.</p>");
|
||||
}
|
||||
|
||||
/* Open and lock logfile */
|
||||
fd = open(logfile, O_WRONLY | O_CREAT, 0666);
|
||||
fd = open(dbpath, O_WRONLY | O_CREAT, 0666);
|
||||
if (-1 == fd) {
|
||||
cgi_error("Unable to open log");
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#define TEAM_MAX 40
|
||||
#define CAT_MAX 40
|
||||
|
||||
int cgi_init();
|
||||
int cgi_init(char *global_argv[]);
|
||||
size_t cgi_item(char *str, size_t maxlen);
|
||||
void cgi_head(char *title);
|
||||
void cgi_foot();
|
||||
|
@ -14,12 +14,10 @@ void cgi_page(char *title, char *fmt, ...);
|
|||
void cgi_error(char *fmt, ...);
|
||||
|
||||
|
||||
#define teamdir "/var/lib/ctf/teams/names"
|
||||
#define pointsdir "/var/lib/ctf/points/new"
|
||||
|
||||
int fgrepx(char const *needle, char const *filename);
|
||||
char *srv_path(char const *fmt, ...);
|
||||
int team_exists(char const *teamhash);
|
||||
int award_points(char const *teamhash,
|
||||
int award_points(char const *teamhacsh,
|
||||
char const *category,
|
||||
long point);
|
||||
void award_and_log_uniquely(char const *team,
|
||||
|
|
|
@ -8,13 +8,11 @@
|
|||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <ctype.h>
|
||||
#include "common.h"
|
||||
#include "xxtea.h"
|
||||
|
||||
#define itokenlen 3
|
||||
|
||||
char const *keydir = "/var/lib/ctf/tokend/keys";
|
||||
char const *tokenlog = "/var/lib/ctf/tokend/tokens.log";
|
||||
|
||||
char const consonants[] = "bcdfghklmnprstvz";
|
||||
char const vowels[] = "aeiouy";
|
||||
|
||||
|
@ -91,16 +89,10 @@ main(int argc, char *argv[])
|
|||
|
||||
/* Read in that service's key. */
|
||||
{
|
||||
char path[100];
|
||||
int fd;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
ret = snprintf(path, sizeof(path),
|
||||
"%s/%s.key", keydir, service);
|
||||
if (ret < sizeof(path)) {
|
||||
fd = open(path, O_RDONLY);
|
||||
}
|
||||
fd = open(srv_path("token.keys/%s", service), O_RDONLY);
|
||||
if (-1 == fd) {
|
||||
write(1, "!nosvc", 6);
|
||||
return 0;
|
||||
|
@ -139,7 +131,7 @@ main(int argc, char *argv[])
|
|||
int ret;
|
||||
|
||||
do {
|
||||
fd = open(tokenlog, O_WRONLY | O_CREAT, 0644);
|
||||
fd = open(srv_path("tokens.db"), O_WRONLY | O_CREAT, 0644);
|
||||
if (-1 == fd) break;
|
||||
|
||||
ret = lockf(fd, F_LOCK, 0);
|
||||
|
|
|
@ -1,18 +1,21 @@
|
|||
#include <stdlib.h>
|
||||
#include "common.h"
|
||||
|
||||
char const *logfile = "/var/lib/ctf/puzzler.log";
|
||||
|
||||
int
|
||||
main(int argc, char *argv)
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
char team[TEAM_MAX];
|
||||
char category[CAT_MAX];
|
||||
char points_str[5];
|
||||
char answer[500];
|
||||
long points;
|
||||
long points = 0;
|
||||
|
||||
if (-1 == cgi_init()) {
|
||||
team[0] = 0;
|
||||
category[0] = 0;
|
||||
answer[0] = 0;
|
||||
|
||||
if (-1 == cgi_init(argv)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -58,26 +61,24 @@ main(int argc, char *argv)
|
|||
|
||||
/* Check answer (also assures category exists) */
|
||||
{
|
||||
char filename[100];
|
||||
char needle[400];
|
||||
|
||||
my_snprintf(filename, sizeof(filename),
|
||||
"/srv/%s/answers.txt", category);
|
||||
my_snprintf(needle, sizeof(needle),
|
||||
"%ld %s", points, answer);
|
||||
if (! fgrepx(needle, filename)) {
|
||||
if (! fgrepx(needle,
|
||||
srv_path("packages/%s/answers.txt", category))) {
|
||||
cgi_page("Wrong answer", "");
|
||||
}
|
||||
}
|
||||
|
||||
award_and_log_uniquely(team, category, points,
|
||||
logfile, "%s %s %ld", team, category, points);
|
||||
"puzzler.db",
|
||||
"%s %s %ld", team, category, points);
|
||||
|
||||
cgi_page("Points awarded",
|
||||
("<p>%d points for %s.</p>\n"
|
||||
"<p>Patience please: it may be up to 1 minute before "
|
||||
"the next puzzle opens in this category.</p>"),
|
||||
points, team);
|
||||
("<p>%d points for %s.</p>"
|
||||
"<!-- awarded %d -->"),
|
||||
points, team, points);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ int ncats = 0;
|
|||
void
|
||||
read_points_by_cat()
|
||||
{
|
||||
FILE *f = fopen("/var/lib/ctf/puzzler.log", "r");
|
||||
FILE *f = fopen(srv_path("puzzler.db"), "r");
|
||||
char cat[CAT_MAX];
|
||||
long points;
|
||||
int i;
|
||||
|
@ -59,10 +59,13 @@ main(int argc, char *argv[])
|
|||
int i;
|
||||
DIR *srv;
|
||||
|
||||
if (-1 == cgi_init(argv)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
read_points_by_cat();
|
||||
|
||||
/* Open /srv/ */
|
||||
srv = opendir("/srv");
|
||||
srv = opendir(srv_path("packages"));
|
||||
if (NULL == srv) {
|
||||
cgi_error("Cannot opendir(\"/srv\")");
|
||||
}
|
||||
|
@ -75,7 +78,6 @@ main(int argc, char *argv[])
|
|||
struct dirent *e = readdir(srv);
|
||||
char *cat = e->d_name;
|
||||
DIR *puzzles;
|
||||
char path[PATH_MAX];
|
||||
long catpoints[PUZZLES_MAX];
|
||||
size_t ncatpoints = 0;
|
||||
|
||||
|
@ -84,9 +86,8 @@ main(int argc, char *argv[])
|
|||
/* We have to lstat anyway to see if it's a directory; may as
|
||||
well just barge ahead and watch for errors. */
|
||||
|
||||
/* Open /srv/$cat/puzzles/ */
|
||||
my_snprintf(path, sizeof(path), "/srv/%s/puzzles", cat);
|
||||
puzzles = opendir(path);
|
||||
/* Open /srv/ctf/$cat/puzzles/ */
|
||||
puzzles = opendir(srv_path("packages/%s/puzzles", cat));
|
||||
if (NULL == puzzles) {
|
||||
continue;
|
||||
}
|
10
src/register
10
src/register
|
@ -8,9 +8,11 @@ fi
|
|||
# Don't overwrite files
|
||||
set -C
|
||||
|
||||
base=${CTF_BASE:-/srv/ctf}
|
||||
|
||||
# Assign a color. I spent two days selecting this color pallette for
|
||||
# people with protanopia. Please don't change these colors.
|
||||
nteams=$(ls /var/lib/ctf/teams/names/ | wc -l)
|
||||
nteams=$(ls $base/teams/names/ | wc -l)
|
||||
case $(expr $nteams % 15) in
|
||||
0) color=8c7a69 ;;
|
||||
1) color=7f7062 ;;
|
||||
|
@ -39,7 +41,7 @@ esac
|
|||
# me since all team hashes are in the set /[0-9a-f]{8}/.
|
||||
hash=$(echo "$1" | md5sum | cut -b 1-8)
|
||||
|
||||
echo "$1" > /var/lib/ctf/teams/names/$hash
|
||||
echo "$color" > /var/lib/ctf/teams/colors/$hash
|
||||
echo "$1" > $base/teams/names/$hash
|
||||
echo "$color" > $base/teams/colors/$hash
|
||||
|
||||
echo "Registered with hash $hash"
|
||||
echo "Registered with hash: $hash"
|
||||
|
|
|
@ -63,6 +63,11 @@ function output( t, c) {
|
|||
}
|
||||
|
||||
BEGIN {
|
||||
base = ENVIRON["CTF_BASE"]
|
||||
if (! base) {
|
||||
base = "/srv/ctf"
|
||||
}
|
||||
|
||||
# Only display two decimal places
|
||||
CONVFMT = "%.2f"
|
||||
|
||||
|
@ -95,11 +100,11 @@ BEGIN {
|
|||
|
||||
# Get team colors and names
|
||||
for (team in teams) {
|
||||
fn = "/var/lib/ctf/teams/colors/" team
|
||||
fn = base "/teams/colors/" team
|
||||
getline colors_by_team[team] < fn
|
||||
close(fn)
|
||||
|
||||
fn = "/var/lib/ctf/teams/names/" team
|
||||
fn = base "/teams/names/" team
|
||||
getline names_by_team[team] < fn
|
||||
close(fn)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
#! /bin/sh -e
|
||||
|
||||
die () {
|
||||
echo $*
|
||||
exit 1
|
||||
}
|
||||
|
||||
CTF_BASE=/tmp/ctf-test.$$ export CTF_BASE
|
||||
trap "rm -rf $CTF_BASE" 0
|
||||
mkdir $CTF_BASE
|
||||
|
||||
# Some skeletal structure
|
||||
mkdir -p $CTF_BASE/points.new
|
||||
|
||||
# Set up some packages
|
||||
for cat in cat1 cat2 cat3; do
|
||||
mkdir -p $CTF_BASE/packages/$cat
|
||||
cat >$CTF_BASE/packages/$cat/answers.txt <<EOF
|
||||
10 ${cat}answer10
|
||||
20 ${cat}answer20
|
||||
30 ${cat}answer30
|
||||
EOF
|
||||
for i in 10 20 30; do
|
||||
mkdir -p $CTF_BASE/packages/$cat/puzzles/$i
|
||||
done
|
||||
done
|
||||
|
||||
# Set up some teams
|
||||
mkdir -p $CTF_BASE/teams/names
|
||||
mkdir -p $CTF_BASE/teams/colors
|
||||
for team in team1 team2 team3; do
|
||||
hash=$(./register $team | awk '{print $NF;}')
|
||||
done
|
||||
|
||||
|
||||
##
|
||||
## Puzzler tests
|
||||
##
|
||||
|
||||
if ./puzzles.cgi | grep 20; then
|
||||
die "20 points puzzles shouldn't show up here"
|
||||
fi
|
||||
|
||||
if ./puzzler.cgi t=$hash c=cat1 p=10 a=cat1answer20 | grep -q 'awarded'; then
|
||||
die "Awarded points with wrong answer"
|
||||
fi
|
||||
|
||||
if ./puzzler.cgi t=$hash c=cat2 p=10 a=cat1answer10 | grep -q 'awarded'; then
|
||||
die "Awarded points with wrong category"
|
||||
fi
|
||||
|
||||
if ./puzzler.cgi t=$hash c=cat1 p=20 a=cat1answer10 | grep -q 'awarded'; then
|
||||
die "Awarded points with wrong point value"
|
||||
fi
|
||||
|
||||
if ./puzzler.cgi t=merfmerfmerfmerf c=cat2 p=10 a=cat1answer10 | grep -q 'awarded'; then
|
||||
die "Awarded points with bad team"
|
||||
fi
|
||||
|
||||
if ! ./puzzler.cgi t=$hash c=cat1 p=10 a=cat1answer10 | grep -q 'awarded 10'; then
|
||||
die "Didn't award points for correct answer"
|
||||
fi
|
||||
|
||||
if ! ./puzzles.cgi | grep -q 20; then
|
||||
die "20 point answer didn't show up"
|
||||
fi
|
||||
|
||||
if ./puzzler.cgi t=$hash c=cat1 p=10 a=cat1answer10 | grep -q 'awarded 10'; then
|
||||
die "Awarded same points twice"
|
||||
fi
|
||||
|
||||
##
|
||||
## Scoreboard tests
|
||||
##
|
||||
|
||||
if ! cat $CTF_BASE/points.new/* | ./scoreboard | grep -q 'total.*team3: 1'; then
|
||||
die "Scoreboard total incorrect"
|
||||
fi
|
||||
|
||||
if ! cat $CTF_BASE/points.new/* | ./scoreboard | grep -q 'cat1.*team3: 10'; then
|
||||
die "Scoreboard cat1 points incorrect"
|
||||
fi
|
||||
|
||||
##
|
||||
## Token tests
|
||||
##
|
||||
|
||||
mkdir -p $CTF_BASE/token.keys
|
||||
echo -n '0123456789abcdef' > $CTF_BASE/token.keys/tokencat
|
||||
|
||||
# in.tokend uses a random number generator
|
||||
echo -n 'tokencat' | ./in.tokend > /dev/null
|
||||
|
||||
if ! grep -q 'tokencat:x....-....x' $CTF_BASE/tokens.db; then
|
||||
die "in.tokend didn't write to database"
|
||||
fi
|
||||
|
||||
if ./claim.cgi t=lalalala k=$(cat $CTF_BASE/tokens.db) | grep -q success; then
|
||||
die "claim.cgi gave points to a bogus team"
|
||||
fi
|
||||
|
||||
if ./claim.cgi t=$hash k=tokencat:xanax-xanax | grep -q success; then
|
||||
die "claim.cgi gave points for a bogus token"
|
||||
fi
|
||||
|
||||
if ! ./claim.cgi t=$hash k=$(cat $CTF_BASE/tokens.db) | grep -q success; then
|
||||
die "claim.cgi didn't give me any points"
|
||||
fi
|
||||
|
||||
if ./claim.cgi t=$hash k=$(cat $CTF_BASE/tokens.db) | grep -q success; then
|
||||
die "claim.cgi gave me points twice for the same token"
|
||||
fi
|
||||
|
||||
if ! [ -f $CTF_BASE/points.new/*.$hash.tokencat.1 ]; then
|
||||
die "claim.cgi didn't actually record any points"
|
||||
fi
|
||||
|
||||
echo "$0: All tests passed!"
|
||||
echo "$0: Aren't you just the best programmer ever?"
|
Loading…
Reference in New Issue