diff options
Diffstat (limited to 'src/http')
| -rw-r--r-- | src/http/modules/ngx_http_fastcgi_module.c | 8 | ||||
| -rw-r--r-- | src/http/modules/ngx_http_grpc_module.c | 15 | ||||
| -rw-r--r-- | src/http/modules/ngx_http_proxy_module.c | 12 | ||||
| -rw-r--r-- | src/http/modules/ngx_http_scgi_module.c | 8 | ||||
| -rw-r--r-- | src/http/modules/ngx_http_uwsgi_module.c | 8 | ||||
| -rw-r--r-- | src/http/ngx_http_parse.c | 118 | ||||
| -rw-r--r-- | src/http/ngx_http_request.c | 47 | ||||
| -rw-r--r-- | src/http/ngx_http_request.h | 36 | ||||
| -rw-r--r-- | src/http/v2/ngx_http_v2.c | 5 |
9 files changed, 132 insertions, 125 deletions
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c index 5191880e3..69ac0f72c 100644 --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -2019,10 +2019,12 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r) break; } - /* there was error while a header line parsing */ + /* rc == NGX_HTTP_PARSE_INVALID_HEADER */ - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "upstream sent invalid header"); + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "upstream sent invalid header: \"%*s\\x%02xd...\"", + r->header_end - r->header_name_start, + r->header_name_start, *r->header_end); return NGX_HTTP_UPSTREAM_INVALID_HEADER; } diff --git a/src/http/modules/ngx_http_grpc_module.c b/src/http/modules/ngx_http_grpc_module.c index 2e20e5ffd..65bd1e6c3 100644 --- a/src/http/modules/ngx_http_grpc_module.c +++ b/src/http/modules/ngx_http_grpc_module.c @@ -121,6 +121,7 @@ typedef struct { unsigned done:1; unsigned status:1; unsigned rst:1; + unsigned goaway:1; ngx_http_request_t *request; @@ -1210,6 +1211,7 @@ ngx_http_grpc_reinit_request(ngx_http_request_t *r) ctx->done = 0; ctx->status = 0; ctx->rst = 0; + ctx->goaway = 0; ctx->connection = NULL; return NGX_OK; @@ -1565,6 +1567,7 @@ ngx_http_grpc_body_output_filter(void *data, ngx_chain_t *in) && ctx->out == NULL && ctx->output_closed && !ctx->output_blocked + && !ctx->goaway && ctx->state == ngx_http_grpc_st_start) { u->keepalive = 1; @@ -1714,6 +1717,8 @@ ngx_http_grpc_process_header(ngx_http_request_t *r) return NGX_HTTP_UPSTREAM_INVALID_HEADER; } + ctx->goaway = 1; + continue; } @@ -1907,6 +1912,7 @@ ngx_http_grpc_process_header(ngx_http_request_t *r) && ctx->out == NULL && ctx->output_closed && !ctx->output_blocked + && !ctx->goaway && b->last == b->pos) { u->keepalive = 1; @@ -2035,6 +2041,7 @@ ngx_http_grpc_filter(void *data, ssize_t bytes) if (ctx->in == NULL && ctx->output_closed && !ctx->output_blocked + && !ctx->goaway && ctx->state == ngx_http_grpc_st_start) { u->keepalive = 1; @@ -2170,6 +2177,8 @@ ngx_http_grpc_filter(void *data, ssize_t bytes) } ctx->rst = 1; + + continue; } if (ctx->type == NGX_HTTP_V2_GOAWAY_FRAME) { @@ -2204,6 +2213,8 @@ ngx_http_grpc_filter(void *data, ssize_t bytes) return NGX_ERROR; } + ctx->goaway = 1; + continue; } @@ -3373,7 +3384,7 @@ ngx_http_grpc_validate_header_name(ngx_http_request_t *r, ngx_str_t *s) return NGX_ERROR; } - if (ch == '\0' || ch == CR || ch == LF) { + if (ch <= 0x20 || ch == 0x7f) { return NGX_ERROR; } } @@ -3475,6 +3486,8 @@ ngx_http_grpc_parse_rst_stream(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx, return NGX_AGAIN; } + ctx->state = ngx_http_grpc_st_start; + return NGX_OK; } diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c index 64190f1a0..368297e77 100644 --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -1186,7 +1186,7 @@ ngx_http_proxy_create_key(ngx_http_request_t *r) loc_len = (r->valid_location && ctx->vars.uri.len) ? plcf->location.len : 0; - if (r->quoted_uri || r->space_in_uri || r->internal) { + if (r->quoted_uri || r->internal) { escape = 2 * ngx_escape_uri(NULL, r->uri.data + loc_len, r->uri.len - loc_len, NGX_ESCAPE_URI); } else { @@ -1299,7 +1299,7 @@ ngx_http_proxy_create_request(ngx_http_request_t *r) loc_len = (r->valid_location && ctx->vars.uri.len) ? plcf->location.len : 0; - if (r->quoted_uri || r->space_in_uri || r->internal) { + if (r->quoted_uri || r->internal) { escape = 2 * ngx_escape_uri(NULL, r->uri.data + loc_len, r->uri.len - loc_len, NGX_ESCAPE_URI); } @@ -2019,10 +2019,12 @@ ngx_http_proxy_process_header(ngx_http_request_t *r) return NGX_AGAIN; } - /* there was error while a header line parsing */ + /* rc == NGX_HTTP_PARSE_INVALID_HEADER */ - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "upstream sent invalid header"); + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "upstream sent invalid header: \"%*s\\x%02xd...\"", + r->header_end - r->header_name_start, + r->header_name_start, *r->header_end); return NGX_HTTP_UPSTREAM_INVALID_HEADER; } diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c index 600999c88..570713df9 100644 --- a/src/http/modules/ngx_http_scgi_module.c +++ b/src/http/modules/ngx_http_scgi_module.c @@ -1140,10 +1140,12 @@ ngx_http_scgi_process_header(ngx_http_request_t *r) return NGX_AGAIN; } - /* there was error while a header line parsing */ + /* rc == NGX_HTTP_PARSE_INVALID_HEADER */ - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "upstream sent invalid header"); + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "upstream sent invalid header: \"%*s\\x%02xd...\"", + r->header_end - r->header_name_start, + r->header_name_start, *r->header_end); return NGX_HTTP_UPSTREAM_INVALID_HEADER; } diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c index 655be98c7..40a06c78e 100644 --- a/src/http/modules/ngx_http_uwsgi_module.c +++ b/src/http/modules/ngx_http_uwsgi_module.c @@ -1361,10 +1361,12 @@ ngx_http_uwsgi_process_header(ngx_http_request_t *r) return NGX_AGAIN; } - /* there was error while a header line parsing */ + /* rc == NGX_HTTP_PARSE_INVALID_HEADER */ - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "upstream sent invalid header"); + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "upstream sent invalid header: \"%*s\\x%02xd...\"", + r->header_end - r->header_name_start, + r->header_name_start, *r->header_end); return NGX_HTTP_UPSTREAM_INVALID_HEADER; } diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c index 20ad89a77..6460da293 100644 --- a/src/http/ngx_http_parse.c +++ b/src/http/ngx_http_parse.c @@ -11,7 +11,7 @@ static uint32_t usual[] = { - 0xffffdbfe, /* 1111 1111 1111 1111 1101 1011 1111 1110 */ + 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ 0x7fff37d6, /* 0111 1111 1111 1111 0011 0111 1101 0110 */ @@ -24,7 +24,7 @@ static uint32_t usual[] = { #endif /* ~}| {zyx wvut srqp onml kjih gfed cba` */ - 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0x7fffffff, /* 0111 1111 1111 1111 1111 1111 1111 1111 */ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ @@ -116,10 +116,8 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) sw_host_end, sw_host_ip_literal, sw_port, - sw_host_http_09, sw_after_slash_in_uri, sw_check_uri, - sw_check_uri_http_09, sw_uri, sw_http_09, sw_http_H, @@ -246,6 +244,11 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) r->method = NGX_HTTP_OPTIONS; } + if (ngx_str7_cmp(m, 'C', 'O', 'N', 'N', 'E', 'C', 'T', ' ')) + { + r->method = NGX_HTTP_CONNECT; + } + break; case 8: @@ -393,7 +396,7 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) */ r->uri_start = r->schema_end + 1; r->uri_end = r->schema_end + 2; - state = sw_host_http_09; + state = sw_http_09; break; default: return NGX_HTTP_PARSE_INVALID_REQUEST; @@ -467,35 +470,13 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) */ r->uri_start = r->schema_end + 1; r->uri_end = r->schema_end + 2; - state = sw_host_http_09; - break; - default: - return NGX_HTTP_PARSE_INVALID_REQUEST; - } - break; - - /* space+ after "http://host[:port] " */ - case sw_host_http_09: - switch (ch) { - case ' ': - break; - case CR: - r->http_minor = 9; - state = sw_almost_done; - break; - case LF: - r->http_minor = 9; - goto done; - case 'H': - r->http_protocol.data = p; - state = sw_http_H; + state = sw_http_09; break; default: return NGX_HTTP_PARSE_INVALID_REQUEST; } break; - /* check "/.", "//", "%", and "\" (Win32) in URI */ case sw_after_slash_in_uri: @@ -507,7 +488,7 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) switch (ch) { case ' ': r->uri_end = p; - state = sw_check_uri_http_09; + state = sw_http_09; break; case CR: r->uri_end = p; @@ -547,9 +528,10 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) case '+': r->plus_in_uri = 1; break; - case '\0': - return NGX_HTTP_PARSE_INVALID_REQUEST; default: + if (ch < 0x20 || ch == 0x7f) { + return NGX_HTTP_PARSE_INVALID_REQUEST; + } state = sw_check_uri; break; } @@ -579,7 +561,7 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) break; case ' ': r->uri_end = p; - state = sw_check_uri_http_09; + state = sw_http_09; break; case CR: r->uri_end = p; @@ -611,36 +593,14 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) case '+': r->plus_in_uri = 1; break; - case '\0': - return NGX_HTTP_PARSE_INVALID_REQUEST; - } - break; - - /* space+ after URI */ - case sw_check_uri_http_09: - switch (ch) { - case ' ': - break; - case CR: - r->http_minor = 9; - state = sw_almost_done; - break; - case LF: - r->http_minor = 9; - goto done; - case 'H': - r->http_protocol.data = p; - state = sw_http_H; - break; default: - r->space_in_uri = 1; - state = sw_check_uri; - p--; + if (ch < 0x20 || ch == 0x7f) { + return NGX_HTTP_PARSE_INVALID_REQUEST; + } break; } break; - /* URI */ case sw_uri: @@ -665,8 +625,11 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) case '#': r->complex_uri = 1; break; - case '\0': - return NGX_HTTP_PARSE_INVALID_REQUEST; + default: + if (ch < 0x20 || ch == 0x7f) { + return NGX_HTTP_PARSE_INVALID_REQUEST; + } + break; } break; @@ -687,10 +650,7 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) state = sw_http_H; break; default: - r->space_in_uri = 1; - state = sw_uri; - p--; - break; + return NGX_HTTP_PARSE_INVALID_REQUEST; } break; @@ -933,7 +893,8 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b, break; } - if (ch == '\0') { + if (ch <= 0x20 || ch == 0x7f || ch == ':') { + r->header_end = p; return NGX_HTTP_PARSE_INVALID_HEADER; } @@ -1001,7 +962,8 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b, break; } - if (ch == '\0') { + if (ch <= 0x20 || ch == 0x7f) { + r->header_end = p; return NGX_HTTP_PARSE_INVALID_HEADER; } @@ -1024,6 +986,7 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b, r->header_end = p; goto done; case '\0': + r->header_end = p; return NGX_HTTP_PARSE_INVALID_HEADER; default: r->header_start = p; @@ -1047,6 +1010,7 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b, r->header_end = p; goto done; case '\0': + r->header_end = p; return NGX_HTTP_PARSE_INVALID_HEADER; } break; @@ -1062,6 +1026,7 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b, case LF: goto done; case '\0': + r->header_end = p; return NGX_HTTP_PARSE_INVALID_HEADER; default: state = sw_value; @@ -1165,10 +1130,6 @@ ngx_http_parse_uri(ngx_http_request_t *r) } switch (ch) { - case ' ': - r->space_in_uri = 1; - state = sw_check_uri; - break; case '.': r->complex_uri = 1; state = sw_uri; @@ -1199,6 +1160,9 @@ ngx_http_parse_uri(ngx_http_request_t *r) r->plus_in_uri = 1; break; default: + if (ch <= 0x20 || ch == 0x7f) { + return NGX_ERROR; + } state = sw_check_uri; break; } @@ -1226,9 +1190,6 @@ ngx_http_parse_uri(ngx_http_request_t *r) case '.': r->uri_ext = p + 1; break; - case ' ': - r->space_in_uri = 1; - break; #if (NGX_WIN32) case '\\': r->complex_uri = 1; @@ -1250,6 +1211,11 @@ ngx_http_parse_uri(ngx_http_request_t *r) case '+': r->plus_in_uri = 1; break; + default: + if (ch <= 0x20 || ch == 0x7f) { + return NGX_ERROR; + } + break; } break; @@ -1261,12 +1227,14 @@ ngx_http_parse_uri(ngx_http_request_t *r) } switch (ch) { - case ' ': - r->space_in_uri = 1; - break; case '#': r->complex_uri = 1; break; + default: + if (ch <= 0x20 || ch == 0x7f) { + return NGX_ERROR; + } + break; } break; } diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index 1816c0360..a27d29368 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -1273,7 +1273,7 @@ ngx_http_process_request_uri(ngx_http_request_t *r) r->unparsed_uri.len = r->uri_end - r->uri_start; r->unparsed_uri.data = r->uri_start; - r->valid_unparsed_uri = (r->space_in_uri || r->empty_path_in_uri) ? 0 : 1; + r->valid_unparsed_uri = r->empty_path_in_uri ? 0 : 1; if (r->uri_ext) { if (r->args_start) { @@ -1531,7 +1531,9 @@ ngx_http_process_request_headers(ngx_event_t *rev) /* rc == NGX_HTTP_PARSE_INVALID_HEADER */ ngx_log_error(NGX_LOG_INFO, c->log, 0, - "client sent invalid header line"); + "client sent invalid header line: \"%*s\\x%02xd...\"", + r->header_end - r->header_name_start, + r->header_name_start, *r->header_end); ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); break; @@ -1989,20 +1991,20 @@ ngx_http_process_request_header(ngx_http_request_t *r) } } - if (r->method == NGX_HTTP_TRACE) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "client sent TRACE method"); - ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED); - return NGX_ERROR; - } - if (r->headers_in.transfer_encoding) { if (r->headers_in.transfer_encoding->value.len == 7 && ngx_strncasecmp(r->headers_in.transfer_encoding->value.data, (u_char *) "chunked", 7) == 0) { - r->headers_in.content_length = NULL; - r->headers_in.content_length_n = -1; + if (r->headers_in.content_length) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent \"Content-Length\" and " + "\"Transfer-Encoding\" headers " + "at the same time"); + ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); + return NGX_ERROR; + } + r->headers_in.chunked = 1; } else { @@ -2022,6 +2024,20 @@ ngx_http_process_request_header(ngx_http_request_t *r) } } + if (r->method == NGX_HTTP_CONNECT) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent CONNECT method"); + ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED); + return NGX_ERROR; + } + + if (r->method == NGX_HTTP_TRACE) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent TRACE method"); + ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED); + return NGX_ERROR; + } + return NGX_OK; } @@ -2169,15 +2185,16 @@ ngx_http_validate_host(ngx_str_t *host, ngx_pool_t *pool, ngx_uint_t alloc) } break; - case '\0': - return NGX_DECLINED; - default: if (ngx_path_separator(ch)) { return NGX_DECLINED; } + if (ch <= 0x20 || ch == 0x7f) { + return NGX_DECLINED; + } + if (ch >= 'A' && ch <= 'Z') { alloc = 1; } @@ -3429,6 +3446,8 @@ ngx_http_set_lingering_close(ngx_connection_t *c) if (c->ssl) { ngx_int_t rc; + c->ssl->shutdown_without_free = 1; + rc = ngx_ssl_shutdown(c); if (rc == NGX_ERROR) { diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h index 60ef4fec1..cd6bd6618 100644 --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -26,22 +26,23 @@ #define NGX_HTTP_VERSION_20 2000 #define NGX_HTTP_VERSION_30 3000 -#define NGX_HTTP_UNKNOWN 0x0001 -#define NGX_HTTP_GET 0x0002 -#define NGX_HTTP_HEAD 0x0004 -#define NGX_HTTP_POST 0x0008 -#define NGX_HTTP_PUT 0x0010 -#define NGX_HTTP_DELETE 0x0020 -#define NGX_HTTP_MKCOL 0x0040 -#define NGX_HTTP_COPY 0x0080 -#define NGX_HTTP_MOVE 0x0100 -#define NGX_HTTP_OPTIONS 0x0200 -#define NGX_HTTP_PROPFIND 0x0400 -#define NGX_HTTP_PROPPATCH 0x0800 -#define NGX_HTTP_LOCK 0x1000 -#define NGX_HTTP_UNLOCK 0x2000 -#define NGX_HTTP_PATCH 0x4000 -#define NGX_HTTP_TRACE 0x8000 +#define NGX_HTTP_UNKNOWN 0x00000001 +#define NGX_HTTP_GET 0x00000002 +#define NGX_HTTP_HEAD 0x00000004 +#define NGX_HTTP_POST 0x00000008 +#define NGX_HTTP_PUT 0x00000010 +#define NGX_HTTP_DELETE 0x00000020 +#define NGX_HTTP_MKCOL 0x00000040 +#define NGX_HTTP_COPY 0x00000080 +#define NGX_HTTP_MOVE 0x00000100 +#define NGX_HTTP_OPTIONS 0x00000200 +#define NGX_HTTP_PROPFIND 0x00000400 +#define NGX_HTTP_PROPPATCH 0x00000800 +#define NGX_HTTP_LOCK 0x00001000 +#define NGX_HTTP_UNLOCK 0x00002000 +#define NGX_HTTP_PATCH 0x00004000 +#define NGX_HTTP_TRACE 0x00008000 +#define NGX_HTTP_CONNECT 0x00010000 #define NGX_HTTP_CONNECTION_CLOSE 1 #define NGX_HTTP_CONNECTION_KEEP_ALIVE 2 @@ -473,9 +474,6 @@ struct ngx_http_request_s { /* URI with "+" */ unsigned plus_in_uri:1; - /* URI with " " */ - unsigned space_in_uri:1; - /* URI with empty path */ unsigned empty_path_in_uri:1; diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c index 3611a2e50..3bef002bd 100644 --- a/src/http/v2/ngx_http_v2.c +++ b/src/http/v2/ngx_http_v2.c @@ -3457,7 +3457,7 @@ ngx_http_v2_validate_header(ngx_http_request_t *r, ngx_http_v2_header_t *header) continue; } - if (ch == '\0' || ch == LF || ch == CR || ch == ':' + if (ch <= 0x20 || ch == 0x7f || ch == ':' || (ch >= 'A' && ch <= 'Z')) { ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, @@ -3606,7 +3606,8 @@ ngx_http_v2_parse_method(ngx_http_request_t *r, ngx_str_t *value) { 4, "LOCK", NGX_HTTP_LOCK }, { 6, "UNLOCK", NGX_HTTP_UNLOCK }, { 5, "PATCH", NGX_HTTP_PATCH }, - { 5, "TRACE", NGX_HTTP_TRACE } + { 5, "TRACE", NGX_HTTP_TRACE }, + { 7, "CONNECT", NGX_HTTP_CONNECT } }, *test; if (r->method_name.len) { |
