X-Git-Url: http://www.dolda2000.com/gitweb/?p=ashd.git;a=blobdiff_plain;f=src%2Fhtparser.c;h=bc8f7fd3a5f7be4fe27509bdf9d29eaa7ef34cd2;hp=ceae319aeafbd12ef68cd0342c9e4be6e2747c38;hb=64a9096a7cd4acf3bbf4a7bf4a214f4b5cca7fdc;hpb=d341283f757e188a52aedae7d715e201f2a430c2 diff --git a/src/htparser.c b/src/htparser.c index ceae319..bc8f7fd 100644 --- a/src/htparser.c +++ b/src/htparser.c @@ -77,6 +77,8 @@ static struct hthead *parsereq(FILE *in) goto fail; } else { bufadd(method, c); + if(method.d >= 128) + goto fail; } } while(1) { @@ -87,6 +89,8 @@ static struct hthead *parsereq(FILE *in) goto fail; } else { bufadd(url, c); + if(url.d >= 65536) + goto fail; } } while(1) { @@ -98,6 +102,8 @@ static struct hthead *parsereq(FILE *in) goto fail; } else { bufadd(ver, c); + if(ver.d >= 128) + goto fail; } } bufadd(method, 0); @@ -140,6 +146,8 @@ static struct hthead *parseresp(FILE *in) goto fail; } else { bufadd(ver, c); + if(ver.d >= 128) + goto fail; } } while(1) { @@ -150,6 +158,8 @@ static struct hthead *parseresp(FILE *in) goto fail; } else { code = (code * 10) + (c - '0'); + if(code >= 10000) + goto fail; } } while(1) { @@ -161,6 +171,8 @@ static struct hthead *parseresp(FILE *in) goto fail; } else { bufadd(msg, c); + if(msg.d >= 512) + goto fail; } } bufadd(msg, 0); @@ -228,12 +240,50 @@ static int hasheader(struct hthead *head, char *name, char *val) return(!strcasecmp(hd, val)); } +static int canonreq(struct hthead *req) +{ + char *p, *p2, *r; + int n; + + if(req->url[0] == '/') { + replrest(req, req->url + 1); + if((p = strchr(req->rest, '?')) != NULL) + *p = 0; + return(1); + } + if((p = strstr(req->url, "://")) != NULL) { + n = p - req->url; + if(((n == 4) && !strncasecmp(req->url, "http", 4)) || + ((n == 5) && !strncasecmp(req->url, "https", 5))) { + if(getheader(req, "host")) + return(0); + p += 3; + if((p2 = strchr(p, '/')) == NULL) { + headappheader(req, "Host", p); + free(req->url); + req->url = sstrdup("/"); + } else { + r = sstrdup(p2); + *(p2++) = 0; + headappheader(req, "Host", p); + free(req->url); + req->url = r; + } + replrest(req, req->url + 1); + if((p = strchr(req->rest, '?')) != NULL) + *p = 0; + return(1); + } + } + return(0); +} + void serve(FILE *in, struct conn *conn) { int pfds[2]; FILE *out; struct hthead *req, *resp; - char *hd, *p; + char *hd; off_t dlen; out = NULL; @@ -241,11 +291,8 @@ void serve(FILE *in, struct conn *conn) while(1) { if((req = parsereq(in)) == NULL) break; - replrest(req, req->url); - if(req->rest[0] == '/') - replrest(req, req->rest + 1); - if((p = strchr(req->rest, '?')) != NULL) - *p = 0; + if(!canonreq(req)) + break; if((conn->initreq != NULL) && conn->initreq(conn, req)) break; @@ -499,7 +546,7 @@ int main(int argc, char **argv) if(usesyslog) opensyslog(); if(root) { - if(chroot(root)) { + if(chdir(root) || chroot(root)) { flog(LOG_ERR, "could not chroot to %s: %s", root, strerror(errno)); exit(1); }