Mercurial > hg > nginx-quic
changeset 4035:c2a91088b0c0
Now if total size of all ranges is greater than source response size,
then nginx disables ranges and returns just the source response.
This fix should not affect well-behaving applications but will defeat
DoS attempts exploiting malicious byte ranges.
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Fri, 26 Aug 2011 09:42:50 +0000 |
parents | e2c075e774b6 |
children | 20c7c73d3efa |
files | src/http/modules/ngx_http_range_filter_module.c |
diffstat | 1 files changed, 23 insertions(+), 14 deletions(-) [+] |
line wrap: on
line diff
--- a/src/http/modules/ngx_http_range_filter_module.c +++ b/src/http/modules/ngx_http_range_filter_module.c @@ -146,7 +146,6 @@ static ngx_int_t ngx_http_range_header_filter(ngx_http_request_t *r) { time_t if_range; - ngx_int_t rc; ngx_http_range_filter_ctx_t *ctx; if (r->http_version < NGX_HTTP_VERSION_10 @@ -192,10 +191,9 @@ ngx_http_range_header_filter(ngx_http_re return NGX_ERROR; } - rc = ngx_http_range_parse(r, ctx); + switch (ngx_http_range_parse(r, ctx)) { - if (rc == NGX_OK) { - + case NGX_OK: ngx_http_set_ctx(r, ctx, ngx_http_range_body_filter_module); r->headers_out.status = NGX_HTTP_PARTIAL_CONTENT; @@ -206,16 +204,17 @@ ngx_http_range_header_filter(ngx_http_re } return ngx_http_range_multipart_header(r, ctx); - } + + case NGX_HTTP_RANGE_NOT_SATISFIABLE: + return ngx_http_range_not_satisfiable(r); - if (rc == NGX_HTTP_RANGE_NOT_SATISFIABLE) { - return ngx_http_range_not_satisfiable(r); + case NGX_ERROR: + return NGX_ERROR; + + default: /* NGX_DECLINED */ + break; } - /* rc == NGX_ERROR */ - - return rc; - next_filter: r->headers_out.accept_ranges = ngx_list_push(&r->headers_out.headers); @@ -235,11 +234,12 @@ ngx_int_t ngx_http_range_parse(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx) { u_char *p; - off_t start, end; + off_t start, end, size; ngx_uint_t suffix; ngx_http_range_t *range; p = r->headers_in.range->value.data + 6; + size = 0; for ( ;; ) { start = 0; @@ -277,9 +277,10 @@ ngx_http_range_parse(ngx_http_request_t range->start = start; range->end = r->headers_out.content_length_n; + size += range->end - start; if (*p++ != ',') { - return NGX_OK; + break; } continue; @@ -331,10 +332,18 @@ ngx_http_range_parse(ngx_http_request_t range->end = end + 1; } + size += range->end - start; + if (*p++ != ',') { - return NGX_OK; + break; } } + + if (size > r->headers_out.content_length_n) { + return NGX_DECLINED; + } + + return NGX_OK; }