diff --git a/src/Makefile b/src/Makefile index f7a14d6..6f7c750 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,11 +1,13 @@ -TARGETS = in.tokend register.cgi claim.cgi +TARGETS = in.tokend register.cgi claim.cgi pointscli all: $(TARGETS) in.tokend: in.tokend.o xxtea.o register.cgi: register.cgi.o cgi.o -claim.cgi: claim.cgi.o cgi.o pointscli.o +claim.cgi: claim.cgi.o cgi.o common.o +pointscli: common.o pointscli.o clean: - rm -f $(TARGETS) *.o \ No newline at end of file + rm -f $(TARGETS) *.o + diff --git a/src/claim.cgi.c b/src/claim.cgi.c index f376056..82463e9 100644 --- a/src/claim.cgi.c +++ b/src/claim.cgi.c @@ -2,10 +2,9 @@ #include #include #include "cgi.h" -#include "pointscli.h" +#include "common.h" char const *tokenlog = "/var/lib/ctf/tokend/tokens.log"; -char const *teamdir = "/var/lib/ctf/teams"; char const *claimlog = "/var/lib/ctf/tokend/claim.log"; int @@ -30,6 +29,9 @@ main(int argc, char *argv[]) char token[100]; size_t tokenlen; + /* XXX: This code needs to be tested */ + abort(); + if (-1 == cgi_init()) { return 0; } @@ -69,7 +71,7 @@ main(int argc, char *argv[]) } } - if (! pointscli_isteam(team)) { + if (! team_exists(team)) { cgi_page("No such team", ""); } @@ -78,7 +80,7 @@ main(int argc, char *argv[]) FILE *f; int valid = 0; - f = fopen(filelog, "r"); + f = fopen(claimlog, "r"); if (f) { while (1) { char line[100]; @@ -113,6 +115,7 @@ main(int argc, char *argv[]) sprintf(needle, "%s %s", team, token); while (1) { char line[100]; + char *p; int pos; if (NULL == fgets(line, sizeof(line), f)) { @@ -120,9 +123,9 @@ main(int argc, char *argv[]) } /* Skip to past first space */ - for (; (*line && (*line != ' ')); line += 1); + for (p = line; (*p && (*p != ' ')); p += 1); - if (0 == mystrcmp(line, needle)) { + if (0 == mystrcmp(p, needle)) { claimed = 1; break; } @@ -143,7 +146,7 @@ main(int argc, char *argv[]) } category[i] = '\0'; - pointscli_award(team, category, points); + award_points(team, category, 1); } /* Finally, append an entry to the log file. I figure it's better diff --git a/src/common.c b/src/common.c new file mode 100644 index 0000000..f82c0c5 --- /dev/null +++ b/src/common.c @@ -0,0 +1,80 @@ +#include +#include +#include +#include +#include +#include +#include +#include "common.h" + +int +team_exists(char *teamhash) +{ + struct stat buf; + char filename[100]; + int ret; + int i; + + /* Check for invalid characters. */ + for (i = 0; teamhash[i]; i += 1) { + if (! isalnum(teamhash[i])) { + return 0; + } + } + + /* 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); + if (-1 == ret) { + return 0; + } + + return 1; +} + +int +award_points(char *teamhash, char *category, int points) +{ + char line[100]; + int linelen; + int fd; + int ret; + + if (! team_exists(teamhash)) { + return -2; + } + + linelen = snprintf(line, sizeof(line), + "%u %s %s %d\n", + time(NULL), teamhash, category, points); + if (sizeof(line) == linelen) { + return -1; + } + + fd = open(pointslog, O_WRONLY | O_CREAT, 0666); + if (-1 == fd) { + return -1; + } + + ret = lockf(fd, F_LOCK, 0); + if (-1 == ret) { + close(fd); + return -1; + } + + ret = lseek(fd, 0, SEEK_END); + if (-1 == ret) { + close(fd); + return -1; + } + + write(fd, line, linelen); + close(fd); + return 0; +} diff --git a/src/common.h b/src/common.h new file mode 100644 index 0000000..745b7c4 --- /dev/null +++ b/src/common.h @@ -0,0 +1,10 @@ +#ifndef __COMMON_H__ +#define __COMMON_H__ + +#define teamdir "/var/lib/ctf/teams" +#define pointslog "/var/lib/ctf/points.log" + +int team_exists(char *teamhash); +int award_points(char *teamhash, char *category, int point); + +#endif diff --git a/src/pointscli.c b/src/pointscli.c index 64694bd..f74d512 100644 --- a/src/pointscli.c +++ b/src/pointscli.c @@ -1,18 +1,37 @@ -/* Does that team even exist? */ -int -pointscli_isteam(char *team) -{ - char filename[100]; - int ret; - FILE *f; +#include +#include +#include +#include "common.h" - ret = snprintf(filename, sizeof(filename), - "%s/%s", teamdir, team); - return 0; - f = fopen(filename, "w"); - if (! f) { - return 0; +int +main(int argc, char *argv[]) +{ + int points; + int ret; + + if (argc != 4) { + fprintf(stderr, "Usage: pointscli TEAM CATEGORY POINTS\n"); + return EX_USAGE; } - fclose(f); - return 1; + + points = atoi(argv[3]); + if (0 == points) { + fprintf(stderr, "Error: award 0 points?\n"); + return EX_USAGE; + } + + ret = award_points(argv[1], argv[2], points); + switch (ret) { + case -3: + fprintf(stderr, "Runtime error\n"); + return EX_SOFTWARE; + case -2: + fprintf(stderr, "No such team\n"); + return EX_NOUSER; + case -1: + perror("Couldn't award points"); + return EX_UNAVAILABLE; + } + + return 0; } diff --git a/src/scoreboard b/src/scoreboard new file mode 100755 index 0000000..adb6355 --- /dev/null +++ b/src/scoreboard @@ -0,0 +1,38 @@ +#! /usr/bin/awk -f + +function output() { + for (c in points_by_cat) { + for (t in teams) { + printf("%d %s %f\n", + (lasttime - start) / 600, + t, + points_by_cat_team[c, t] / points_by_cat[c]); + } + } +} + +{ + time = $1 + team = $2 + cat = $3 + points = int($4) + + if (! start) { + start = time + } + + # Every 10 minutes + if (time > (outtime + 600)) { + outtime = time + output() + } + lasttime = time + + teams[team] = team + points_by_cat[cat] += points + points_by_cat_team[cat, team] += points +} + +END { + output() +}