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