r2008 merge:
*) host in request line has priority *) allow several Host headers *) validate host
This commit is contained in:
parent
f8f26bfe3f
commit
0c7bd716fe
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
@ -1216,6 +1232,36 @@ ngx_http_process_unique_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
|
|||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h,
|
||||
ngx_uint_t offset)
|
||||
{
|
||||
ssize_t len;
|
||||
|
||||
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_connection(ngx_http_request_t *r, ngx_table_elt_t *h,
|
||||
ngx_uint_t offset)
|
||||
|
@ -1231,24 +1277,6 @@ ngx_http_process_connection(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_uint_t offset)
|
||||
{
|
||||
ngx_table_elt_t **cookie;
|
||||
|
||||
cookie = ngx_array_push(&r->headers_in.cookies);
|
||||
if (cookie) {
|
||||
*cookie = h;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_process_user_agent(ngx_http_request_t *r, ngx_table_elt_t *h,
|
||||
ngx_uint_t offset)
|
||||
|
@ -1303,60 +1331,40 @@ 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_uint_t offset)
|
||||
{
|
||||
ngx_table_elt_t **cookie;
|
||||
|
||||
cookie = ngx_array_push(&r->headers_in.cookies);
|
||||
if (cookie) {
|
||||
*cookie = h;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_process_request_header(ngx_http_request_t *r)
|
||||
{
|
||||
size_t len;
|
||||
u_char *host, ch;
|
||||
ngx_uint_t hash;
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
host = r->host_start;
|
||||
|
||||
if (host == NULL) {
|
||||
host = r->headers_in.host->value.data;
|
||||
len = r->headers_in.host_name_len;
|
||||
|
||||
} else {
|
||||
len = r->host_end - host;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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];
|
||||
|
||||
cscf = ngx_hash_find_combined(&r->virtual_names->names, hash, host, len);
|
||||
if (len == 0 || r->virtual_names == NULL) {
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue