diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2014-07-11 22:28:46 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2014-07-11 22:28:46 +0000 |
commit | 536f98dfa5333adb90b8c78ca020d7f070702965 (patch) | |
tree | e61db580bfe0a5c0f4c9fccbffa04073717ed0be | |
parent | e135a1a144961c66ddc491f160b768094f3ee23e (diff) |
Limit HTTP header length to about 8K (based on the default of 4-8K in
common web servers). Add a related regress test.
OK benno@
-rw-r--r-- | regress/usr.sbin/relayd/args-http-headerlength.pl | 26 | ||||
-rw-r--r-- | usr.sbin/relayd/relay_http.c | 17 | ||||
-rw-r--r-- | usr.sbin/relayd/relayd.h | 4 |
3 files changed, 43 insertions, 4 deletions
diff --git a/regress/usr.sbin/relayd/args-http-headerlength.pl b/regress/usr.sbin/relayd/args-http-headerlength.pl new file mode 100644 index 00000000000..00b40952038 --- /dev/null +++ b/regress/usr.sbin/relayd/args-http-headerlength.pl @@ -0,0 +1,26 @@ +use strict; +use warnings; + +my %header = ( "Host" => "www.example.com", "Set-Cookie" => "a="."X"x8192 ); +our %args = ( + client => { + func => \&http_client, + header => \%header, + httpnok => 1, + nocheck => 1, + loggrep => qr/HTTP\/1\.0 413 Request Entity Too Large/, + }, + relayd => { + protocol => [ "http", + 'return error', + 'pass', + ], + loggrep => qr/413 Request Entity Too Large/, + }, + server => { + noserver => 1, + nocheck => 1, + }, +); + +1; diff --git a/usr.sbin/relayd/relay_http.c b/usr.sbin/relayd/relay_http.c index 7bf18cc9501..7872b40e0f1 100644 --- a/usr.sbin/relayd/relay_http.c +++ b/usr.sbin/relayd/relay_http.c @@ -1,4 +1,4 @@ -/* $OpenBSD: relay_http.c,v 1.23 2014/07/11 11:48:50 reyk Exp $ */ +/* $OpenBSD: relay_http.c,v 1.24 2014/07/11 22:28:44 reyk Exp $ */ /* * Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org> @@ -164,7 +164,7 @@ relay_read_http(struct bufferevent *bev, void *arg) char *line = NULL, *key, *value; int action; const char *errstr; - size_t size; + size_t size, linelen; struct kv *hdr = NULL; getmonotime(&con->se_tv_last); @@ -180,17 +180,27 @@ relay_read_http(struct bufferevent *bev, void *arg) } while (!cre->done && (line = evbuffer_readline(src)) != NULL) { + linelen = strlen(line); + /* * An empty line indicates the end of the request. * libevent already stripped the \r\n for us. */ - if (!strlen(line)) { + if (!linelen) { cre->done = 1; free(line); break; } key = line; + /* Limit the total header length minus \r\n */ + cre->headerlen += linelen; + if (cre->headerlen > RELAY_MAXHEADERLENGTH) { + free(line); + relay_abort_http(con, 413, "request too large", 0); + return; + } + /* * The first line is the GET/POST/PUT/... request, * subsequent lines are HTTP headers. @@ -614,6 +624,7 @@ relay_reset_http(struct ctl_relay_event *cre) } desc->http_method = 0; desc->http_chunked = 0; + cre->headerlen = 0; cre->line = 0; cre->done = 0; } diff --git a/usr.sbin/relayd/relayd.h b/usr.sbin/relayd/relayd.h index bf9bcf3467a..88c27b47ccc 100644 --- a/usr.sbin/relayd/relayd.h +++ b/usr.sbin/relayd/relayd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: relayd.h,v 1.185 2014/07/11 21:09:28 reyk Exp $ */ +/* $OpenBSD: relayd.h,v 1.186 2014/07/11 22:28:44 reyk Exp $ */ /* * Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org> @@ -59,6 +59,7 @@ #define RELAY_NUMPROC 3 #define RELAY_MAXPROC 32 #define RELAY_MAXHOSTS 32 +#define RELAY_MAXHEADERLENGTH 8192 #define RELAY_STATINTERVAL 60 #define RELAY_BACKLOG 10 #define RELAY_MAXLOOKUPLEVELS 5 @@ -183,6 +184,7 @@ struct ctl_relay_event { off_t splicelen; int line; + size_t headerlen; off_t toread; int done; enum direction dir; |