diff options
Diffstat (limited to 'src/http/ngx_http_request.c')
| -rw-r--r-- | src/http/ngx_http_request.c | 788 |
1 files changed, 455 insertions, 333 deletions
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index 763e7bf11..54e1c262e 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -21,21 +21,24 @@ static ngx_int_t ngx_http_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t ngx_http_process_unique_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t ngx_http_process_multi_header_lines(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t ngx_http_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t ngx_http_process_user_agent(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset); -static ngx_int_t ngx_http_process_cookie(ngx_http_request_t *r, - ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r); static void ngx_http_process_request(ngx_http_request_t *r); -static ssize_t ngx_http_validate_host(ngx_http_request_t *r, u_char **host, - size_t len, ngx_uint_t alloc); -static ngx_int_t ngx_http_find_virtual_server(ngx_http_request_t *r, - u_char *host, size_t len); +static ngx_int_t ngx_http_validate_host(ngx_str_t *host, ngx_pool_t *pool, + ngx_uint_t alloc); +static ngx_int_t ngx_http_set_virtual_server(ngx_http_request_t *r, + ngx_str_t *host); +static ngx_int_t ngx_http_find_virtual_server(ngx_connection_t *c, + ngx_http_virtual_names_t *virtual_names, ngx_str_t *host, + ngx_http_request_t *r, ngx_http_core_srv_conf_t **cscfp); static void ngx_http_request_handler(ngx_event_t *ev); static void ngx_http_terminate_request(ngx_http_request_t *r, ngx_int_t rc); @@ -153,7 +156,7 @@ ngx_http_header_t ngx_http_headers_in[] = { #if (NGX_HTTP_X_FORWARDED_FOR) { ngx_string("X-Forwarded-For"), offsetof(ngx_http_headers_in_t, x_forwarded_for), - ngx_http_process_header_line }, + ngx_http_process_multi_header_lines }, #endif #if (NGX_HTTP_REALIP) @@ -185,7 +188,8 @@ ngx_http_header_t ngx_http_headers_in[] = { ngx_http_process_header_line }, #endif - { ngx_string("Cookie"), 0, ngx_http_process_cookie }, + { ngx_string("Cookie"), offsetof(ngx_http_headers_in_t, cookies), + ngx_http_process_multi_header_lines }, { ngx_null_string, 0, NULL } }; @@ -194,137 +198,30 @@ ngx_http_header_t ngx_http_headers_in[] = { void ngx_http_init_connection(ngx_connection_t *c) { - ngx_event_t *rev; - ngx_http_log_ctx_t *ctx; - - ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t)); - if (ctx == NULL) { - ngx_http_close_connection(c); - return; - } - - ctx->connection = c; - ctx->request = NULL; - ctx->current_request = NULL; - - c->log->connection = c->number; - c->log->handler = ngx_http_log_error; - c->log->data = ctx; - c->log->action = "reading client request line"; - - c->log_error = NGX_ERROR_INFO; - - rev = c->read; - rev->handler = ngx_http_init_request; - c->write->handler = ngx_http_empty_handler; - -#if (NGX_STAT_STUB) - (void) ngx_atomic_fetch_add(ngx_stat_reading, 1); -#endif - - if (rev->ready) { - /* the deferred accept(), rtsig, aio, iocp */ - - if (ngx_use_accept_mutex) { - ngx_post_event(rev, &ngx_posted_events); - return; - } - - ngx_http_init_request(rev); - return; - } - - ngx_add_timer(rev, c->listening->post_accept_timeout); - - if (ngx_handle_read_event(rev, 0) != NGX_OK) { -#if (NGX_STAT_STUB) - (void) ngx_atomic_fetch_add(ngx_stat_reading, -1); -#endif - ngx_http_close_connection(c); - return; - } -} - - -static void -ngx_http_init_request(ngx_event_t *rev) -{ - ngx_time_t *tp; - ngx_uint_t i; - ngx_connection_t *c; - ngx_http_request_t *r; - struct sockaddr_in *sin; - ngx_http_port_t *port; - ngx_http_in_addr_t *addr; - ngx_http_log_ctx_t *ctx; - ngx_http_addr_conf_t *addr_conf; - ngx_http_connection_t *hc; - ngx_http_core_srv_conf_t *cscf; - ngx_http_core_loc_conf_t *clcf; - ngx_http_core_main_conf_t *cmcf; + ngx_uint_t i; + ngx_event_t *rev; + struct sockaddr_in *sin; + ngx_http_port_t *port; + ngx_http_in_addr_t *addr; + ngx_http_log_ctx_t *ctx; + ngx_http_connection_t *hc; #if (NGX_HAVE_INET6) - struct sockaddr_in6 *sin6; - ngx_http_in6_addr_t *addr6; + struct sockaddr_in6 *sin6; + ngx_http_in6_addr_t *addr6; #endif -#if (NGX_STAT_STUB) - (void) ngx_atomic_fetch_add(ngx_stat_reading, -1); -#endif - - c = rev->data; - - if (rev->timedout) { - ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); - + hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t)); + if (hc == NULL) { ngx_http_close_connection(c); return; } - c->requests++; - - hc = c->data; - - if (hc == NULL) { - hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t)); - if (hc == NULL) { - ngx_http_close_connection(c); - return; - } - } - - r = hc->request; - - if (r) { - ngx_memzero(r, sizeof(ngx_http_request_t)); - - r->pipeline = hc->pipeline; - - if (hc->nbusy) { - r->header_in = hc->busy[0]; - } - - } else { - r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t)); - if (r == NULL) { - ngx_http_close_connection(c); - return; - } - - hc->request = r; - } - - c->data = r; - r->http_connection = hc; - - c->sent = 0; - r->signature = NGX_HTTP_MODULE; + c->data = hc; /* find the server configuration for the address:port */ port = c->listening->servers; - r->connection = c; - if (port->naddrs > 1) { /* @@ -354,7 +251,7 @@ ngx_http_init_request(ngx_event_t *rev) } } - addr_conf = &addr6[i].conf; + hc->addr_conf = &addr6[i].conf; break; #endif @@ -372,7 +269,7 @@ ngx_http_init_request(ngx_event_t *rev) } } - addr_conf = &addr[i].conf; + hc->addr_conf = &addr[i].conf; break; } @@ -384,90 +281,161 @@ ngx_http_init_request(ngx_event_t *rev) #if (NGX_HAVE_INET6) case AF_INET6: addr6 = port->addrs; - addr_conf = &addr6[0].conf; + hc->addr_conf = &addr6[0].conf; break; #endif default: /* AF_INET */ addr = port->addrs; - addr_conf = &addr[0].conf; + hc->addr_conf = &addr[0].conf; break; } } - r->virtual_names = addr_conf->virtual_names; - /* the default server configuration for the address:port */ - cscf = addr_conf->default_server; + hc->conf_ctx = hc->addr_conf->default_server->ctx; - r->main_conf = cscf->ctx->main_conf; - r->srv_conf = cscf->ctx->srv_conf; - r->loc_conf = cscf->ctx->loc_conf; + ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t)); + if (ctx == NULL) { + ngx_http_close_connection(c); + return; + } - rev->handler = ngx_http_process_request_line; - r->read_event_handler = ngx_http_block_reading; + ctx->connection = c; + ctx->request = NULL; + ctx->current_request = NULL; -#if (NGX_HTTP_SSL) + c->log->connection = c->number; + c->log->handler = ngx_http_log_error; + c->log->data = ctx; + c->log->action = "reading client request line"; + c->log_error = NGX_ERROR_INFO; + + rev = c->read; + rev->handler = ngx_http_init_request; + c->write->handler = ngx_http_empty_handler; + +#if (NGX_HTTP_SSL) { ngx_http_ssl_srv_conf_t *sscf; - sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module); - if (sscf->enable || addr_conf->ssl) { + sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module); - if (c->ssl == NULL) { + if (sscf->enable || hc->addr_conf->ssl) { - c->log->action = "SSL handshaking"; + c->log->action = "SSL handshaking"; - if (addr_conf->ssl && sscf->ssl.ctx == NULL) { - ngx_log_error(NGX_LOG_ERR, c->log, 0, - "no \"ssl_certificate\" is defined " - "in server listening on SSL port"); - ngx_http_close_connection(c); - return; - } + if (hc->addr_conf->ssl && sscf->ssl.ctx == NULL) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "no \"ssl_certificate\" is defined " + "in server listening on SSL port"); + ngx_http_close_connection(c); + return; + } - if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER) - != NGX_OK) - { - ngx_http_close_connection(c); - return; - } + hc->ssl = 1; + + rev->handler = ngx_http_ssl_handshake; + } + } +#endif - rev->handler = ngx_http_ssl_handshake; + if (rev->ready) { + /* the deferred accept(), rtsig, aio, iocp */ + + if (ngx_use_accept_mutex) { + ngx_post_event(rev, &ngx_posted_events); + return; } - r->main_filter_need_in_memory = 1; + rev->handler(rev); + return; } + + ngx_add_timer(rev, c->listening->post_accept_timeout); + + if (ngx_handle_read_event(rev, 0) != NGX_OK) { + ngx_http_close_connection(c); + return; } +} -#endif - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - c->log->file = clcf->error_log->file; - if (!(c->log->log_level & NGX_LOG_DEBUG_CONNECTION)) { - c->log->log_level = clcf->error_log->log_level; +static void +ngx_http_init_request(ngx_event_t *rev) +{ + ngx_pool_t *pool; + ngx_time_t *tp; + ngx_connection_t *c; + ngx_http_request_t *r; + ngx_http_log_ctx_t *ctx; + ngx_http_connection_t *hc; + ngx_http_core_srv_conf_t *cscf; + ngx_http_core_loc_conf_t *clcf; + ngx_http_core_main_conf_t *cmcf; + + c = rev->data; + + if (rev->timedout) { + ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); + + ngx_http_close_connection(c); + return; + } + + c->requests++; + + hc = c->data; + + cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_core_module); + + pool = ngx_create_pool(cscf->request_pool_size, c->log); + if (pool == NULL) { + ngx_http_close_connection(c); + return; + } + + r = ngx_pcalloc(pool, sizeof(ngx_http_request_t)); + if (r == NULL) { + ngx_destroy_pool(pool); + ngx_http_close_connection(c); + return; } + r->pool = pool; + + r->pipeline = hc->pipeline; + + c->data = r; + r->http_connection = hc; + + c->sent = 0; + r->signature = NGX_HTTP_MODULE; + + r->connection = c; + + r->main_conf = hc->conf_ctx->main_conf; + r->srv_conf = hc->conf_ctx->srv_conf; + r->loc_conf = hc->conf_ctx->loc_conf; + + r->read_event_handler = ngx_http_block_reading; + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + ngx_http_set_connection_log(r->connection, clcf->error_log); + if (c->buffer == NULL) { c->buffer = ngx_create_temp_buf(c->pool, cscf->client_header_buffer_size); if (c->buffer == NULL) { + ngx_destroy_pool(r->pool); ngx_http_close_connection(c); return; } } - if (r->header_in == NULL) { - r->header_in = c->buffer; - } - - r->pool = ngx_create_pool(cscf->request_pool_size, c->log); - if (r->pool == NULL) { - ngx_http_close_connection(c); - return; - } - + r->header_in = hc->nbusy ? hc->busy[0] : c->buffer; if (ngx_list_init(&r->headers_out.headers, r->pool, 20, sizeof(ngx_table_elt_t)) @@ -498,6 +466,12 @@ ngx_http_init_request(ngx_event_t *rev) c->single_connection = 1; c->destroyed = 0; +#if (NGX_HTTP_SSL) + if (c->ssl) { + r->main_filter_need_in_memory = 1; + } +#endif + r->main = r; r->count = 1; @@ -528,7 +502,8 @@ ngx_http_init_request(ngx_event_t *rev) (void) ngx_atomic_fetch_add(ngx_stat_requests, 1); #endif - rev->handler(rev); + rev->handler = ngx_http_process_request_line; + ngx_http_process_request_line(rev); } @@ -537,37 +512,48 @@ ngx_http_init_request(ngx_event_t *rev) static void ngx_http_ssl_handshake(ngx_event_t *rev) { - u_char buf[1]; - ssize_t n; - ngx_int_t rc; - ngx_connection_t *c; - ngx_http_request_t *r; + u_char buf[1]; + ssize_t n; + ngx_err_t err; + ngx_int_t rc; + ngx_connection_t *c; + ngx_http_connection_t *hc; + ngx_http_ssl_srv_conf_t *sscf; c = rev->data; - r = c->data; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http check ssl handshake"); if (rev->timedout) { ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); - c->timedout = 1; - ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT); + ngx_http_close_connection(c); return; } n = recv(c->fd, (char *) buf, 1, MSG_PEEK); - if (n == -1 && ngx_socket_errno == NGX_EAGAIN) { + err = ngx_socket_errno; - if (!rev->timer_set) { - ngx_add_timer(rev, c->listening->post_accept_timeout); - } + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http recv(): %d", n); - if (ngx_handle_read_event(rev, 0) != NGX_OK) { - ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + if (n == -1) { + if (err == NGX_EAGAIN) { + + if (!rev->timer_set) { + ngx_add_timer(rev, c->listening->post_accept_timeout); + } + + if (ngx_handle_read_event(rev, 0) != NGX_OK) { + ngx_http_close_connection(c); + } + + return; } + ngx_connection_error(c, err, "recv() failed"); + ngx_http_close_connection(c); + return; } @@ -576,6 +562,17 @@ ngx_http_ssl_handshake(ngx_event_t *rev) ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0, "https ssl handshake: 0x%02Xd", buf[0]); + hc = c->data; + sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, + ngx_http_ssl_module); + + if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER) + != NGX_OK) + { + ngx_http_close_connection(c); + return; + } + rc = ngx_ssl_handshake(c); if (rc == NGX_AGAIN) { @@ -591,27 +588,26 @@ ngx_http_ssl_handshake(ngx_event_t *rev) ngx_http_ssl_handshake_handler(c); return; + } - } else { - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, - "plain http"); + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "plain http"); - r->plain_http = 1; - } - } + c->log->action = "reading client request line"; - c->log->action = "reading client request line"; + rev->handler = ngx_http_init_request; + ngx_http_init_request(rev); - rev->handler = ngx_http_process_request_line; - ngx_http_process_request_line(rev); + return; + } + + ngx_log_error(NGX_LOG_INFO, c->log, 0, "client closed connection"); + ngx_http_close_connection(c); } static void ngx_http_ssl_handshake_handler(ngx_connection_t *c) { - ngx_http_request_t *r; - if (c->ssl->handshaked) { /* @@ -626,19 +622,19 @@ ngx_http_ssl_handshake_handler(ngx_connection_t *c) c->log->action = "reading client request line"; - c->read->handler = ngx_http_process_request_line; + c->read->handler = ngx_http_init_request; /* STUB: epoll edge */ c->write->handler = ngx_http_empty_handler; - ngx_http_process_request_line(c->read); + ngx_http_init_request(c->read); return; } - r = c->data; - - ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST); + if (c->read->timedout) { + ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); + } - return; + ngx_http_close_connection(c); } #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME @@ -646,12 +642,13 @@ ngx_http_ssl_handshake_handler(ngx_connection_t *c) int ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) { - size_t len; - u_char *host; - const char *servername; - ngx_connection_t *c; - ngx_http_request_t *r; - ngx_http_ssl_srv_conf_t *sscf; + ngx_str_t host; + const char *servername; + ngx_connection_t *c; + ngx_http_connection_t *hc; + ngx_http_ssl_srv_conf_t *sscf; + ngx_http_core_loc_conf_t *clcf; + ngx_http_core_srv_conf_t *cscf; servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name); @@ -664,27 +661,41 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "SSL server name: \"%s\"", servername); - len = ngx_strlen(servername); + host.len = ngx_strlen(servername); - if (len == 0) { + if (host.len == 0) { return SSL_TLSEXT_ERR_NOACK; } - r = c->data; + host.data = (u_char *) servername; - host = (u_char *) servername; + if (ngx_http_validate_host(&host, c->pool, 1) != NGX_OK) { + return SSL_TLSEXT_ERR_NOACK; + } - len = ngx_http_validate_host(r, &host, len, 1); + hc = c->data; - if (len <= 0) { + if (ngx_http_find_virtual_server(c, hc->addr_conf->virtual_names, &host, + NULL, &cscf) + != NGX_OK) + { return SSL_TLSEXT_ERR_NOACK; } - if (ngx_http_find_virtual_server(r, host, len) != NGX_OK) { + hc->ssl_servername = ngx_palloc(c->pool, sizeof(ngx_str_t)); + if (hc->ssl_servername == NULL) { return SSL_TLSEXT_ERR_NOACK; } - sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module); + *hc->ssl_servername = host; + + hc->conf_ctx = cscf->ctx; + + clcf = ngx_http_get_module_loc_conf(hc->conf_ctx, ngx_http_core_module); + + ngx_http_set_connection_log(c, clcf->error_log); + + sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module); if (sscf->ssl.ctx) { SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx); @@ -719,9 +730,9 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) static void ngx_http_process_request_line(ngx_event_t *rev) { - u_char *host; ssize_t n; ngx_int_t rc, rv; + ngx_str_t host; ngx_connection_t *c; ngx_http_request_t *r; ngx_http_core_srv_conf_t *cscf; @@ -887,33 +898,36 @@ ngx_http_process_request_line(ngx_event_t *rev) if (r->host_start && r->host_end) { - host = r->host_start; - n = ngx_http_validate_host(r, &host, - r->host_end - r->host_start, 0); + host.len = r->host_end - r->host_start; + host.data = r->host_start; + + rc = ngx_http_validate_host(&host, r->pool, 0); - if (n == 0) { + if (rc == NGX_DECLINED) { ngx_log_error(NGX_LOG_INFO, c->log, 0, "client sent invalid host in request line"); ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); return; } - if (n < 0) { + if (rc == NGX_ERROR) { ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } - r->headers_in.server.len = n; - r->headers_in.server.data = host; + if (ngx_http_set_virtual_server(r, &host) == NGX_ERROR) { + return; + } + + r->headers_in.server = host; } if (r->http_version < NGX_HTTP_VERSION_10) { - if (ngx_http_find_virtual_server(r, r->headers_in.server.data, - r->headers_in.server.len) - == NGX_ERROR) + if (r->headers_in.server.len == 0 + && ngx_http_set_virtual_server(r, &r->headers_in.server) + == NGX_ERROR) { - ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } @@ -930,15 +944,6 @@ ngx_http_process_request_line(ngx_event_t *rev) return; } - - if (ngx_array_init(&r->headers_in.cookies, r->pool, 2, - sizeof(ngx_table_elt_t *)) - != NGX_OK) - { - ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - return; - } - c->log->action = "reading client request headers"; rev->handler = ngx_http_process_request_headers; @@ -1010,7 +1015,6 @@ ngx_http_process_request_headers(ngx_event_t *rev) } cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); - cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); rc = NGX_AGAIN; @@ -1064,6 +1068,9 @@ ngx_http_process_request_headers(ngx_event_t *rev) } } + /* the host header could change the server configuration context */ + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); + rc = ngx_http_parse_header_line(r, r->header_in, cscf->underscores_in_headers); @@ -1413,24 +1420,25 @@ static ngx_int_t ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset) { - u_char *host; - ssize_t len; + ngx_int_t rc; + ngx_str_t host; if (r->headers_in.host == NULL) { r->headers_in.host = h; } - host = h->value.data; - len = ngx_http_validate_host(r, &host, h->value.len, 0); + host = h->value; + + rc = ngx_http_validate_host(&host, r->pool, 0); - if (len == 0) { + if (rc == NGX_DECLINED) { ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "client sent invalid host header"); ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); return NGX_ERROR; } - if (len < 0) { + if (rc == NGX_ERROR) { ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_ERROR; } @@ -1439,8 +1447,11 @@ ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h, return NGX_OK; } - r->headers_in.server.len = len; - r->headers_in.server.data = host; + if (ngx_http_set_virtual_server(r, &host) == NGX_ERROR) { + return NGX_ERROR; + } + + r->headers_in.server = host; return NGX_OK; } @@ -1535,31 +1546,41 @@ ngx_http_process_user_agent(ngx_http_request_t *r, ngx_table_elt_t *h, static ngx_int_t -ngx_http_process_cookie(ngx_http_request_t *r, ngx_table_elt_t *h, +ngx_http_process_multi_header_lines(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset) { - ngx_table_elt_t **cookie; + ngx_array_t *headers; + ngx_table_elt_t **ph; - cookie = ngx_array_push(&r->headers_in.cookies); - if (cookie) { - *cookie = h; - return NGX_OK; + headers = (ngx_array_t *) ((char *) &r->headers_in + offset); + + if (headers->elts == NULL) { + if (ngx_array_init(headers, r->pool, 1, sizeof(ngx_table_elt_t *)) + != NGX_OK) + { + ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return NGX_ERROR; + } } - ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + ph = ngx_array_push(headers); + if (ph == NULL) { + ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return NGX_ERROR; + } - return NGX_ERROR; + *ph = h; + return NGX_OK; } static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r) { - if (ngx_http_find_virtual_server(r, r->headers_in.server.data, - r->headers_in.server.len) - == NGX_ERROR) + if (r->headers_in.server.len == 0 + && ngx_http_set_virtual_server(r, &r->headers_in.server) + == NGX_ERROR) { - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_ERROR; } @@ -1630,20 +1651,20 @@ ngx_http_process_request(ngx_http_request_t *r) c = r->connection; - if (r->plain_http) { - ngx_log_error(NGX_LOG_INFO, c->log, 0, - "client sent plain HTTP request to HTTPS port"); - ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS); - return; - } - #if (NGX_HTTP_SSL) - if (c->ssl) { + if (r->http_connection->ssl) { long rc; X509 *cert; ngx_http_ssl_srv_conf_t *sscf; + if (c->ssl == NULL) { + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client sent plain HTTP request to HTTPS port"); + ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS); + return; + } + sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module); if (sscf->verify) { @@ -1705,9 +1726,8 @@ ngx_http_process_request(ngx_http_request_t *r) } -static ssize_t -ngx_http_validate_host(ngx_http_request_t *r, u_char **host, size_t len, - ngx_uint_t alloc) +static ngx_int_t +ngx_http_validate_host(ngx_str_t *host, ngx_pool_t *pool, ngx_uint_t alloc) { u_char *h, ch; size_t i, dot_pos, host_len; @@ -1718,21 +1738,21 @@ ngx_http_validate_host(ngx_http_request_t *r, u_char **host, size_t len, sw_rest } state; - dot_pos = len; - host_len = len; + dot_pos = host->len; + host_len = host->len; - h = *host; + h = host->data; state = sw_usual; - for (i = 0; i < len; i++) { + for (i = 0; i < host->len; i++) { ch = h[i]; switch (ch) { case '.': if (dot_pos == i - 1) { - return 0; + return NGX_DECLINED; } dot_pos = i; break; @@ -1758,12 +1778,12 @@ ngx_http_validate_host(ngx_http_request_t *r, u_char **host, size_t len, break; case '\0': - return 0; + return NGX_DECLINED; default: if (ngx_path_separator(ch)) { - return 0; + return NGX_DECLINED; } if (ch >= 'A' && ch <= 'Z') { @@ -1778,83 +1798,187 @@ ngx_http_validate_host(ngx_http_request_t *r, u_char **host, size_t len, host_len--; } + if (host_len == 0) { + return NGX_DECLINED; + } + if (alloc) { - *host = ngx_pnalloc(r->pool, host_len); - if (*host == NULL) { - return -1; + host->data = ngx_pnalloc(pool, host_len); + if (host->data == NULL) { + return NGX_ERROR; } - ngx_strlow(*host, h, host_len); + ngx_strlow(host->data, h, host_len); } - return host_len; + host->len = host_len; + + return NGX_OK; } static ngx_int_t -ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host, size_t len) +ngx_http_set_virtual_server(ngx_http_request_t *r, ngx_str_t *host) { + ngx_int_t rc; + ngx_http_connection_t *hc; ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; - if (r->virtual_names == NULL) { + hc = r->http_connection; + +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME + + if (hc->ssl_servername) { + if (hc->ssl_servername->len == host->len + && ngx_strncmp(hc->ssl_servername->data, + host->data, host->len) == 0) + { +#if (NGX_PCRE) + if (hc->ssl_servername_regex + && ngx_http_regex_exec(r, hc->ssl_servername_regex, + hc->ssl_servername) != NGX_OK) + { + ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return NGX_ERROR; + } +#endif + return NGX_OK; + } + } + +#endif + + rc = ngx_http_find_virtual_server(r->connection, + hc->addr_conf->virtual_names, + host, r, &cscf); + + if (rc == NGX_ERROR) { + ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return NGX_ERROR; + } + +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME + + if (hc->ssl_servername) { + ngx_http_ssl_srv_conf_t *sscf; + + if (rc == NGX_DECLINED) { + cscf = hc->addr_conf->default_server; + rc = NGX_OK; + } + + sscf = ngx_http_get_module_srv_conf(cscf->ctx, ngx_http_ssl_module); + + if (sscf->verify) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client attempted to request the server name " + "different from that one was negotiated"); + ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); + return NGX_ERROR; + } + } + +#endif + + if (rc == NGX_DECLINED) { + return NGX_OK; + } + + r->srv_conf = cscf->ctx->srv_conf; + r->loc_conf = cscf->ctx->loc_conf; + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + ngx_http_set_connection_log(r->connection, clcf->error_log); + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_find_virtual_server(ngx_connection_t *c, + ngx_http_virtual_names_t *virtual_names, ngx_str_t *host, + ngx_http_request_t *r, ngx_http_core_srv_conf_t **cscfp) +{ + ngx_http_core_srv_conf_t *cscf; + + if (virtual_names == NULL) { return NGX_DECLINED; } - cscf = ngx_hash_find_combined(&r->virtual_names->names, - ngx_hash_key(host, len), host, len); + cscf = ngx_hash_find_combined(&virtual_names->names, + ngx_hash_key(host->data, host->len), + host->data, host->len); if (cscf) { - goto found; + *cscfp = cscf; + return NGX_OK; } #if (NGX_PCRE) - if (len && r->virtual_names->nregex) { + if (host->len && virtual_names->nregex) { ngx_int_t n; ngx_uint_t i; - ngx_str_t name; ngx_http_server_name_t *sn; - name.len = len; - name.data = host; + sn = virtual_names->regex; - sn = r->virtual_names->regex; +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME - for (i = 0; i < r->virtual_names->nregex; i++) { + if (r == NULL) { + ngx_http_connection_t *hc; - n = ngx_http_regex_exec(r, sn[i].regex, &name); + for (i = 0; i < virtual_names->nregex; i++) { - if (n == NGX_OK) { - cscf = sn[i].server; - goto found; - } + n = ngx_regex_exec(sn[i].regex->regex, host, NULL, 0); - if (n == NGX_DECLINED) { - continue; + if (n == NGX_REGEX_NO_MATCHED) { + continue; + } + + if (n >= 0) { + hc = c->data; + hc->ssl_servername_regex = sn[i].regex; + + *cscfp = sn[i].server; + return NGX_OK; + } + + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + ngx_regex_exec_n " failed: %i " + "on \"%V\" using \"%V\"", + n, host, &sn[i].regex->name); + + return NGX_ERROR; } - return NGX_ERROR; + return NGX_DECLINED; } - } -#endif +#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */ - return NGX_DECLINED; + for (i = 0; i < virtual_names->nregex; i++) { -found: + n = ngx_http_regex_exec(r, sn[i].regex, host); - r->srv_conf = cscf->ctx->srv_conf; - r->loc_conf = cscf->ctx->loc_conf; + if (n == NGX_DECLINED) { + continue; + } - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - r->connection->log->file = clcf->error_log->file; + if (n == NGX_OK) { + *cscfp = sn[i].server; + return NGX_OK; + } - if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION)) { - r->connection->log->log_level = clcf->error_log->log_level; + return NGX_ERROR; + } } - return NGX_OK; +#endif /* NGX_PCRE */ + + return NGX_DECLINED; } @@ -2528,6 +2652,7 @@ ngx_http_set_keepalive(ngx_http_request_t *r) } } + /* guard against recursive call from ngx_http_finalize_connection() */ r->keepalive = 0; ngx_http_free_request(r, 0); @@ -2548,10 +2673,6 @@ ngx_http_set_keepalive(ngx_http_request_t *r) ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request"); -#if (NGX_STAT_STUB) - (void) ngx_atomic_fetch_add(ngx_stat_reading, 1); -#endif - hc->pipeline = 1; c->log->action = "reading client pipelined request line"; @@ -2563,17 +2684,12 @@ ngx_http_set_keepalive(ngx_http_request_t *r) hc->pipeline = 0; /* - * To keep a memory footprint as small as possible for an idle - * keepalive connection we try to free the ngx_http_request_t and - * c->buffer's memory if they were allocated outside the c->pool. - * The large header buffers are always allocated outside the c->pool and - * are freed too. + * To keep a memory footprint as small as possible for an idle keepalive + * connection we try to free c->buffer's memory if it was allocated outside + * the c->pool. The large header buffers are always allocated outside the + * c->pool and are freed too. */ - if (ngx_pfree(c->pool, r) == NGX_OK) { - hc->request = NULL; - } - b = c->buffer; if (ngx_pfree(c->pool, b->start) == NGX_OK) { @@ -2758,6 +2874,7 @@ ngx_http_keepalive_handler(ngx_event_t *rev) if (n == NGX_AGAIN) { if (ngx_handle_read_event(rev, 0) != NGX_OK) { ngx_http_close_connection(c); + return; } /* @@ -2793,10 +2910,6 @@ ngx_http_keepalive_handler(ngx_event_t *rev) b->last += n; -#if (NGX_STAT_STUB) - (void) ngx_atomic_fetch_add(ngx_stat_reading, 1); -#endif - c->log->handler = ngx_http_log_error; c->log->action = "reading client request line"; @@ -3027,6 +3140,7 @@ static void ngx_http_free_request(ngx_http_request_t *r, ngx_int_t rc) { ngx_log_t *log; + ngx_pool_t *pool; struct linger linger; ngx_http_cleanup_t *cln; ngx_http_log_ctx_t *ctx; @@ -3093,7 +3207,15 @@ ngx_http_free_request(ngx_http_request_t *r, ngx_int_t rc) r->connection->destroyed = 1; - ngx_destroy_pool(r->pool); + /* + * Setting r->pool to NULL will increase probability to catch double close + * of request since the request object is allocated from its own pool. + */ + + pool = r->pool; + r->pool = NULL; + + ngx_destroy_pool(pool); } |
