aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi.dcr@tutanota.com>2024-02-19 23:00:56 +0100
committerXavier Del Campo Romero <xavi.dcr@tutanota.com>2024-02-19 23:00:56 +0100
commitafe0681c0b26bb64bad55d7e86770f346cfa043e (patch)
tree420dbf3084332bf1750d0986ea118b427aed7364
parent9d9e0c2979f43297b2ebbf84f14f064f3f9ced0e (diff)
Limit maximum multipart/form-data pairs and files
A malicious user could inject an infinite number of empty files or key/value pairs into a request in order to exhaust the device's resources.
-rw-r--r--doc/man7/libweb_handler.76
-rw-r--r--doc/man7/libweb_http.730
-rw-r--r--handler.c3
-rw-r--r--http.c18
-rw-r--r--include/libweb/handler.h1
-rw-r--r--include/libweb/http.h5
6 files changed, 59 insertions, 4 deletions
diff --git a/doc/man7/libweb_handler.7 b/doc/man7/libweb_handler.7
index f975444..bf47567 100644
--- a/doc/man7/libweb_handler.7
+++ b/doc/man7/libweb_handler.7
@@ -76,6 +76,7 @@ struct handler_cfg
int (*\fIlength\fP)(unsigned long long len, const struct http_cookie *c, struct http_response *r, void *user);
void *\fIuser\fP;
size_t \fImax_headers\fP;
+ struct http_cfg_post \fIpost\fP;
};
.EE
.in
@@ -83,9 +84,10 @@ struct handler_cfg
.IR tmpdir ,
.IR length ,
-.I user
-and
+.IR user ,
.I max_headers
+and
+.I post
are passed directly to the
.I struct http_cfg
object used to initialize a
diff --git a/doc/man7/libweb_http.7 b/doc/man7/libweb_http.7
index 0beb686..de627cb 100644
--- a/doc/man7/libweb_http.7
+++ b/doc/man7/libweb_http.7
@@ -94,6 +94,11 @@ struct http_cfg
const char *\fItmpdir\fP;
void *\fIuser\fP;
size_t \fImax_headers\fP;
+
+ struct http_cfg_post
+ {
+ size_t \fImax_pairs\fP, \fImax_files\fP;
+ } \fIpost\fP;
};
.EE
.in
@@ -221,6 +226,31 @@ Any extra headers sent by the client outside this maximum value shall be
silently ignored by
.IR libweb .
+.I post
+contains configuration parameters specific to
+.B POST
+requests:
+
+.I max_pairs
+refers to the maximum number of key/value pairs that shall be accepted by
+.I libweb
+on
+.B POST
+.IR multipart/form-data -encoded
+requests. If the maximum number of pairs is exceeded by the request,
+.I libweb
+shall terminate the connection.
+
+.I max_files
+refers to the maximum number of files that shall be accepted by
+.I libweb
+on
+.B POST
+.IR multipart/form-data -encoded
+requests. If the maximum number of files is exceeded by the request,
+.I libweb
+shall terminate the connection.
+
.SS HTTP payload
When a client submits a request to the server,
diff --git a/handler.c b/handler.c
index f400f2b..3d806e6 100644
--- a/handler.c
+++ b/handler.c
@@ -110,7 +110,8 @@ static struct client *find_or_alloc_client(struct handler *const h,
.length = on_length,
.user = ret,
.tmpdir = h->cfg.tmpdir,
- .max_headers = h->cfg.max_headers
+ .max_headers = h->cfg.max_headers,
+ .post = h->cfg.post
};
*ret = (const struct client)
diff --git a/http.c b/http.c
index 478541e..19a1b93 100644
--- a/http.c
+++ b/http.c
@@ -1728,7 +1728,16 @@ static int apply_from_file(struct http_ctx *const h, struct form *const f)
m->f = NULL;
+ const struct http_cfg_post *const cfg = &h->cfg.post;
const size_t n = m->nfiles + 1;
+
+ if (n > cfg->max_files)
+ {
+ fprintf(stderr, "%s: exceeded maximum number of files (%zu)\n",
+ __func__, cfg->max_files);
+ return 1;
+ }
+
struct http_post_file *const files = realloc(m->files,
n * sizeof *m->files);
@@ -1777,10 +1786,17 @@ static int apply_from_mem(struct http_ctx *const h, struct form *const f)
if (name_exists(m, f))
return 1;
+ const struct http_cfg_post *const cfg = &h->cfg.post;
struct http_post_pair *pairs, *p;
const size_t n = m->npairs + 1;
- if (!(f->value = strndup(h->line, m->written)))
+ if (n > cfg->max_pairs)
+ {
+ fprintf(stderr, "%s: exceeded maximum number of pairs (%zu)\n",
+ __func__, cfg->max_pairs);
+ return 1;
+ }
+ else if (!(f->value = strndup(h->line, m->written)))
{
fprintf(stderr, "%s: strndup(3): %s\n", __func__, strerror(errno));
return -1;
diff --git a/include/libweb/handler.h b/include/libweb/handler.h
index 493e24c..72ef1e0 100644
--- a/include/libweb/handler.h
+++ b/include/libweb/handler.h
@@ -14,6 +14,7 @@ struct handler_cfg
struct http_response *r, void *user);
void *user;
size_t max_headers;
+ struct http_cfg_post post;
};
struct handler *handler_alloc(const struct handler_cfg *cfg);
diff --git a/include/libweb/http.h b/include/libweb/http.h
index 7af66b5..4e80570 100644
--- a/include/libweb/http.h
+++ b/include/libweb/http.h
@@ -106,6 +106,11 @@ struct http_cfg
const char *tmpdir;
void *user;
size_t max_headers;
+
+ struct http_cfg_post
+ {
+ size_t max_pairs, max_files;
+ } post;
};
struct http_ctx *http_alloc(const struct http_cfg *cfg);