mirror of https://github.com/dirtbags/moth.git
A new C-based register.cgi
This commit is contained in:
parent
8d4fea620b
commit
be41c32fd1
|
@ -1,3 +1,6 @@
|
||||||
all: in.tokend
|
all: in.tokend register.cgi
|
||||||
|
|
||||||
|
in.tokend: in.tokend.o xxtea.o
|
||||||
|
|
||||||
|
register.cgi: register.cgi.o cgi.o
|
||||||
|
|
||||||
in.tokend: in.tokend.c xxtea.c
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "cgi.h"
|
||||||
|
|
||||||
|
static size_t inlen = 0;
|
||||||
|
|
||||||
|
int
|
||||||
|
cgi_init()
|
||||||
|
{
|
||||||
|
char *rm = getenv("REQUEST_METHOD");
|
||||||
|
|
||||||
|
if (! (rm && (0 == strcmp(rm, "POST")))) {
|
||||||
|
printf("405 Method not allowed\n"
|
||||||
|
"Allow: POST\n"
|
||||||
|
"Content-type: text/html\n"
|
||||||
|
"\n"
|
||||||
|
"<h1>Method not allowed</h1>\n"
|
||||||
|
"<p>I only speak POST. Sorry.</p>\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inlen = atoi(getenv("CONTENT_LENGTH"));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
read_char()
|
||||||
|
{
|
||||||
|
if (inlen) {
|
||||||
|
inlen -= 1;
|
||||||
|
return getchar();
|
||||||
|
}
|
||||||
|
return EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char
|
||||||
|
tonum(int c)
|
||||||
|
{
|
||||||
|
if ((c >= '0') && (c <= '9')) {
|
||||||
|
return c - '0';
|
||||||
|
}
|
||||||
|
if ((c >= 'a') && (c <= 'f')) {
|
||||||
|
return 10 + c - 'a';
|
||||||
|
}
|
||||||
|
if ((c >= 'A') && (c <= 'F')) {
|
||||||
|
return 10 + c - 'A';
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char
|
||||||
|
read_hex()
|
||||||
|
{
|
||||||
|
int a = read_char();
|
||||||
|
int b = read_char();
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
size_t
|
||||||
|
read_item(char *str, size_t maxlen)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
size_t pos = 0;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
c = read_char();
|
||||||
|
switch (c) {
|
||||||
|
case EOF:
|
||||||
|
case '=':
|
||||||
|
case '&':
|
||||||
|
str[pos] = '\0';
|
||||||
|
return pos;
|
||||||
|
case '%':
|
||||||
|
c = read_hex();
|
||||||
|
break;
|
||||||
|
case '+':
|
||||||
|
c = ' ';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (pos < maxlen - 1) {
|
||||||
|
str[pos] = c;
|
||||||
|
pos += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
#ifndef __CGI_H__
|
||||||
|
#define __CGI_H__
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
int cgi_init();
|
||||||
|
size_t read_item(char *str, size_t maxlen);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,113 @@
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include "cgi.h"
|
||||||
|
|
||||||
|
char *BASE_PATH = "/var/lib/ctf/teams";
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
djbhash(char const *buf, size_t buflen)
|
||||||
|
{
|
||||||
|
unsigned int h = 5381;
|
||||||
|
|
||||||
|
while (buflen--) {
|
||||||
|
h = ((h << 5) + h) ^ *(buf++);
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
page(char *title, char *fmt, ...)
|
||||||
|
{
|
||||||
|
FILE *p;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
printf("Content-type: text/html\r\n\r\n");
|
||||||
|
fflush(stdout);
|
||||||
|
p = popen("./template", "w");
|
||||||
|
if (NULL == p) {
|
||||||
|
printf("<h1>%s</h1>\n", title);
|
||||||
|
p = stdout;
|
||||||
|
} else {
|
||||||
|
fprintf(p, "Title: %s\n", title);
|
||||||
|
}
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vfprintf(p, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
fclose(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char team[80];
|
||||||
|
size_t teamlen;
|
||||||
|
char hash[9];
|
||||||
|
|
||||||
|
if (-1 == cgi_init()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read in team name, the only thing we care about */
|
||||||
|
while (1) {
|
||||||
|
size_t len;
|
||||||
|
char key[20];
|
||||||
|
|
||||||
|
len = read_item(key, sizeof(key));
|
||||||
|
if (0 == len) break;
|
||||||
|
if ((1 == len) && ('t' == key[0])) {
|
||||||
|
teamlen = read_item(team, sizeof(team));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute the hash */
|
||||||
|
sprintf(hash, "%08x", djbhash(team, teamlen));
|
||||||
|
|
||||||
|
/* Write team name into file */
|
||||||
|
{
|
||||||
|
char filename[100];
|
||||||
|
int fd;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = snprintf(filename, sizeof(filename),
|
||||||
|
"%s/%s",
|
||||||
|
BASE_PATH, hash);
|
||||||
|
if (sizeof(filename) == ret) {
|
||||||
|
printf(("500 Server screwed up\n"
|
||||||
|
"Content-type: text/plain\n"
|
||||||
|
"\n"
|
||||||
|
"The full path to the team hash file is too long.\n"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
fd = creat(filename, 0444);
|
||||||
|
if (-1 == fd) {
|
||||||
|
page("Bad team name",
|
||||||
|
("<p>Either that team name is already in use, or you "
|
||||||
|
"found a hash collision (way to go). "
|
||||||
|
"In any case, you're going to "
|
||||||
|
"have to pick something else.</p>"
|
||||||
|
"<p>If you're just trying to find your team hash again,"
|
||||||
|
"it's <samp>%s</samp>.</p>"),
|
||||||
|
hash);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
write(fd, team, teamlen);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Let them know what their hash is. */
|
||||||
|
page("Team registered",
|
||||||
|
("<p>Team hash: <samp>%s</samp></p>"
|
||||||
|
"<p><b>Save your team hash somewhere!</b>. You will need it "
|
||||||
|
"to claim points.</b></p>"),
|
||||||
|
hash);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue