From 77c3ed33dd1da4511388d819de93a179ee6f701c Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Thu, 26 Feb 2015 16:04:43 -0700 Subject: [PATCH] Better way to do stunnel addr --- eris.c | 808 +++++++++++++++++++++++++-------------------------------- 1 file changed, 359 insertions(+), 449 deletions(-) diff --git a/eris.c b/eris.c index a33cd68..42ebcbf 100644 --- a/eris.c +++ b/eris.c @@ -28,9 +28,9 @@ #include "version.h" #ifdef __linux__ -#include +# include #else -#define sendfile(a, b, c, d) -1 +# define sendfile(a, b, c, d) -1 #endif #ifndef min @@ -50,44 +50,28 @@ #define DUMP_p(v) DUMPf("%s = %p", #v, v) #define DUMP_buf(v, l) DUMPf("%s = %.*s", #v, (int)(l), v) -/* - * Wait this long (seconds) for a valid HTTP request - */ +/* Wait this long (seconds) for a valid HTTP request */ #define READTIMEOUT 2 -/* - * Wait this long (seconds) for a non-file send to complete - */ +/* Wait this long (seconds) for a non-file send to complete */ #define WRITETIMEOUT 10 -/* - * Quit if we can't write at least this many bytes per second - */ +/* Quit if we can't write at least this many bytes per second */ #define MIN_WRITE_RATE 2560 -/* - * Wait this long for CGI to complete - */ +/* Wait this long for CGI to complete */ #define CGI_TIMEOUT (5*60) -/* - * How long each sendfile call can take - */ +/* How long each sendfile call can take */ #define SENDFILE_TIMEOUT ((int)(SIZE_MAX / MIN_WRITE_RATE)) -/* - * Maximum size of a request header (the whole block) - */ +/* Maximum size of a request header (the whole block) */ #define MAXHEADERLEN 8192 -/* - * Maximum size of a request line - */ +/* Maximum size of a request line */ #define MAXREQUESTLEN 2048 -/* - * Maximum number of header fields - */ +/* Maximum number of header fields */ #define MAXHEADERFIELDS 60 #define BUFFER_SIZE 8192 @@ -104,13 +88,11 @@ int portappend = 0; char *connector = NULL; -/* - * Variables that persist between requests - */ -int cwd; -int keepalive = 0; -char *remote_addr = NULL; -char *remote_ident = NULL; +/* Variables that persist between requests */ +int cwd; +int keepalive = 0; +char *remote_addr = NULL; +char *remote_ident = NULL; /* * Things that are really super convenient to have globally. @@ -122,7 +104,7 @@ char *host; char *user_agent; char *refer; char *path; -int http_version; +int http_version; char *content_type; size_t content_length; off_t range_start, range_end; @@ -135,12 +117,13 @@ time_t ims; /** Log a request */ void dolog(int code, off_t len) -{ /* write a log line to stderr */ +{ /* write a log line to stderr */ sanitize(host); sanitize(user_agent); sanitize(refer); - fprintf(stderr, "%s %d %lu %s %s %s %s\n", remote_addr, code, (unsigned long) len, host, user_agent, refer, path); + fprintf(stderr, "%s %d %lu %s %s %s %s\n", + remote_addr, code, (unsigned long) len, host, user_agent, refer, path); } void @@ -148,7 +131,7 @@ header(unsigned int code, const char *httpcomment) { printf("HTTP/1.%d %u %s\r\n", http_version, code, httpcomment); printf("Server: %s\r\n", FNORD); - printf("Connection: %s\r\n", keepalive ? "keep-alive" : "close"); + printf("Connection: %s\r\n", keepalive?"keep-alive":"close"); } @@ -171,7 +154,8 @@ badrequest(long code, const char *httpcomment, const char *message) if (message) { msglen = (strlen(message) * 2) + 15; - printf("Content-Length: %lu\r\nContent-Type: text/html\r\n\r\n", (unsigned long) msglen); + printf("Content-Length: %lu\r\nContent-Type: text/html\r\n\r\n", + (unsigned long) msglen); printf("%s%s", message, message); } printf("\r\n"); @@ -216,34 +200,32 @@ proto_getenv(char *proto, char *name) void get_ucspi_env() { - char *ucspi = getenv("PROTO"); - char *ip = NULL; - char *port = NULL; + char *ucspi = getenv("PROTO"); if (ucspi) { char *p; - /* - * Busybox, as usual, has the right idea - */ + /* Busybox, as usual, has the right idea */ if ((p = proto_getenv(ucspi, "REMOTEADDR"))) { remote_addr = strdup(p); } else { - ip = proto_getenv(ucspi, "REMOTEIP"); - port = proto_getenv(ucspi, "REMOTEPORT"); + char *ip = proto_getenv(ucspi, "REMOTEIP"); + char *port = proto_getenv(ucspi, "REMOTEPORT"); + + if (ip) { + char buf[80]; + + snprintf(buf, sizeof buf, "%s:%s", ip, port); + remote_addr = strdup(buf); + } } if ((p = proto_getenv(ucspi, "REMOTEINFO"))) { remote_ident = strdup(p); } } - - if (ip) { - char buf[80]; - - snprintf(buf, sizeof buf, "%s:%s", ip, port); - remote_addr = strdup(buf); - } else { + + if (! remote_addr) { // stunnel remote_addr = getenv("REMOTE_ADDR"); } @@ -252,47 +234,48 @@ get_ucspi_env() void parse_options(int argc, char *argv[]) { - int opt; + int opt; while (-1 != (opt = getopt(argc, argv, "acdhkpro:v."))) { switch (opt) { - case 'a': - doauth = 1; - break; - case 'c': - docgi = 1; - break; - case 'd': - doidx = 1; - break; - case '.': - nochdir = 1; - break; - case 'p': - portappend = 1; - break; - case 'r': - redirect = 1; - break; - case 'o': - connector = optarg; - break; - case 'v': - printf("%s\n", FNORD); - exit(0); - case 'h': - default: - fprintf(stderr, "Usage: %s [OPTIONS]\n", argv[0]); - fprintf(stderr, "\n"); - fprintf(stderr, "-a Enable authentication\n"); - fprintf(stderr, "-c Enable CGI\n"); - fprintf(stderr, "-d Enable directory listing\n"); - fprintf(stderr, "-. Serve out of ./ (no vhosting)\n"); - fprintf(stderr, "-p Append port to hostname directory\n"); - fprintf(stderr, "-r Enable symlink redirection\n"); - fprintf(stderr, "-o HANDLER Path to HTTP CONNECT handler\n"); - fprintf(stderr, "-v Print version and exit\n"); - exit(69); + case 'a': + doauth = 1; + break; + case 'c': + docgi = 1; + break; + case 'd': + doidx = 1; + break; + case '.': + nochdir = 1; + break; + case 'p': + portappend = 1; + break; + case 'r': + redirect = 1; + break; + case 'o': + connector = optarg; + break; + case 'v': + printf("%s\n", FNORD); + exit(0); + case 'h': + default: + fprintf(stderr, "Usage: %s [OPTIONS]\n", + argv[0]); + fprintf(stderr, "\n"); + fprintf(stderr, "-a Enable authentication\n"); + fprintf(stderr, "-c Enable CGI\n"); + fprintf(stderr, "-d Enable directory listing\n"); + fprintf(stderr, "-. Serve out of ./ (no vhosting)\n"); + fprintf(stderr, "-p Append port to hostname directory\n"); + fprintf(stderr, "-r Enable symlink redirection\n"); + fprintf(stderr, "-o HANDLER Path to HTTP CONNECT handler\n"); + fprintf(stderr, "-v Print version and exit\n"); + exit(69); } } } @@ -303,257 +286,234 @@ parse_options(int argc, char *argv[]) static void sigchld(int sig) { - while (waitpid(0, NULL, WNOHANG) > 0); + while (waitpid(0, NULL, WNOHANG) > 0); } static void sigalarm_cgi(int sig) { - /* - * send this out regardless of whether we've already sent a header, to maybe help with debugging - */ - badrequest(504, "Gateway Timeout", "The CGI is being too slow."); + /* send this out regardless of whether we've already sent a header, + * to maybe help with debugging */ + badrequest(504, "Gateway Timeout", "The CGI is being too slow."); } static void cgi_child(const char *relpath) { - env("GATEWAY_INTERFACE", "CGI/1.1"); - env("SERVER_SOFTWARE", FNORD); - env("REQUEST_URI", path); - env("SERVER_NAME", host); - env("SCRIPT_NAME", relpath); - env("REMOTE_ADDR", remote_addr); - env("REMOTE_IDENT", remote_ident); - if (content_length) { - char cl[20]; + env("GATEWAY_INTERFACE", "CGI/1.1"); + env("SERVER_SOFTWARE", FNORD); + env("REQUEST_URI", path); + env("SERVER_NAME", host); + env("SCRIPT_NAME", relpath); + env("REMOTE_ADDR", remote_addr); + env("REMOTE_IDENT", remote_ident); + if (content_length) { + char cl[20]; - snprintf(cl, sizeof cl, "%llu", (unsigned long long) content_length); - env("CONTENT_LENGTH", cl); - env("CONTENT_TYPE", content_type); - } + snprintf(cl, sizeof cl, "%llu", (unsigned long long) content_length); + env("CONTENT_LENGTH", cl); + env("CONTENT_TYPE", content_type); + } - /* - * Try to change to CGI's directory - */ - { - char *delim = strrchr(relpath, '/'); + /* Try to change to CGI's directory */ + { + char *delim = strrchr(relpath, '/'); - if (delim) { - *delim = '\0'; - if (0 == chdir(relpath)) { - relpath = delim + 1; - } - } - } + if (delim) { + *delim = '\0'; + if (0 == chdir(relpath)) { + relpath = delim + 1; + } + } + } - execl(relpath, relpath, NULL); - exit(1); + execl(relpath, relpath, NULL); + exit(1); } void cgi_parent(int cin, int cout, int passthru) { - char cgiheader[BUFFER_SIZE]; - size_t cgiheaderlen = 0; - FILE *cinf = fdopen(cin, "rb"); - size_t size = 0; - int header_sent = 0; - int code = 200; + char cgiheader[BUFFER_SIZE]; + size_t cgiheaderlen = 0; + FILE *cinf = fdopen(cin, "rb"); + size_t size = 0; + int header_sent = 0; + int code = 200; - fcntl(cin, F_SETFL, O_NONBLOCK); - signal(SIGCHLD, sigchld); - signal(SIGPIPE, SIG_IGN); /* NO! no signal! */ - signal(SIGALRM, sigalarm_cgi); + fcntl(cin, F_SETFL, O_NONBLOCK); + signal(SIGCHLD, sigchld); + signal(SIGPIPE, SIG_IGN); /* NO! no signal! */ + signal(SIGALRM, sigalarm_cgi); - while (1) { - int nfds; - fd_set rfds, wfds; + while (1) { + int nfds; + fd_set rfds, wfds; + + FD_ZERO(&rfds); + FD_ZERO(&wfds); + FD_SET(cin, &rfds); + nfds = cin; + + if (content_length) { + /* have post data */ + FD_SET(cout, &wfds); + if (cout > nfds) { + nfds = cout; + } + } else if (cout >= 0) { + close(cout); /* no post data */ + cout = -1; + } - FD_ZERO(&rfds); - FD_ZERO(&wfds); - FD_SET(cin, &rfds); - nfds = cin; + alarm(CGI_TIMEOUT); + if (-1 == select(nfds+1, &rfds, &wfds, NULL, NULL)) { + break; + } - if (content_length) { - /* - * have post data - */ - FD_SET(cout, &wfds); - if (cout > nfds) { - nfds = cout; - } - } else if (cout >= 0) { - close(cout); /* no post data */ - cout = -1; - } + if (FD_ISSET(cin, &rfds)) { + if (passthru) { + /* Pass everything through verbatim */ + size_t len; - alarm(CGI_TIMEOUT); - if (-1 == select(nfds + 1, &rfds, &wfds, NULL, NULL)) { - break; - } + /* Re-use this big buffer */ + len = fread(cgiheader, 1, sizeof cgiheader, cinf); + if (0 == len) { + /* CGI is done */ + break; + } + fwrite(cgiheader, 1, len, stdout); - if (FD_ISSET(cin, &rfds)) { - if (passthru) { - /* - * Pass everything through verbatim - */ - size_t len; + /* Naively assume the CGI knows best about sending stuff */ + fflush(stdout); + size += len; + } else { + /* Interpret header fields */ + size_t readlen = (sizeof cgiheader) - cgiheaderlen; - /* - * Re-use this big buffer - */ - len = fread(cgiheader, 1, sizeof cgiheader, cinf); - if (0 == len) { - /* - * CGI is done - */ - break; - } - fwrite(cgiheader, 1, len, stdout); + if (NULL == fgets(cgiheader + cgiheaderlen, readlen, cinf)) { + /* EOF or error */ + badrequest(500, "CGI Error", "CGI output too weird"); + } + cgiheaderlen = strlen(cgiheader); - /* - * Naively assume the CGI knows best about sending stuff - */ - fflush(stdout); - size += len; - } else { - /* - * Interpret header fields - */ - size_t readlen = (sizeof cgiheader) - cgiheaderlen; + if ('\n' == cgiheader[cgiheaderlen - 1]) { + /* We read a whole line */ + size_t len; + char *val; - if (NULL == fgets(cgiheader + cgiheaderlen, readlen, cinf)) { - /* - * EOF or error - */ - badrequest(500, "CGI Error", "CGI output too weird"); - } - cgiheaderlen = strlen(cgiheader); + len = extract_header_field(cgiheader, &val, 0); + if (! len) { + /* We've read the entire header block */ + passthru = 1; + eoh(); + } else { + if (! header_sent) { + if (! strcasecmp(cgiheader, "Location")) { + header(302, "CGI Redirect"); + printf("%s: %s\r\n\r\n", cgiheader, val); + dolog(302, 0); + exit(0); + } else if (! strcasecmp(cgiheader, "Status")) { + char *txt; + + if (val) { + code = (int)strtol(val, &txt, 10); + } else { + code = 0; + } + if (code < 100) { + header(500, "Internal Error"); + printf("CGI returned Status: %d\n", code); + dolog(500, 0); + exit(0); + } + for (; *txt == ' '; txt += 1); + header(code, txt); + } else { + header(200, "OK"); + printf("Pragma: no-cache\r\n"); + } + header_sent = 1; + } + printf("%s: %s\r\n", cgiheader, val); + cgiheaderlen = 0; + } + } + } + } else if (FD_ISSET(cout, &wfds)) { + /* + * write to cgi the post data + */ + if (content_length) { + size_t len; + char buf[BUFFER_SIZE]; + size_t nmemb = min(BUFFER_SIZE, content_length); + char *p = buf; - if ('\n' == cgiheader[cgiheaderlen - 1]) { - /* - * We read a whole line - */ - size_t len; - char *val; + len = fread(buf, 1, nmemb, stdin); + if (len < 1) { + break; + } + content_length -= len; - len = extract_header_field(cgiheader, &val, 0); - if (!len) { - /* - * We've read the entire header block - */ - passthru = 1; - eoh(); - } else { - if (!header_sent) { - if (!strcasecmp(cgiheader, "Location")) { - header(302, "CGI Redirect"); - printf("%s: %s\r\n\r\n", cgiheader, val); - dolog(302, 0); - exit(0); - } else if (!strcasecmp(cgiheader, "Status")) { - char *txt; + while (len > 0) { + size_t wlen = write(cout, p, len); - if (val) { - code = (int) strtol(val, &txt, 10); - } else { - code = 0; - } - if (code < 100) { - header(500, "Internal Error"); - printf("CGI returned Status: %d\n", code); - dolog(500, 0); - exit(0); - } - for (; *txt == ' '; txt += 1); - header(code, txt); - } else { - header(200, "OK"); - printf("Pragma: no-cache\r\n"); - } - header_sent = 1; - } - printf("%s: %s\r\n", cgiheader, val); - cgiheaderlen = 0; - } - } - } - } else if (FD_ISSET(cout, &wfds)) { - /* - * write to cgi the post data - */ - if (content_length) { - size_t len; - char buf[BUFFER_SIZE]; - size_t nmemb = min(BUFFER_SIZE, content_length); - char *p = buf; + if (wlen == -1) { + break; + } + len -= wlen; + p += wlen; + } + } else { + close(cout); + } + } + } - len = fread(buf, 1, nmemb, stdin); - if (len < 1) { - break; - } - content_length -= len; - - while (len > 0) { - size_t wlen = write(cout, p, len); - - if (wlen == -1) { - break; - } - len -= wlen; - p += wlen; - } - } else { - close(cout); - } - } - } - - fflush(stdout); - dolog(code, size); + fflush(stdout); + dolog(code, size); } void serve_cgi(char *relpath) { - int pid; - int cin[2]; - int cout[2]; + int pid; + int cin[2]; + int cout[2]; - if (pipe(cin) || pipe(cout)) { - badrequest(500, "Internal Server Error", "Server Resource problem."); - } + if (pipe(cin) || pipe(cout)) { + badrequest(500, "Internal Server Error", "Server Resource problem."); + } - pid = fork(); - if (-1 == pid) { - badrequest(500, "Internal Server Error", "Unable to fork."); - } - if (pid) { - close(cin[1]); - close(cout[0]); + pid = fork(); + if (-1 == pid) { + badrequest(500, "Internal Server Error", "Unable to fork."); + } + if (pid) { + close(cin[1]); + close(cout[0]); - /* - * Eris is not this smart yet - */ - keepalive = 0; + /* Eris is not this smart yet */ + keepalive = 0; - cgi_parent(cin[0], cout[1], 0); + cgi_parent(cin[0], cout[1], 0); - exit(0); - } else { - close(cwd); - close(cout[1]); - close(cin[0]); + exit(0); + } else { + close(cwd); + close(cout[1]); + close(cin[0]); - dup2(cout[0], 0); - dup2(cin[1], 1); + dup2(cout[0], 0); + dup2(cin[1], 1); - close(cout[0]); - close(cin[1]); + close(cout[0]); + close(cin[1]); - cgi_child(relpath); - } + cgi_child(relpath); + } } /* @@ -561,26 +521,20 @@ serve_cgi(char *relpath) */ ssize_t -fake_sendfile(int out_fd, int in_fd, off_t * offset, size_t count) +fake_sendfile(int out_fd, int in_fd, off_t *offset, size_t count) { char buf[BUFFER_SIZE]; ssize_t l, m; - /* - * is mmap quicker? does it matter? - */ + /* is mmap quicker? does it matter? */ if (-1 == lseek(in_fd, *offset, SEEK_SET)) { - /* - * We're screwed. The most helpful thing we can do now is die. - */ + /* We're screwed. The most helpful thing we can do now is die. */ fprintf(stderr, "Unable to seek. Dying.\n"); exit(0); } l = read(in_fd, buf, min(count, sizeof buf)); if (-1 == l) { - /* - * Also screwed. - */ + /* Also screwed. */ fprintf(stderr, "Unable to read an open file. Dying.\n"); exit(0); } @@ -589,15 +543,13 @@ fake_sendfile(int out_fd, int in_fd, off_t * offset, size_t count) while (l) { m = write(out_fd, buf, l); if (-1 == m) { - /* - * ALSO screwed. - */ + /* ALSO screwed. */ fprintf(stderr, "Unable to write to client: %m (req %s). Dying.\n", path); exit(0); } l -= m; } - + return l; } @@ -643,7 +595,7 @@ serve_file(int fd, char *filename, struct stat *st) return; } - for (remain = len; remain;) { + for (remain = len; remain; ) { size_t count = min(remain, SIZE_MAX); ssize_t sent; @@ -683,31 +635,31 @@ serve_idx(int fd, char *path) } while ((de = readdir(d))) { - char *name = de->d_name; - char symlink[PATH_MAX]; - struct stat st; + char *name = de->d_name; + char symlink[PATH_MAX]; + struct stat st; if (name[0] == '.') { - continue; /* hidden files -> skip */ + continue; /* hidden files -> skip */ } if (lstat(name, &st)) { - continue; /* can't stat -> skip */ + continue; /* can't stat -> skip */ } if (S_ISDIR(st.st_mode)) { printf("[DIR] "); } else if (S_ISLNK(st.st_mode)) { - ssize_t len = readlink(de->d_name, symlink, (sizeof symlink) - 1); + ssize_t len = readlink(de->d_name, symlink, (sizeof symlink) - 1); if (len < 1) { continue; } name = symlink; - printf("[LNK] "); /* symlink */ + printf("[LNK] "); /* symlink */ } else if (S_ISREG(st.st_mode)) { - printf("%10llu", (unsigned long long) st.st_size); + printf("%10llu", (unsigned long long)st.st_size); } else { - continue; /* not a file we can provide -> skip */ + continue; /* not a file we can provide -> skip */ } /* @@ -733,45 +685,35 @@ find_serve_file(char *relpath) int fd; struct stat st; - /* - * Open fspath. If that worked, - */ + /* Open fspath. If that worked, */ if ((fd = open(relpath, O_RDONLY)) > -1) { fstat(fd, &st); - /* - * If it is a directory, - */ + /* If it is a directory, */ if (S_ISDIR(st.st_mode)) { char path2[PATH_MAX]; int fd2; - /* - * Redirect if it doesn't end with / - */ - if (!endswith(path, "/")) { + /* Redirect if it doesn't end with / */ + if (! endswith(path, "/")) { header(301, "Redirect"); printf("Location: %s/\r\n", path); eoh(); return; } - - /* - * Open relpath + "index.html". If that worked, - */ - snprintf(path2, sizeof path2, "%sindex.html", relpath); - if ((fd2 = open(path2, O_RDONLY)) > -1) { - /* - * serve that file and return. - */ + + /* Open relpath + "index.html". If that worked,*/ + snprintf(path2, sizeof path2, "%sindex.html", relpath); + if ((fd2 = open(path2, O_RDONLY)) > -1) { + /* serve that file and return. */ fstat(fd2, &st); serve_file(fd2, path2, &st); close(fd2); close(fd); return; - } else { + } else { if (docgi) { snprintf(path2, sizeof path2, "%sindex.cgi", relpath); - if (!stat(path2, &st)) { + if (! stat(path2, &st)) { return serve_cgi(path2); } } @@ -781,7 +723,7 @@ find_serve_file(char *relpath) return; } return not_found(); - } + } } else { if (docgi && endswith(relpath, ".cgi")) { close(fd); @@ -797,7 +739,7 @@ find_serve_file(char *relpath) p += 4; env("PATH_INFO", p); *p = 0; - if (!stat(relpath, &st)) { + if (! stat(relpath, &st)) { close(fd); return serve_cgi(relpath); } @@ -810,14 +752,12 @@ find_serve_file(char *relpath) void handle_request() { - char request[MAXREQUESTLEN]; - char fspath[PATH_MAX]; - char buf[MAXHEADERLEN]; + char request[MAXREQUESTLEN]; + char fspath[PATH_MAX]; + char buf[MAXHEADERLEN]; char *p; - /* - * Initialize globals - */ + /* Initialize globals */ host = NULL; user_agent = NULL; refer = NULL; @@ -830,14 +770,10 @@ handle_request() alarm(READTIMEOUT); - /* - * Read request line first - */ + /* Read request line first */ request[0] = 0; if (NULL == fgets(request, sizeof request, stdin)) { - /* - * They must have hung up! - */ + /* They must have hung up! */ exit(0); } if (!strncmp(request, "GET /", 5)) { @@ -853,9 +789,7 @@ handle_request() method = CONNECT; p = request + 8; } else { - /* - * This also handles the case where fgets does nothing - */ + /* This also handles the case where fgets does nothing */ badrequest(405, "Method Not Allowed", "Unsupported HTTP method."); } @@ -864,54 +798,50 @@ handle_request() env("REQUEST_METHOD", request); } - /* - * Interpret path into fspath. - */ + /* Interpret path into fspath. */ path = p; { char *fsp = fspath; char *query_string = NULL; - + *(fsp++) = '.'; for (; *p != ' '; p += 1) { char c = *p; switch (c) { - case 0: - badrequest(413, "Request Entity Too Large", "The HTTP request was too long"); - case '\n': - badrequest(505, "Version Not Supported", "HTTP/0.9 not supported"); - case '?': - query_string = p + 1; - break; - case '%': - if ((!query_string) && p[1] && p[2]) { - int a = fromhex(p[1]); - int b = fromhex(p[2]); + case 0: + badrequest(413, "Request Entity Too Large", "The HTTP request was too long"); + case '\n': + badrequest(505, "Version Not Supported", "HTTP/0.9 not supported"); + case '?': + query_string = p + 1; + break; + case '%': + if ((! query_string) && p[1] && p[2]) { + int a = fromhex(p[1]); + int b = fromhex(p[2]); - if ((a >= 0) && (b >= 0)) { - c = (a << 4) | b; - p += 2; + if ((a >= 0) && (b >= 0)) { + c = (a << 4) | b; + p += 2; + } } - } - break; + break; } - if ((!query_string) && (fsp - fspath + 1 < sizeof fspath)) { + if ((! query_string) && (fsp - fspath + 1 < sizeof fspath)) { *(fsp++) = c; } } *fsp = 0; - /* - * Change "/." to "/:" to keep "hidden" files such and prevent directory traversal - */ + /* Change "/." to "/:" to keep "hidden" files such and prevent directory traversal */ while ((fsp = strstr(fspath, "/."))) { - *(fsp + 1) = ':'; + *(fsp+1) = ':'; } - *(p++) = 0; /* NULL-terminate path */ + *(p++) = 0; /* NULL-terminate path */ if (docgi && query_string) { env("QUERY_STRING", query_string); @@ -919,10 +849,10 @@ handle_request() } http_version = -1; - if (!strncmp(p, "HTTP/1.", 7) && p[8] && ((p[8] == '\r') || (p[8] == '\n'))) { + if (! strncmp(p, "HTTP/1.", 7) && p[8] && ((p[8] == '\r') || (p[8] == '\n'))) { http_version = p[7] - '0'; } - if (!((http_version == 0) || (http_version == 1))) { + if (! ((http_version == 0) || (http_version == 1))) { http_version = 0; badrequest(505, "Version Not Supported", "HTTP version not supported"); } @@ -936,25 +866,21 @@ handle_request() env("SERVER_PROTOCOL", p); } - /* - * Read header fields - */ + /* Read header fields */ { - char *base = buf; - char *lastchar = base + (sizeof buf) - 2; - int nheaders = 0; + char *base = buf; + char *lastchar = base + (sizeof buf) - 2; + int nheaders = 0; *lastchar = 0; while (1) { - char *cgi_name = base; - char *p; - int plen = (sizeof buf) - (base - buf); - char *name, *val; - size_t len; + char *cgi_name = base; + char *p; + int plen = (sizeof buf) - (base - buf); + char *name, *val; + size_t len; - /* - * 40 is totally arbitrary here. - */ + /* 40 is totally arbitrary here. */ if (plen < 40) { badrequest(431, "Request Header Too Large", "The HTTP header block was too large"); } @@ -973,67 +899,55 @@ handle_request() } len = extract_header_field(p, &val, 1); - if (!len) { - /* - * blank line - */ + if (! len) { + /* blank line */ break; } - if (!val) { + if (! val) { badrequest(400, "Invalid header", "Unable to parse header block"); } name = p; - /* - * Set up CGI environment variables - */ + /* Set up CGI environment variables */ if (docgi) { env(cgi_name, val); } - /* - * By default, re-use buffer space - */ + /* By default, re-use buffer space */ base = cgi_name; - /* - * Handle special header fields - */ - if (!strcmp(name, "HOST")) { + /* Handle special header fields */ + if (! strcmp(name, "HOST")) { host = val; base = name + len + 1; - } else if (!strcmp(name, "USER_AGENT")) { + } else if (! strcmp(name, "USER_AGENT")) { user_agent = val; base = name + len + 1; - } else if (!strcmp(name, "REFERER")) { + } else if (! strcmp(name, "REFERER")) { refer = val; base = name + len + 1; - } else if (!strcmp(name, "CONTENT_TYPE")) { + } else if (! strcmp(name, "CONTENT_TYPE")) { content_type = val; base = name + len + 1; - } else if (!strcmp(name, "CONTENT_LENGTH")) { + } else if (! strcmp(name, "CONTENT_LENGTH")) { content_length = (size_t) strtoull(val, NULL, 10); - } else if (!strcmp(name, "CONNECTION")) { - if (!strcasecmp(val, "keep-alive")) { + } else if (! strcmp(name, "CONNECTION")) { + if (! strcasecmp(val, "keep-alive")) { keepalive = 1; } else { keepalive = 0; } - } else if (!strcmp(name, "IF_MODIFIED_SINCE")) { + } else if (! strcmp(name, "IF_MODIFIED_SINCE")) { ims = timerfc(val); - } else if (!strcmp(name, "RANGE")) { - /* - * Range: bytes=17-23 - */ - /* - * Range: bytes=23- - */ - if (!strncmp(val, "bytes=", 6)) { + } else if (! strcmp(name, "RANGE")) { + /* Range: bytes=17-23 */ + /* Range: bytes=23- */ + if (! strncmp(val, "bytes=", 6)) { p = val + 6; range_start = (off_t) strtoull(p, &p, 10); if (*p == '-') { - range_end = (off_t) strtoull(p + 1, NULL, 10); + range_end = (off_t) strtoull(p+1, NULL, 10); } else { range_end = 0; } @@ -1042,10 +956,8 @@ handle_request() } } - /* - * Try to change into the appropriate directory - */ - if (!nochdir) { + /* Try to change into the appropriate directory */ + if (! nochdir) { char fn[PATH_MAX]; if (host) { @@ -1058,15 +970,15 @@ handle_request() } for (p = fn; *p; p += 1) { switch (*p) { - case '/': - *p = ':'; - break; - case ':': - *p = 0; - break; - case 'A' ... 'Z': - *p ^= ' '; - break; + case '/': + *p = ':'; + break; + case ':': + *p = 0; + break; + case 'A'...'Z': + *p ^= ' '; + break; } } @@ -1080,9 +992,7 @@ handle_request() badrequest(500, "Unable to exec connector", strerror(errno)); } - /* - * Serve the file - */ + /* Serve the file */ alarm(WRITETIMEOUT); find_serve_file(fspath); fflush(stdout); @@ -1102,7 +1012,7 @@ main(int argc, char *argv[], const char *const *envp) while (1) { handle_request(); - if (!keepalive) { + if (! keepalive) { break; } if (-1 == fchdir(cwd)) {