From a2cbe890a19ca2341de5b54ffe9c9f5924cf10ec Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Thu, 7 Feb 2019 17:40:27 +0300 Subject: Rejecting requests with invalid "Content-Length". --- src/nxt_http_request.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src/nxt_http_request.c') diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index b80998cb..c8adb499 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -79,14 +79,20 @@ nxt_int_t nxt_http_request_content_length(void *ctx, nxt_http_field_t *field, uintptr_t data) { + nxt_off_t n; nxt_http_request_t *r; r = ctx; - r->content_length = field; - r->content_length_n = nxt_off_t_parse(field->value, field->value_length); - return NXT_OK; + n = nxt_off_t_parse(field->value, field->value_length); + + if (nxt_fast_path(n >= 0)) { + r->content_length_n = n; + return NXT_OK; + } + + return NXT_ERROR; } -- cgit From 2a6b54c23020a24eaadfb4006235ca17dfa877f8 Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Mon, 18 Feb 2019 16:51:30 +0300 Subject: Rejecting requests with duplicate "Content-Length". --- src/nxt_http_request.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'src/nxt_http_request.c') diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index c8adb499..bbc138a7 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -83,13 +83,16 @@ nxt_http_request_content_length(void *ctx, nxt_http_field_t *field, nxt_http_request_t *r; r = ctx; - r->content_length = field; - n = nxt_off_t_parse(field->value, field->value_length); + if (nxt_fast_path(r->content_length == NULL)) { + r->content_length = field; - if (nxt_fast_path(n >= 0)) { - r->content_length_n = n; - return NXT_OK; + n = nxt_off_t_parse(field->value, field->value_length); + + if (nxt_fast_path(n >= 0)) { + r->content_length_n = n; + return NXT_OK; + } } return NXT_ERROR; -- cgit From bb11e9036f8c5bf6f36899bb462709bdbf55bfa4 Mon Sep 17 00:00:00 2001 From: Igor Sysoev Date: Mon, 18 Feb 2019 17:28:55 +0300 Subject: Fixed memory leak on response body sending failure. --- src/nxt_http_request.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/nxt_http_request.c') diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index bbc138a7..ed65a592 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -13,6 +13,8 @@ static void nxt_http_app_request(nxt_task_t *task, void *obj, void *data); static void nxt_http_request_mem_buf_completion(nxt_task_t *task, void *obj, void *data); static void nxt_http_request_done(nxt_task_t *task, void *obj, void *data); +static void nxt_http_request_close_handler(nxt_task_t *task, void *obj, + void *data); static u_char *nxt_http_date(u_char *buf, nxt_realtime_t *now, struct tm *tm, size_t size, const char *format); @@ -449,7 +451,7 @@ nxt_http_request_error_handler(nxt_task_t *task, void *obj, void *data) } -void +static void nxt_http_request_close_handler(nxt_task_t *task, void *obj, void *data) { nxt_http_proto_t proto; -- cgit From 2d4697dbbec7dd51ed5aeebb10e543038e15a359 Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Tue, 19 Feb 2019 20:25:25 +0300 Subject: Validation and normalization of request host. --- src/nxt_http_request.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 110 insertions(+), 7 deletions(-) (limited to 'src/nxt_http_request.c') diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index ed65a592..6029c5c0 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -8,6 +8,7 @@ #include +static nxt_int_t nxt_http_validate_host(nxt_str_t *host, nxt_mp_t *mp); static void nxt_http_request_start(nxt_task_t *task, void *obj, void *data); static void nxt_http_app_request(nxt_task_t *task, void *obj, void *data); static void nxt_http_request_mem_buf_completion(nxt_task_t *task, void *obj, @@ -52,13 +53,118 @@ nxt_http_init(nxt_task_t *task, nxt_runtime_t *rt) nxt_int_t nxt_http_request_host(void *ctx, nxt_http_field_t *field, uintptr_t data) { + nxt_int_t ret; + nxt_str_t host; nxt_http_request_t *r; r = ctx; - /* TODO: validate host. */ + if (nxt_slow_path(r->host.start != NULL)) { + return NXT_HTTP_BAD_REQUEST; + } + + host.length = field->value_length; + host.start = field->value; + + ret = nxt_http_validate_host(&host, r->mem_pool); + + if (nxt_fast_path(ret == NXT_OK)) { + r->host = host; + } + + return ret; +} + + +static nxt_int_t +nxt_http_validate_host(nxt_str_t *host, nxt_mp_t *mp) +{ + u_char *h, ch; + size_t i, dot_pos, host_length; + nxt_bool_t lowcase; + + enum { + sw_usual, + sw_literal, + sw_rest + } state; + + dot_pos = host->length; + host_length = host->length; + + h = host->start; + + lowcase = 0; + state = sw_usual; + + for (i = 0; i < host->length; i++) { + ch = h[i]; + + if (ch > ']') { + /* Short path. */ + continue; + } + + switch (ch) { + + case '.': + if (dot_pos == i - 1) { + return NXT_HTTP_BAD_REQUEST; + } - r->host = field; + dot_pos = i; + break; + + case ':': + if (state == sw_usual) { + host_length = i; + state = sw_rest; + } + + break; + + case '[': + if (i == 0) { + state = sw_literal; + } + + break; + + case ']': + if (state == sw_literal) { + host_length = i + 1; + state = sw_rest; + } + + break; + + case '/': + case '\0': + return NXT_HTTP_BAD_REQUEST; + + default: + if (ch >= 'A' && ch <= 'Z') { + lowcase = 1; + } + + break; + } + } + + if (dot_pos == host_length - 1) { + host_length--; + } + + host->length = host_length; + + if (lowcase) { + host->start = nxt_mp_nget(mp, host_length); + if (nxt_slow_path(host->start == NULL)) { + return NXT_HTTP_INTERNAL_SERVER_ERROR; + } + + nxt_memcpy_lowcase(host->start, h, host_length); + } return NXT_OK; } @@ -97,7 +203,7 @@ nxt_http_request_content_length(void *ctx, nxt_http_field_t *field, } } - return NXT_ERROR; + return NXT_HTTP_BAD_REQUEST; } @@ -237,10 +343,7 @@ nxt_http_app_request(nxt_task_t *task, void *obj, void *data) ar->r.header.query = *r->args; } - if (r->host != NULL) { - ar->r.header.host.length = r->host->value_length; - ar->r.header.host.start = r->host->value; - } + ar->r.header.host = r->host; if (r->content_type != NULL) { ar->r.header.content_type.length = r->content_type->value_length; -- cgit From c5563d142dd189050aee08a00e3079e3e7ff14a7 Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Sat, 23 Feb 2019 14:48:33 +0300 Subject: Removed surplus check for NUL in nxt_http_validate_host(). Such header fields are already rejected by HTTP parser. --- src/nxt_http_request.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src/nxt_http_request.c') diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index 6029c5c0..b7d46c72 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -139,7 +139,6 @@ nxt_http_validate_host(nxt_str_t *host, nxt_mp_t *mp) break; case '/': - case '\0': return NXT_HTTP_BAD_REQUEST; default: -- cgit From d4ccaae900f78b13923a9bd9ee7bbaa33c99b18b Mon Sep 17 00:00:00 2001 From: Igor Sysoev Date: Wed, 27 Feb 2019 16:41:11 +0300 Subject: Initial routing implementation. --- src/nxt_http_request.c | 53 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 8 deletions(-) (limited to 'src/nxt_http_request.c') diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index b7d46c72..f6c14df9 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -10,7 +10,7 @@ static nxt_int_t nxt_http_validate_host(nxt_str_t *host, nxt_mp_t *mp); static void nxt_http_request_start(nxt_task_t *task, void *obj, void *data); -static void nxt_http_app_request(nxt_task_t *task, void *obj, void *data); +static void nxt_http_request_pass(nxt_task_t *task, void *obj, void *data); static void nxt_http_request_mem_buf_completion(nxt_task_t *task, void *obj, void *data); static void nxt_http_request_done(nxt_task_t *task, void *obj, void *data); @@ -278,25 +278,60 @@ nxt_http_request_start(nxt_task_t *task, void *obj, void *data) static const nxt_http_request_state_t nxt_http_request_body_state nxt_aligned(64) = { - .ready_handler = nxt_http_app_request, + .ready_handler = nxt_http_request_pass, .error_handler = nxt_http_request_close_handler, }; static void -nxt_http_app_request(nxt_task_t *task, void *obj, void *data) +nxt_http_request_pass(nxt_task_t *task, void *obj, void *data) +{ + nxt_http_pass_t *pass; + nxt_http_request_t *r; + + r = obj; + + pass = r->conf->socket_conf->pass; + + if (nxt_slow_path(pass == NULL)) { + goto fail; + } + + for ( ;; ) { + nxt_debug(task, "http request route: %V", &pass->name); + + pass = pass->handler(task, r, pass); + if (pass == NULL) { + break; + } + + if (nxt_slow_path(r->pass_count++ == 255)) { + goto fail; + } + } + + return; + +fail: + + nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); +} + + +nxt_http_pass_t * +nxt_http_request_application(nxt_task_t *task, nxt_http_request_t *r, + nxt_http_pass_t *pass) { nxt_int_t ret; nxt_event_engine_t *engine; - nxt_http_request_t *r; nxt_app_parse_ctx_t *ar; - r = obj; + nxt_debug(task, "http request application"); ar = nxt_mp_zget(r->mem_pool, sizeof(nxt_app_parse_ctx_t)); if (nxt_slow_path(ar == NULL)) { nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); - return; + return NULL; } ar->request = r; @@ -370,10 +405,12 @@ nxt_http_app_request(nxt_task_t *task, void *obj, void *data) ret = nxt_http_parse_request_init(&ar->resp_parser, r->mem_pool); if (nxt_slow_path(ret != NXT_OK)) { nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); - return; + return NULL; } - nxt_router_process_http_request(task, ar); + nxt_router_process_http_request(task, ar, pass->u.application); + + return NULL; } -- cgit From e929d08201aae949db25ae8c1051a91e96ba3011 Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Wed, 27 Feb 2019 17:25:07 +0300 Subject: Fixed processing of SERVER_NAME after 77aad2c142a0. Previously, the nxt_router_prepare_msg() function expected server host among other headers unmodified. It's not true anymore since normalization of the Host header has been introduced in 77aad2c142a0. The nxt_unit_split_host() function was removed. It didn't work correctly with IPv6 literals. Anyway, after 77aad2c142a0 the port splitting is done in router while Host header processing. --- src/nxt_http_request.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src/nxt_http_request.c') diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index f6c14df9..724b0808 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -367,6 +367,13 @@ nxt_http_request_application(nxt_task_t *task, nxt_http_request_t *r, ar->r.header.method = *r->method; } + if (r->host.length != 0) { + ar->r.header.server_name = r->host; + + } else { + nxt_str_set(&ar->r.header.server_name, "localhost"); + } + ar->r.header.target = r->target; if (r->path != NULL) { @@ -377,8 +384,6 @@ nxt_http_request_application(nxt_task_t *task, nxt_http_request_t *r, ar->r.header.query = *r->args; } - ar->r.header.host = r->host; - if (r->content_type != NULL) { ar->r.header.content_type.length = r->content_type->value_length; ar->r.header.content_type.start = r->content_type->value; -- cgit