#include #include #include #include #include #include #include #define MAX_QUERY_LEN 255 #define IP_LEN 16 #define IP_FILE "ip.txt" #define TOKEN "" char *form_value(const char *args, const char *field) { char *s; char *token; char *value; char *ret = NULL; size_t len; len = strlen(field); s = strdup(args); while((token = strsep(&s, "&")) != NULL) { if(strlen(token) < len) continue; if(strncmp(field, token, len) == 0) { value = strchr(token, '='); ret = strdup(value); break; } } free(s); return(ret); } 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 wfd) { char *ip = NULL, *token = NULL; int ret = 1; size_t len; ip = form_value(env, "ip"); if(!ip) return(ret); token = form_value(env, "token"); if(!token) free(ip); return(ret); if(ctc(token, TOKEN) == 1) { len = strlen(ip); if(len >= IP_LEN-1) len = IP_LEN-1; write(wfd, ip, len); close(wfd); ret = 0; } else ret = 2; free(ip); free(token); return(ret); } char *err_msg[2] = {"invalid arguments", "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-1]); else puts("ok"); } else { len = strlen(ip); write(wfd, ip, len); close(wfd); if(len > 1) puts(ip); else puts("empty"); } return(EXIT_SUCCESS); }