aboutsummaryrefslogtreecommitdiffstats
path: root/src/libutil/http.c
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2016-07-30 13:56:04 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2016-07-30 13:56:04 +0100
commite36b9317f9ad222393385a5e6a3806d5e88c9a89 (patch)
tree4b401b83d5b4a8344b170901e9eefffa41202988 /src/libutil/http.c
parentf58e36df4d8e262134dc145bb08757928fa774a9 (diff)
downloadrspamd-e36b9317f9ad222393385a5e6a3806d5e88c9a89.tar.gz
rspamd-e36b9317f9ad222393385a5e6a3806d5e88c9a89.zip
[Fix] Set max size on per connection basis
Diffstat (limited to 'src/libutil/http.c')
-rw-r--r--src/libutil/http.c47
1 files changed, 31 insertions, 16 deletions
diff --git a/src/libutil/http.c b/src/libutil/http.c
index 03d28db77..d7f10d20f 100644
--- a/src/libutil/http.c
+++ b/src/libutil/http.c
@@ -102,7 +102,6 @@ static const rspamd_ftok_t last_modified_header = {
.begin = "Last-Modified",
.len = 13
};
-static gsize rspamd_http_global_max_size = 0;
static void rspamd_http_message_storage_cleanup (struct rspamd_http_message *msg);
static gboolean rspamd_http_message_grow_body (struct rspamd_http_message *msg,
@@ -617,16 +616,23 @@ rspamd_http_on_headers_complete (http_parser * parser)
priv->flags &= ~RSPAMD_HTTP_CONN_FLAG_NEW_HEADER;
}
- if (conn->type == RSPAMD_HTTP_SERVER &&
- rspamd_http_global_max_size > 0 &&
- parser->content_length > rspamd_http_global_max_size) {
- /* Too large message */
- priv->flags |= RSPAMD_HTTP_CONN_FLAG_TOO_LARGE;
- return -1;
- }
+ /*
+ * HTTP parser sets content length to (-1) when it doesn't know the real
+ * length, for example, in case of chunked encoding.
+ *
+ * Hence, we skip body setup here
+ */
+ if (parser->content_length != ULLONG_MAX) {
+ if (conn->max_size > 0 &&
+ parser->content_length > conn->max_size) {
+ /* Too large message */
+ priv->flags |= RSPAMD_HTTP_CONN_FLAG_TOO_LARGE;
+ return -1;
+ }
- if (!rspamd_http_message_set_body (msg, NULL, parser->content_length)) {
- return -1;
+ if (!rspamd_http_message_set_body (msg, NULL, parser->content_length)) {
+ return -1;
+ }
}
if (parser->flags & F_SPAMC) {
@@ -663,9 +669,14 @@ rspamd_http_on_body (http_parser * parser, const gchar *at, size_t length)
pbuf = priv->buf;
p = at;
- if (conn->type == RSPAMD_HTTP_SERVER &&
- rspamd_http_global_max_size > 0 &&
- msg->body_buf.len + length > rspamd_http_global_max_size) {
+ if (!(msg->flags & RSPAMD_HTTP_FLAG_HAS_BODY)) {
+ if (!rspamd_http_message_set_body (msg, NULL, parser->content_length)) {
+ return -1;
+ }
+ }
+
+ if (conn->max_size > 0 &&
+ msg->body_buf.len + length > conn->max_size) {
/* Body length overflow */
priv->flags |= RSPAMD_HTTP_CONN_FLAG_TOO_LARGE;
return -1;
@@ -1097,7 +1108,8 @@ rspamd_http_event_handler (int fd, short what, gpointer ud)
d, r) != (size_t)r || priv->parser.http_errno != 0) {
if (priv->flags & RSPAMD_HTTP_CONN_FLAG_TOO_LARGE) {
err = g_error_new (HTTP_ERROR, 413,
- "Request entity too large");
+ "Request entity too large: %zu",
+ (size_t)priv->parser.content_length);
}
else {
err = g_error_new (HTTP_ERROR, priv->parser.http_errno,
@@ -2331,6 +2343,8 @@ rspamd_http_message_set_body (struct rspamd_http_message *msg,
msg->body_buf.allocated_len = storage->normal->allocated;
}
+ msg->flags |= RSPAMD_HTTP_FLAG_HAS_BODY;
+
return TRUE;
}
@@ -2536,9 +2550,10 @@ rspamd_http_message_storage_cleanup (struct rspamd_http_message *msg)
}
void
-rspamd_http_message_set_max_size (gsize sz)
+rspamd_http_connection_set_max_size (struct rspamd_http_connection *conn,
+ gsize sz)
{
- rspamd_http_global_max_size = sz;
+ conn->max_size = sz;
}
void