From 4dd188b55f77c2a41c9fb2bab693e78aab8c0bbc Mon Sep 17 00:00:00 2001 From: reyk Date: Wed, 6 Aug 2014 18:21:14 +0000 Subject: [PATCH] Limit the body size in client requests (eg. POST data) to 1M by default; add a configuration option to change the limit. ok florian@ --- usr.sbin/httpd/config.c | 3 ++- usr.sbin/httpd/httpd.conf.5 | 7 ++++++- usr.sbin/httpd/httpd.h | 4 +++- usr.sbin/httpd/parse.y | 16 +++++++++++----- usr.sbin/httpd/server_http.c | 8 +++++++- 5 files changed, 29 insertions(+), 9 deletions(-) diff --git a/usr.sbin/httpd/config.c b/usr.sbin/httpd/config.c index 95c80a8b635..7ab53b5a817 100644 --- a/usr.sbin/httpd/config.c +++ b/usr.sbin/httpd/config.c @@ -1,4 +1,4 @@ -/* $OpenBSD: config.c,v 1.20 2014/08/06 02:04:42 jsing Exp $ */ +/* $OpenBSD: config.c,v 1.21 2014/08/06 18:21:14 reyk Exp $ */ /* * Copyright (c) 2011 - 2014 Reyk Floeter @@ -296,6 +296,7 @@ config_getserver_config(struct httpd *env, struct server *srv, memcpy(&srv_conf->timeout, &srv->srv_conf.timeout, sizeof(srv_conf->timeout)); srv_conf->maxrequests = srv->srv_conf.maxrequests; + srv_conf->maxrequestbody = srv->srv_conf.maxrequestbody; DPRINTF("%s: %s %d location \"%s\", " "parent \"%s\", flags: %s", diff --git a/usr.sbin/httpd/httpd.conf.5 b/usr.sbin/httpd/httpd.conf.5 index adacb8d9196..d0c91942a7b 100644 --- a/usr.sbin/httpd/httpd.conf.5 +++ b/usr.sbin/httpd/httpd.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: httpd.conf.5,v 1.27 2014/08/06 16:31:09 jsing Exp $ +.\" $OpenBSD: httpd.conf.5,v 1.28 2014/08/06 18:21:14 reyk Exp $ .\" .\" Copyright (c) 2014 Reyk Floeter .\" @@ -123,6 +123,11 @@ and include one or more lines of the following syntax: Set the specified options and limits for HTTP connections. Valid options are: .Bl -tag -width Ds +.It Ic max request body Ar number +Set the maximum body size in bytes that the client can send to the server. +The default value is +.Ar 1048576 +bytes (1M). .It Ic max requests Ar number Set the maximum number of requests per persistent HTTP connection. Persistent connections are negotiated using the Keep-Alive header in diff --git a/usr.sbin/httpd/httpd.h b/usr.sbin/httpd/httpd.h index c129860fb97..74d6904e206 100644 --- a/usr.sbin/httpd/httpd.h +++ b/usr.sbin/httpd/httpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: httpd.h,v 1.50 2014/08/06 16:09:02 jsing Exp $ */ +/* $OpenBSD: httpd.h,v 1.51 2014/08/06 18:21:14 reyk Exp $ */ /* * Copyright (c) 2006 - 2014 Reyk Floeter @@ -50,6 +50,7 @@ #define SERVER_MAXPROC 32 #define SERVER_MAXHEADERLENGTH 8192 #define SERVER_MAXREQUESTS 100 /* max requests per connection */ +#define SERVER_MAXREQUESTBODY 1048576 /* 1M */ #define SERVER_BACKLOG 10 #define SERVER_OUTOF_FD_RETRIES 5 @@ -370,6 +371,7 @@ struct server_config { int prefixlen; struct timeval timeout; u_int32_t maxrequests; + size_t maxrequestbody; char *ssl_cert; off_t ssl_cert_len; diff --git a/usr.sbin/httpd/parse.y b/usr.sbin/httpd/parse.y index 2f74bb426a6..532e56a394a 100644 --- a/usr.sbin/httpd/parse.y +++ b/usr.sbin/httpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.32 2014/08/06 16:11:34 jsing Exp $ */ +/* $OpenBSD: parse.y,v 1.33 2014/08/06 18:21:14 reyk Exp $ */ /* * Copyright (c) 2007 - 2014 Reyk Floeter @@ -125,10 +125,10 @@ typedef struct { %} -%token ACCESS AUTO BACKLOG BUFFER CERTIFICATE CHROOT CIPHERS COMMON COMBINED -%token CONNECTION DIRECTORY ERR FCGI INDEX IP KEY LISTEN LOCATION LOG MAXIMUM -%token NO NODELAY ON PORT PREFORK REQUESTS ROOT SACK SERVER SOCKET SSL STYLE -%token SYSLOG TCP TIMEOUT TYPES +%token ACCESS AUTO BACKLOG BODY BUFFER CERTIFICATE CHROOT CIPHERS COMMON +%token COMBINED CONNECTION DIRECTORY ERR FCGI INDEX IP KEY LISTEN LOCATION +%token LOG MAXIMUM NO NODELAY ON PORT PREFORK REQUEST REQUESTS ROOT SACK +%token SERVER SOCKET SSL STYLE SYSLOG TCP TIMEOUT TYPES %token ERROR INCLUDE %token STRING %token NUMBER @@ -231,6 +231,7 @@ server : SERVER STRING { s->srv_conf.id = ++last_server_id; s->srv_conf.timeout.tv_sec = SERVER_TIMEOUT; s->srv_conf.maxrequests = SERVER_MAXREQUESTS; + s->srv_conf.maxrequestbody = SERVER_MAXREQUESTBODY; s->srv_conf.flags |= SRVFLAG_LOG; s->srv_conf.logformat = LOG_FORMAT_COMMON; if ((s->srv_conf.ssl_cert_file = @@ -473,6 +474,9 @@ conflags : TIMEOUT timeout { | MAXIMUM REQUESTS NUMBER { srv_conf->maxrequests = $3; } + | MAXIMUM REQUEST BODY NUMBER { + srv_conf->maxrequestbody = $4; + } ; ssl : '{' sslopts_l '}' @@ -793,6 +797,7 @@ lookup(char *s) { "access", ACCESS }, { "auto", AUTO }, { "backlog", BACKLOG }, + { "body", BODY }, { "buffer", BUFFER }, { "certificate", CERTIFICATE }, { "chroot", CHROOT }, @@ -816,6 +821,7 @@ lookup(char *s) { "on", ON }, { "port", PORT }, { "prefork", PREFORK }, + { "request", REQUEST }, { "requests", REQUESTS }, { "root", ROOT }, { "sack", SACK }, diff --git a/usr.sbin/httpd/server_http.c b/usr.sbin/httpd/server_http.c index f221e5adf75..259376df40d 100644 --- a/usr.sbin/httpd/server_http.c +++ b/usr.sbin/httpd/server_http.c @@ -1,4 +1,4 @@ -/* $OpenBSD: server_http.c,v 1.41 2014/08/06 15:08:04 florian Exp $ */ +/* $OpenBSD: server_http.c,v 1.42 2014/08/06 18:21:14 reyk Exp $ */ /* * Copyright (c) 2006 - 2014 Reyk Floeter @@ -120,6 +120,7 @@ void server_read_http(struct bufferevent *bev, void *arg) { struct client *clt = arg; + struct server_config *srv_conf = clt->clt_srv_conf; struct http_descriptor *desc = clt->clt_desc; struct evbuffer *src = EVBUFFER_INPUT(bev); char *line = NULL, *key, *value; @@ -261,6 +262,11 @@ server_read_http(struct bufferevent *bev, void *arg) server_abort_http(clt, 500, errstr); goto abort; } + if ((size_t)clt->clt_toread > + srv_conf->maxrequestbody) { + server_abort_http(clt, 413, NULL); + goto abort; + } } if (strcasecmp("Transfer-Encoding", key) == 0 && -- 2.20.1