diff options
Diffstat (limited to 'usr.sbin/nginx/src/http/ngx_http_parse.c')
| -rw-r--r-- | usr.sbin/nginx/src/http/ngx_http_parse.c | 98 |
1 files changed, 88 insertions, 10 deletions
diff --git a/usr.sbin/nginx/src/http/ngx_http_parse.c b/usr.sbin/nginx/src/http/ngx_http_parse.c index f8d5910ddef..02b4a0fd109 100644 --- a/usr.sbin/nginx/src/http/ngx_http_parse.c +++ b/usr.sbin/nginx/src/http/ngx_http_parse.c @@ -212,14 +212,17 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) case 5: if (ngx_str5cmp(m, 'M', 'K', 'C', 'O', 'L')) { r->method = NGX_HTTP_MKCOL; + break; } if (ngx_str5cmp(m, 'P', 'A', 'T', 'C', 'H')) { r->method = NGX_HTTP_PATCH; + break; } if (ngx_str5cmp(m, 'T', 'R', 'A', 'C', 'E')) { r->method = NGX_HTTP_TRACE; + break; } break; @@ -883,6 +886,19 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b, break; } + if (ch == '_') { + if (allow_underscores) { + hash = ngx_hash(0, ch); + r->lowcase_header[0] = ch; + i = 1; + + } else { + r->invalid_header = 1; + } + + break; + } + if (ch == '\0') { return NGX_HTTP_PARSE_INVALID_HEADER; } @@ -1258,8 +1274,8 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes) * the line feed */ - ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "s:%d in:'%Xd:%c', out:'%c'", state, ch, ch, *u); + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "s:%d in:'%Xd:%c'", state, ch, ch); switch (state) { @@ -1777,17 +1793,21 @@ ngx_int_t ngx_http_parse_unsafe_uri(ngx_http_request_t *r, ngx_str_t *uri, ngx_str_t *args, ngx_uint_t *flags) { - u_char ch, *p; - size_t len; + u_char ch, *p, *src, *dst; + size_t len; + ngx_uint_t quoted; len = uri->len; p = uri->data; + quoted = 0; if (len == 0 || p[0] == '?') { goto unsafe; } - if (p[0] == '.' && len == 3 && p[1] == '.' && (ngx_path_separator(p[2]))) { + if (p[0] == '.' && len > 1 && p[1] == '.' + && (len == 2 || ngx_path_separator(p[2]))) + { goto unsafe; } @@ -1795,6 +1815,11 @@ ngx_http_parse_unsafe_uri(ngx_http_request_t *r, ngx_str_t *uri, ch = *p++; + if (ch == '%') { + quoted = 1; + continue; + } + if (usual[ch >> 5] & (1 << (ch & 0x1f))) { continue; } @@ -1804,7 +1829,7 @@ ngx_http_parse_unsafe_uri(ngx_http_request_t *r, ngx_str_t *uri, args->data = p; uri->len -= len; - return NGX_OK; + break; } if (ch == '\0') { @@ -1813,14 +1838,66 @@ ngx_http_parse_unsafe_uri(ngx_http_request_t *r, ngx_str_t *uri, if (ngx_path_separator(ch) && len > 2) { - /* detect "/../" */ + /* detect "/../" and "/.." */ - if (p[0] == '.' && p[1] == '.' && ngx_path_separator(p[2])) { + if (p[0] == '.' && p[1] == '.' + && (len == 3 || ngx_path_separator(p[2]))) + { goto unsafe; } } } + if (quoted) { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "escaped URI: \"%V\"", uri); + + src = uri->data; + + dst = ngx_pnalloc(r->pool, uri->len); + if (dst == NULL) { + return NGX_ERROR; + } + + uri->data = dst; + + ngx_unescape_uri(&dst, &src, uri->len, 0); + + uri->len = dst - uri->data; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "unescaped URI: \"%V\"", uri); + + len = uri->len; + p = uri->data; + + if (p[0] == '.' && len > 1 && p[1] == '.' + && (len == 2 || ngx_path_separator(p[2]))) + { + goto unsafe; + } + + for ( /* void */ ; len; len--) { + + ch = *p++; + + if (ch == '\0') { + goto unsafe; + } + + if (ngx_path_separator(ch) && len > 2) { + + /* detect "/../" and "/.." */ + + if (p[0] == '.' && p[1] == '.' + && (len == 3 || ngx_path_separator(p[2]))) + { + goto unsafe; + } + } + } + } + return NGX_OK; unsafe: @@ -2182,8 +2259,9 @@ data: ctx->length = 3 /* "0" LF LF */; break; case sw_chunk_size: - ctx->length = 2 /* LF LF */ - + (ctx->size ? ctx->size + 4 /* LF "0" LF LF */ : 0); + ctx->length = 1 /* LF */ + + (ctx->size ? ctx->size + 4 /* LF "0" LF LF */ + : 1 /* LF */); break; case sw_chunk_extension: case sw_chunk_extension_almost_done: |
