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.
This commit is contained in:
parent
9d9e0c2979
commit
afe0681c0b
|
@ -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);
|
int (*\fIlength\fP)(unsigned long long len, const struct http_cookie *c, struct http_response *r, void *user);
|
||||||
void *\fIuser\fP;
|
void *\fIuser\fP;
|
||||||
size_t \fImax_headers\fP;
|
size_t \fImax_headers\fP;
|
||||||
|
struct http_cfg_post \fIpost\fP;
|
||||||
};
|
};
|
||||||
.EE
|
.EE
|
||||||
.in
|
.in
|
||||||
|
@ -83,9 +84,10 @@ struct handler_cfg
|
||||||
|
|
||||||
.IR tmpdir ,
|
.IR tmpdir ,
|
||||||
.IR length ,
|
.IR length ,
|
||||||
.I user
|
.IR user ,
|
||||||
and
|
|
||||||
.I max_headers
|
.I max_headers
|
||||||
|
and
|
||||||
|
.I post
|
||||||
are passed directly to the
|
are passed directly to the
|
||||||
.I struct http_cfg
|
.I struct http_cfg
|
||||||
object used to initialize a
|
object used to initialize a
|
||||||
|
|
|
@ -94,6 +94,11 @@ struct http_cfg
|
||||||
const char *\fItmpdir\fP;
|
const char *\fItmpdir\fP;
|
||||||
void *\fIuser\fP;
|
void *\fIuser\fP;
|
||||||
size_t \fImax_headers\fP;
|
size_t \fImax_headers\fP;
|
||||||
|
|
||||||
|
struct http_cfg_post
|
||||||
|
{
|
||||||
|
size_t \fImax_pairs\fP, \fImax_files\fP;
|
||||||
|
} \fIpost\fP;
|
||||||
};
|
};
|
||||||
.EE
|
.EE
|
||||||
.in
|
.in
|
||||||
|
@ -221,6 +226,31 @@ Any extra headers sent by the client outside this maximum value shall be
|
||||||
silently ignored by
|
silently ignored by
|
||||||
.IR libweb .
|
.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
|
.SS HTTP payload
|
||||||
|
|
||||||
When a client submits a request to the server,
|
When a client submits a request to the server,
|
||||||
|
|
|
@ -110,7 +110,8 @@ static struct client *find_or_alloc_client(struct handler *const h,
|
||||||
.length = on_length,
|
.length = on_length,
|
||||||
.user = ret,
|
.user = ret,
|
||||||
.tmpdir = h->cfg.tmpdir,
|
.tmpdir = h->cfg.tmpdir,
|
||||||
.max_headers = h->cfg.max_headers
|
.max_headers = h->cfg.max_headers,
|
||||||
|
.post = h->cfg.post
|
||||||
};
|
};
|
||||||
|
|
||||||
*ret = (const struct client)
|
*ret = (const struct client)
|
||||||
|
|
18
http.c
18
http.c
|
@ -1728,7 +1728,16 @@ static int apply_from_file(struct http_ctx *const h, struct form *const f)
|
||||||
|
|
||||||
m->f = NULL;
|
m->f = NULL;
|
||||||
|
|
||||||
|
const struct http_cfg_post *const cfg = &h->cfg.post;
|
||||||
const size_t n = m->nfiles + 1;
|
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,
|
struct http_post_file *const files = realloc(m->files,
|
||||||
n * sizeof *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))
|
if (name_exists(m, f))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
const struct http_cfg_post *const cfg = &h->cfg.post;
|
||||||
struct http_post_pair *pairs, *p;
|
struct http_post_pair *pairs, *p;
|
||||||
const size_t n = m->npairs + 1;
|
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));
|
fprintf(stderr, "%s: strndup(3): %s\n", __func__, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -14,6 +14,7 @@ struct handler_cfg
|
||||||
struct http_response *r, void *user);
|
struct http_response *r, void *user);
|
||||||
void *user;
|
void *user;
|
||||||
size_t max_headers;
|
size_t max_headers;
|
||||||
|
struct http_cfg_post post;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct handler *handler_alloc(const struct handler_cfg *cfg);
|
struct handler *handler_alloc(const struct handler_cfg *cfg);
|
||||||
|
|
|
@ -106,6 +106,11 @@ struct http_cfg
|
||||||
const char *tmpdir;
|
const char *tmpdir;
|
||||||
void *user;
|
void *user;
|
||||||
size_t max_headers;
|
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);
|
struct http_ctx *http_alloc(const struct http_cfg *cfg);
|
||||||
|
|
Loading…
Reference in New Issue