Mercurial > hg > nginx-quic
comparison src/http/modules/ngx_http_range_filter_module.c @ 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 | dd1570b6f237 |
children | 20c7c73d3efa |
comparison
equal
deleted
inserted
replaced
4034:e2c075e774b6 | 4035:c2a91088b0c0 |
---|---|
144 | 144 |
145 static ngx_int_t | 145 static ngx_int_t |
146 ngx_http_range_header_filter(ngx_http_request_t *r) | 146 ngx_http_range_header_filter(ngx_http_request_t *r) |
147 { | 147 { |
148 time_t if_range; | 148 time_t if_range; |
149 ngx_int_t rc; | |
150 ngx_http_range_filter_ctx_t *ctx; | 149 ngx_http_range_filter_ctx_t *ctx; |
151 | 150 |
152 if (r->http_version < NGX_HTTP_VERSION_10 | 151 if (r->http_version < NGX_HTTP_VERSION_10 |
153 || r->headers_out.status != NGX_HTTP_OK | 152 || r->headers_out.status != NGX_HTTP_OK |
154 || r != r->main | 153 || r != r->main |
190 != NGX_OK) | 189 != NGX_OK) |
191 { | 190 { |
192 return NGX_ERROR; | 191 return NGX_ERROR; |
193 } | 192 } |
194 | 193 |
195 rc = ngx_http_range_parse(r, ctx); | 194 switch (ngx_http_range_parse(r, ctx)) { |
196 | 195 |
197 if (rc == NGX_OK) { | 196 case NGX_OK: |
198 | |
199 ngx_http_set_ctx(r, ctx, ngx_http_range_body_filter_module); | 197 ngx_http_set_ctx(r, ctx, ngx_http_range_body_filter_module); |
200 | 198 |
201 r->headers_out.status = NGX_HTTP_PARTIAL_CONTENT; | 199 r->headers_out.status = NGX_HTTP_PARTIAL_CONTENT; |
202 r->headers_out.status_line.len = 0; | 200 r->headers_out.status_line.len = 0; |
203 | 201 |
204 if (ctx->ranges.nelts == 1) { | 202 if (ctx->ranges.nelts == 1) { |
205 return ngx_http_range_singlepart_header(r, ctx); | 203 return ngx_http_range_singlepart_header(r, ctx); |
206 } | 204 } |
207 | 205 |
208 return ngx_http_range_multipart_header(r, ctx); | 206 return ngx_http_range_multipart_header(r, ctx); |
209 } | 207 |
210 | 208 case NGX_HTTP_RANGE_NOT_SATISFIABLE: |
211 if (rc == NGX_HTTP_RANGE_NOT_SATISFIABLE) { | |
212 return ngx_http_range_not_satisfiable(r); | 209 return ngx_http_range_not_satisfiable(r); |
213 } | 210 |
214 | 211 case NGX_ERROR: |
215 /* rc == NGX_ERROR */ | 212 return NGX_ERROR; |
216 | 213 |
217 return rc; | 214 default: /* NGX_DECLINED */ |
215 break; | |
216 } | |
218 | 217 |
219 next_filter: | 218 next_filter: |
220 | 219 |
221 r->headers_out.accept_ranges = ngx_list_push(&r->headers_out.headers); | 220 r->headers_out.accept_ranges = ngx_list_push(&r->headers_out.headers); |
222 if (r->headers_out.accept_ranges == NULL) { | 221 if (r->headers_out.accept_ranges == NULL) { |
233 | 232 |
234 ngx_int_t | 233 ngx_int_t |
235 ngx_http_range_parse(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx) | 234 ngx_http_range_parse(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx) |
236 { | 235 { |
237 u_char *p; | 236 u_char *p; |
238 off_t start, end; | 237 off_t start, end, size; |
239 ngx_uint_t suffix; | 238 ngx_uint_t suffix; |
240 ngx_http_range_t *range; | 239 ngx_http_range_t *range; |
241 | 240 |
242 p = r->headers_in.range->value.data + 6; | 241 p = r->headers_in.range->value.data + 6; |
242 size = 0; | |
243 | 243 |
244 for ( ;; ) { | 244 for ( ;; ) { |
245 start = 0; | 245 start = 0; |
246 end = 0; | 246 end = 0; |
247 suffix = 0; | 247 suffix = 0; |
275 return NGX_ERROR; | 275 return NGX_ERROR; |
276 } | 276 } |
277 | 277 |
278 range->start = start; | 278 range->start = start; |
279 range->end = r->headers_out.content_length_n; | 279 range->end = r->headers_out.content_length_n; |
280 size += range->end - start; | |
280 | 281 |
281 if (*p++ != ',') { | 282 if (*p++ != ',') { |
282 return NGX_OK; | 283 break; |
283 } | 284 } |
284 | 285 |
285 continue; | 286 continue; |
286 } | 287 } |
287 | 288 |
329 | 330 |
330 } else { | 331 } else { |
331 range->end = end + 1; | 332 range->end = end + 1; |
332 } | 333 } |
333 | 334 |
335 size += range->end - start; | |
336 | |
334 if (*p++ != ',') { | 337 if (*p++ != ',') { |
335 return NGX_OK; | 338 break; |
336 } | 339 } |
337 } | 340 } |
341 | |
342 if (size > r->headers_out.content_length_n) { | |
343 return NGX_DECLINED; | |
344 } | |
345 | |
346 return NGX_OK; | |
338 } | 347 } |
339 | 348 |
340 | 349 |
341 static ngx_int_t | 350 static ngx_int_t |
342 ngx_http_range_singlepart_header(ngx_http_request_t *r, | 351 ngx_http_range_singlepart_header(ngx_http_request_t *r, |