Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nginx/nginx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2008-05-15 18:44:47 +0400
committerIgor Sysoev <igor@sysoev.ru>2008-05-15 18:44:47 +0400
commit5fd0931a611c112265d7d11a448cf26ffb542aad (patch)
tree503d22585a5fe2a2a703deccbb19552c0eaceac5 /src
parent433608c18072cbaa99deddf4432ab2537397f025 (diff)
*) host in request line has priority
*) allow several Host headers *) validate host
Diffstat (limited to 'src')
-rw-r--r--src/http/modules/ngx_http_dav_module.c18
-rw-r--r--src/http/ngx_http_core_module.c3
-rw-r--r--src/http/ngx_http_header_filter_module.c5
-rw-r--r--src/http/ngx_http_request.c255
-rw-r--r--src/http/ngx_http_request.h2
-rw-r--r--src/http/ngx_http_variables.c25
6 files changed, 188 insertions, 120 deletions
diff --git a/src/http/modules/ngx_http_dav_module.c b/src/http/modules/ngx_http_dav_module.c
index b1e0831b1..3d54525e8 100644
--- a/src/http/modules/ngx_http_dav_module.c
+++ b/src/http/modules/ngx_http_dav_module.c
@@ -512,7 +512,7 @@ ngx_http_dav_mkcol_handler(ngx_http_request_t *r, ngx_http_dav_loc_conf_t *dlcf)
static ngx_int_t
ngx_http_dav_copy_move_handler(ngx_http_request_t *r)
{
- u_char *p, *desthost, *last, ch;
+ u_char *p, *host, *last, ch;
size_t len, root;
ngx_err_t err;
ngx_int_t rc, depth;
@@ -520,7 +520,7 @@ ngx_http_dav_copy_move_handler(ngx_http_request_t *r)
ngx_str_t path, uri;
ngx_tree_ctx_t tree;
ngx_file_info_t fi;
- ngx_table_elt_t *host, *dest, *over;
+ ngx_table_elt_t *dest, *over;
ngx_http_dav_copy_ctx_t copy;
ngx_http_dav_loc_conf_t *dlcf;
@@ -536,9 +536,9 @@ ngx_http_dav_copy_move_handler(ngx_http_request_t *r)
return NGX_HTTP_BAD_REQUEST;
}
- host = r->headers_in.host;
+ len = r->headers_in.server.len;
- if (host == NULL) {
+ if (len == 0) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"client sent no \"Host\" header");
return NGX_HTTP_BAD_REQUEST;
@@ -553,7 +553,7 @@ ngx_http_dav_copy_move_handler(ngx_http_request_t *r)
goto invalid_destination;
}
- desthost = dest->value.data + sizeof("https://") - 1;
+ host = dest->value.data + sizeof("https://") - 1;
} else
#endif
@@ -564,12 +564,10 @@ ngx_http_dav_copy_move_handler(ngx_http_request_t *r)
goto invalid_destination;
}
- desthost = dest->value.data + sizeof("http://") - 1;
+ host = dest->value.data + sizeof("http://") - 1;
}
- len = r->headers_in.host_name_len;
-
- if (ngx_strncmp(desthost, host->value.data, len) != 0) {
+ if (ngx_strncmp(host, r->headers_in.server.data, len) != 0) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"\"Destination\" URI \"%V\" is handled by "
"different repository than the source URI",
@@ -579,7 +577,7 @@ ngx_http_dav_copy_move_handler(ngx_http_request_t *r)
last = dest->value.data + dest->value.len;
- for (p = desthost + len; p < last; p++) {
+ for (p = host + len; p < last; p++) {
if (*p == '/') {
goto destination_done;
}
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index cb9eb14c7..a80947058 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -3216,8 +3216,7 @@ ngx_http_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
value[i].len--;
value[i].data++;
- sn->regex = ngx_regex_compile(&value[i], NGX_REGEX_CASELESS, cf->pool,
- &err);
+ sn->regex = ngx_regex_compile(&value[i], 0, cf->pool, &err);
if (sn->regex == NULL) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
diff --git a/src/http/ngx_http_header_filter_module.c b/src/http/ngx_http_header_filter_module.c
index 9cdac6126..2dd5b952b 100644
--- a/src/http/ngx_http_header_filter_module.c
+++ b/src/http/ngx_http_header_filter_module.c
@@ -286,9 +286,8 @@ ngx_http_header_filter(ngx_http_request_t *r)
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
host = cscf->server_name;
- } else if (r->headers_in.host) {
- host.len = r->headers_in.host_name_len;
- host.data = r->headers_in.host->value.data;
+ } else if (r->headers_in.server.len) {
+ host = r->headers_in.server;
} else {
host.data = addr;
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index e124e5f99..0535fc0ef 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -21,6 +21,8 @@ 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_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,
@@ -30,8 +32,9 @@ static ngx_int_t ngx_http_process_cookie(ngx_http_request_t *r,
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 void ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host,
- size_t len, ngx_uint_t hash);
+static ssize_t ngx_http_validate_host(u_char *host, size_t len);
+static ngx_int_t ngx_http_find_virtual_server(ngx_http_request_t *r,
+ u_char *host, size_t len);
static void ngx_http_request_handler(ngx_event_t *ev);
static ngx_int_t ngx_http_set_write_handler(ngx_http_request_t *r);
@@ -71,8 +74,7 @@ static char *ngx_http_client_errors[] = {
ngx_http_header_t ngx_http_headers_in[] = {
- { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host),
- ngx_http_process_unique_header_line },
+ { ngx_string("Host"), 0, ngx_http_process_host },
{ ngx_string("Connection"), 0, ngx_http_process_connection },
@@ -562,8 +564,6 @@ ngx_http_ssl_handshake_handler(ngx_connection_t *c)
int
ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
{
- u_char *p;
- ngx_uint_t hash;
const char *servername;
ngx_connection_t *c;
ngx_http_request_t *r;
@@ -582,21 +582,13 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
r = c->data;
- if (r->virtual_names == NULL) {
+ if (ngx_http_find_virtual_server(r, (u_char *) servername,
+ ngx_strlen(servername))
+ != NGX_OK)
+ {
return SSL_TLSEXT_ERR_NOACK;
}
- /* it seems browsers send low case server name */
-
- hash = 0;
-
- for (p = (u_char *) servername; *p; p++) {
- hash = ngx_hash(hash, *p);
- }
-
- ngx_http_find_virtual_server(r, (u_char *) servername,
- p - (u_char *) servername, hash);
-
sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx);
@@ -726,7 +718,31 @@ ngx_http_process_request_line(ngx_event_t *rev)
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
"http exten: \"%V\"", &r->exten);
+ if (r->host_start && r->host_end) {
+ n = ngx_http_validate_host(r->host_start,
+ r->host_end - r->host_start);
+
+ if (n <= 0) {
+ 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;
+ }
+
+ r->headers_in.server.len = n;
+ r->headers_in.server.data = r->host_start;
+ }
+
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)
+ {
+ ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return;
+ }
+
ngx_http_process_request(r);
return;
}
@@ -1217,35 +1233,47 @@ ngx_http_process_unique_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
static ngx_int_t
-ngx_http_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h,
+ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h,
ngx_uint_t offset)
{
- if (ngx_strcasestrn(h->value.data, "close", 5 - 1)) {
- r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
+ ssize_t len;
- } else if (ngx_strcasestrn(h->value.data, "keep-alive", 10 - 1)) {
- r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE;
+ if (r->headers_in.host == NULL) {
+ r->headers_in.host = h;
+ }
+
+ len = ngx_http_validate_host(h->value.data, h->value.len);
+
+ if (len <= 0) {
+ 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 (r->headers_in.server.len) {
+ return NGX_OK;
}
+ r->headers_in.server.len = len;
+ r->headers_in.server.data = h->value.data;
+
return NGX_OK;
}
static ngx_int_t
-ngx_http_process_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
+ngx_http_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h,
ngx_uint_t offset)
{
- ngx_table_elt_t **cookie;
+ if (ngx_strcasestrn(h->value.data, "close", 5 - 1)) {
+ r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
- cookie = ngx_array_push(&r->headers_in.cookies);
- if (cookie) {
- *cookie = h;
- return NGX_OK;
+ } else if (ngx_strcasestrn(h->value.data, "keep-alive", 10 - 1)) {
+ r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE;
}
- ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
-
- return NGX_ERROR;
+ return NGX_OK;
}
@@ -1304,59 +1332,39 @@ ngx_http_process_user_agent(ngx_http_request_t *r, ngx_table_elt_t *h,
static ngx_int_t
-ngx_http_process_request_header(ngx_http_request_t *r)
+ngx_http_process_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
+ ngx_uint_t offset)
{
- size_t len;
- u_char *host, ch;
- ngx_uint_t hash;
-
- if (r->headers_in.host) {
-
- hash = 0;
-
- for (len = 0; len < r->headers_in.host->value.len; len++) {
- ch = r->headers_in.host->value.data[len];
-
- if (ch == ':') {
- break;
- }
-
- ch = ngx_tolower(ch);
- r->headers_in.host->value.data[len] = ch;
- hash = ngx_hash(hash, ch);
- }
-
- if (len && r->headers_in.host->value.data[len - 1] == '.') {
- len--;
- hash = ngx_hash_key(r->headers_in.host->value.data, len);
- }
-
- r->headers_in.host_name_len = len;
-
- if (r->virtual_names) {
+ ngx_table_elt_t **cookie;
- host = r->host_start;
+ cookie = ngx_array_push(&r->headers_in.cookies);
+ if (cookie) {
+ *cookie = h;
+ return NGX_OK;
+ }
- if (host == NULL) {
- host = r->headers_in.host->value.data;
- len = r->headers_in.host_name_len;
+ ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
- } else {
- len = r->host_end - host;
- }
+ return NGX_ERROR;
+}
- ngx_http_find_virtual_server(r, host, len, hash);
- }
- } else {
- if (r->http_version > NGX_HTTP_VERSION_10) {
- ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
- "client sent HTTP/1.1 request without \"Host\" header");
- ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
- return NGX_ERROR;
- }
+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)
+ {
+ ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return NGX_ERROR;
+ }
- r->headers_in.host_name_len = 0;
+ if (r->headers_in.host == NULL && r->http_version > NGX_HTTP_VERSION_10) {
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
+ "client sent HTTP/1.1 request without \"Host\" header");
+ ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
+ return NGX_ERROR;
}
if (r->headers_in.content_length) {
@@ -1489,14 +1497,89 @@ ngx_http_process_request(ngx_http_request_t *r)
}
-static void
-ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host, size_t len,
- ngx_uint_t hash)
+static ssize_t
+ngx_http_validate_host(u_char *host, size_t len)
+{
+ u_char ch;
+ size_t i, last;
+ ngx_uint_t dot;
+
+ last = len;
+ dot = 0;
+
+ for (i = 0; i < len; i++) {
+ ch = host[i];
+
+ if (ch == '.') {
+ if (dot) {
+ return -1;
+ }
+
+ dot = 1;
+ continue;
+ }
+
+ dot = 0;
+
+ if (ch == ':') {
+ last = i;
+ continue;
+ }
+
+ if (ch == '/' || ch == '\0') {
+ return -1;
+ }
+
+#if (NGX_WIN32)
+ if (ch == '\\') {
+ return -1;
+ }
+#endif
+ }
+
+ if (dot) {
+ last--;
+ }
+
+ return last;
+}
+
+
+static ngx_int_t
+ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host, size_t len)
{
+ u_char *server, ch;
+ ngx_uint_t i, hash;
ngx_http_core_loc_conf_t *clcf;
ngx_http_core_srv_conf_t *cscf;
+ u_char buf[32];
+
+ if (len == 0 || r->virtual_names == NULL) {
+ return NGX_DECLINED;
+ }
- cscf = ngx_hash_find_combined(&r->virtual_names->names, hash, host, len);
+ if (len <= 32) {
+ server = buf;
+
+ } else {
+ server = ngx_palloc(r->pool, len);
+ if (server == NULL) {
+ return NGX_ERROR;
+ }
+ }
+
+ hash = 0;
+
+ for (i = 0; i < len; i++) {
+ ch = host[i];
+
+ ch = ngx_tolower(ch);
+ server[i] = ch;
+
+ hash = ngx_hash(hash, ch);
+ }
+
+ cscf = ngx_hash_find_combined(&r->virtual_names->names, hash, server, len);
if (cscf) {
goto found;
@@ -1511,7 +1594,7 @@ ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host, size_t len,
ngx_http_server_name_t *sn;
name.len = len;
- name.data = host;
+ name.data = server;
sn = r->virtual_names->regex;
@@ -1528,7 +1611,7 @@ ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host, size_t len,
ngx_regex_exec_n
" failed: %d on \"%V\" using \"%V\"",
n, &name, &sn[i].name);
- return;
+ return NGX_ERROR;
}
/* match */
@@ -1541,7 +1624,7 @@ ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host, size_t len,
#endif
- return;
+ return NGX_OK;
found:
@@ -1555,7 +1638,7 @@ found:
r->connection->log->log_level = clcf->err_log->log_level;
}
- return;
+ return NGX_OK;
}
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index 9073be928..2e7ff54b6 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -206,7 +206,7 @@ typedef struct {
ngx_array_t cookies;
- size_t host_name_len;
+ ngx_str_t server;
off_t content_length_n;
time_t keep_alive_n;
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index df00675eb..c2a27a76a 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -712,26 +712,15 @@ ngx_http_variable_host(ngx_http_request_t *r, ngx_http_variable_value_t *v,
{
ngx_http_core_srv_conf_t *cscf;
- if (r->host_start == NULL) {
-
- if (r->headers_in.host) {
- v->len = r->headers_in.host_name_len;
- v->data = r->headers_in.host->value.data;
-
- } else {
- cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
-
- v->len = cscf->server_name.len;
- v->data = cscf->server_name.data;
- }
-
- } else if (r->host_end) {
- v->len = r->host_end - r->host_start;
- v->data = r->host_start;
+ if (r->headers_in.server.len) {
+ v->len = r->headers_in.server.len;
+ v->data = r->headers_in.server.data;
} else {
- v->not_found = 1;
- return NGX_OK;
+ cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
+
+ v->len = cscf->server_name.len;
+ v->data = cscf->server_name.data;
}
v->valid = 1;