#include #include #include #include #include #include #include #define SEP '=' #define MAX_QUERY_LEN 255 #define MAX_QUERY_ARGS 2 #define IP_LEN 16 #define IP_FILE "ip.txt" #define TOKEN "" void free_arr(void *arr) { uintptr_t *a = arr; while(*a) { free((void*)*a++); } free(arr); } char **parse(const char *str) { const char *s = str; char *qs, *token; char **arr = NULL; int c = 1, argc = 0; qs = strdup(s); while((token = strsep(&qs, "&")) != NULL) { if(++argc > MAX_QUERY_ARGS) break; c++; if(arr == NULL) { arr = malloc(c*sizeof(char *)); if(arr == NULL) break; } else { arr = realloc(arr, c*sizeof(char *)); if(arr == NULL) break; } arr[c-1] = NULL; arr[c-2] = strdup(token); } free(qs); return(arr); } void header() { puts("Status: 200 OK\r"); puts("Content-Type: text/html\r"); puts("\r"); } int ctb(unsigned char a, unsigned char b) { unsigned char c = ~(a ^ b); c &= c >> 4; c &= c >> 2; c &= c >> 1; return((int)c); } int ctc(const char *a, const char *b) { if(!a || !b) return(0); if(strlen(a) != strlen(b)) return(0); const char *x = a, *y = b; char v = 0; while(*x) v |= *x++ ^ *y++; return(ctb(v, 0)); } int set_ip(char *env, int fd) { char *ip = NULL, *token = NULL, *tmp = NULL; int ret = -1, len = 0; char **arg = parse(env); char **arr = arg; if(arg == NULL) return(0); for(; *arr; arr++) { if(strncmp(*arr, "ip", 2) == 0) { tmp = strchr(*arr, SEP); if(++tmp == NULL) continue; ip = strdup(tmp); } else if(strncmp(*arr, "token", 5) == 0) { tmp = strchr(*arr, SEP); if(++tmp == NULL) continue; token = strdup(tmp); } } tmp = NULL; free_arr(arg); if(ctc(token, TOKEN) == 1) { if(ip) { len = strlen(ip); if(len >= IP_LEN-1) len = IP_LEN-1; write(fd, ip, len); } close(fd); } else ret = 1; if(ip) free(ip); if(token) free(token); return(ret); } char *err_msg[2] = {"wrong input", "wrong token"}; int main(void) { char *env = NULL; char ip[IP_LEN]; int errn = 0, len = 0; int rfd, wfd; if((rfd = open(IP_FILE, O_RDONLY|O_SHLOCK)) == -1) err(EXIT_FAILURE, "read open failed"); if(read(rfd, &ip, IP_LEN) <= 0) ip[0] = '\0'; close(rfd); ip[IP_LEN] = '\0'; if((wfd = open(IP_FILE, O_WRONLY|O_CREAT|O_TRUNC|O_EXLOCK)) == -1) err(EXIT_FAILURE, "rw open failed"); if(pledge("stdio", NULL) == -1) err(EXIT_FAILURE, "pledge"); env = getenv("QUERY_STRING"); header(); if(env != NULL) { if(strlen(env) > MAX_QUERY_LEN) { puts("query longer than 255 bytes"); return(EXIT_SUCCESS); } if((errn = set_ip(env, wfd)) >= 0) puts(err_msg[errn]); else puts("ok"); } else { len = strlen(ip); write(wfd, ip, len); close(wfd); if(len > 1) puts(ip); else puts("empty"); } return(EXIT_SUCCESS); }