diff options
author | Igor Sysoev <igor@sysoev.ru> | 2007-11-07 16:46:29 +0300 |
---|---|---|
committer | Igor Sysoev <igor@sysoev.ru> | 2007-11-07 16:46:29 +0300 |
commit | ce87ce477e9c349fbff1d30e3a45a8f0cc928ef6 (patch) | |
tree | 5e275a216ad3398bd155782f3fa73673cd47d3e4 | |
parent | c2378f80289ead8157c63ac6216836bab6e4294b (diff) |
r1386, r1388, r1389, r1580, r1581 merge:
regex in server_name and valid_referers
-rw-r--r-- | src/http/modules/ngx_http_referer_module.c | 161 | ||||
-rw-r--r-- | src/http/ngx_http.c | 57 | ||||
-rw-r--r-- | src/http/ngx_http_core_module.c | 51 | ||||
-rw-r--r-- | src/http/ngx_http_core_module.h | 16 | ||||
-rw-r--r-- | src/http/ngx_http_request.c | 46 | ||||
-rw-r--r-- | src/http/ngx_http_request.h | 10 |
6 files changed, 315 insertions, 26 deletions
diff --git a/src/http/modules/ngx_http_referer_module.c b/src/http/modules/ngx_http_referer_module.c index 8559521e2..bf87a1bfc 100644 --- a/src/http/modules/ngx_http_referer_module.c +++ b/src/http/modules/ngx_http_referer_module.c @@ -11,9 +11,27 @@ #define NGX_HTTP_REFERER_NO_URI_PART ((void *) 4) +#if (NGX_PCRE) + +typedef struct { + ngx_regex_t *regex; + ngx_str_t name; +} ngx_http_referer_regex_t; + +#else + +#define ngx_regex_t void + +#endif + + typedef struct { ngx_hash_combined_t hash; +#if (NGX_PCRE) + ngx_array_t *regex; +#endif + ngx_flag_t no_referer; ngx_flag_t blocked_referer; @@ -28,6 +46,8 @@ static char *ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_http_add_referer(ngx_conf_t *cf, ngx_hash_keys_arrays_t *keys, ngx_str_t *value, ngx_str_t *uri); +static char *ngx_http_add_regex_referer(ngx_conf_t *cf, + ngx_http_referer_conf_t *rlcf, ngx_str_t *name, ngx_regex_t *regex); static int ngx_libc_cdecl ngx_http_cmp_referer_wildcards(const void *one, const void *two); @@ -80,18 +100,27 @@ static ngx_int_t ngx_http_referer_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { - u_char *p, *ref, *last; - size_t len; - ngx_str_t *uri; - ngx_uint_t i, key; - ngx_http_referer_conf_t *rlcf; - u_char buf[256]; + u_char *p, *ref, *last; + size_t len; + ngx_str_t *uri; + ngx_uint_t i, key; + ngx_http_referer_conf_t *rlcf; + u_char buf[256]; +#if (NGX_PCRE) + ngx_int_t n; + ngx_str_t referer; + ngx_http_referer_regex_t *regex; +#endif rlcf = ngx_http_get_module_loc_conf(r, ngx_http_referer_module); if (rlcf->hash.hash.buckets == NULL && rlcf->hash.wc_head == NULL - && rlcf->hash.wc_tail == NULL) + && rlcf->hash.wc_tail == NULL +#if (NGX_PCRE) + && rlcf->regex == NULL +#endif + ) { goto valid; } @@ -135,14 +164,44 @@ ngx_http_referer_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, } } - len = p - ref; - - uri = ngx_hash_find_combined(&rlcf->hash, key, buf, len); + uri = ngx_hash_find_combined(&rlcf->hash, key, buf, p - ref); if (uri) { goto uri; } +#if (NGX_PCRE) + + if (rlcf->regex) { + + referer.len = len - 7; + referer.data = ref; + + regex = rlcf->regex->elts; + + for (i = 0; i < rlcf->regex->nelts; i++) { + n = ngx_regex_exec(regex[i].regex, &referer, NULL, 0); + + if (n == NGX_REGEX_NO_MATCHED) { + continue; + } + + if (n < 0) { + ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, + ngx_regex_exec_n + " failed: %d on \"%V\" using \"%V\"", + n, &referer, ®ex[i].name); + return NGX_ERROR; + } + + /* match */ + + goto valid; + } + } + +#endif + invalid: *v = ngx_http_variable_true_value; @@ -357,6 +416,21 @@ ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) sn = cscf->server_names.elts; for (n = 0; n < cscf->server_names.nelts; n++) { + +#if (NGX_PCRE) + if (sn[n].regex) { + + if (ngx_http_add_regex_referer(cf, rlcf, &sn[n].name, + sn[n].regex) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + + continue; + } +#endif + if (ngx_http_add_referer(cf, rlcf->keys, &sn[n].name, &uri) != NGX_OK) { @@ -367,6 +441,15 @@ ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) continue; } + if (value[i].data[0] == '~') { + if (ngx_http_add_regex_referer(cf, rlcf, &value[i], NULL) != NGX_OK) + { + return NGX_CONF_ERROR; + } + + continue; + } + p = (u_char *) ngx_strchr(value[i].data, '/'); if (p) { @@ -423,6 +506,64 @@ ngx_http_add_referer(ngx_conf_t *cf, ngx_hash_keys_arrays_t *keys, } +static char * +ngx_http_add_regex_referer(ngx_conf_t *cf, ngx_http_referer_conf_t *rlcf, + ngx_str_t *name, ngx_regex_t *regex) +{ +#if (NGX_PCRE) + ngx_str_t err; + ngx_http_referer_regex_t *rr; + u_char errstr[NGX_MAX_CONF_ERRSTR]; + + if (rlcf->regex == NULL) { + rlcf->regex = ngx_array_create(cf->pool, 2, + sizeof(ngx_http_referer_regex_t)); + if (rlcf->regex == NULL) { + return NGX_CONF_ERROR; + } + } + + rr = ngx_array_push(rlcf->regex); + if (rr == NULL) { + return NGX_CONF_ERROR; + } + + if (regex) { + rr->regex = regex; + rr->name = *name; + + return NGX_CONF_OK; + } + + err.len = NGX_MAX_CONF_ERRSTR; + err.data = errstr; + + name->len--; + name->data++; + + rr->regex = ngx_regex_compile(name, NGX_REGEX_CASELESS, cf->pool, &err); + + if (rr->regex == NULL) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data); + return NGX_CONF_ERROR; + } + + rr->name = *name; + + return NGX_CONF_OK; + +#else + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "the using of the regex \"%V\" requires PCRE library", + name); + + return NGX_CONF_ERROR; + +#endif +} + + static int ngx_libc_cdecl ngx_http_cmp_referer_wildcards(const void *one, const void *two) { diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c index 7a2fb85b3..59b43d054 100644 --- a/src/http/ngx_http.c +++ b/src/http/ngx_http.c @@ -98,6 +98,9 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ngx_http_core_loc_conf_t *clcf; ngx_http_phase_handler_pt checker; ngx_http_core_main_conf_t *cmcf; +#if (NGX_PCRE) + ngx_uint_t regex; +#endif #if (NGX_WIN32) ngx_iocp_conf_t *iocpcf; #endif @@ -655,10 +658,21 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } +#if (NGX_PCRE) + regex = 0; +#endif + name = in_addr[a].names.elts; for (s = 0; s < in_addr[a].names.nelts; s++) { +#if (NGX_PCRE) + if (name[s].regex) { + regex++; + continue; + } +#endif + rc = ngx_hash_add_key(&ha, &name[s].name, name[s].core_srv_conf, NGX_HASH_WILDCARD_KEY); @@ -740,6 +754,27 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } ngx_destroy_pool(ha.temp_pool); + +#if (NGX_PCRE) + + if (regex == 0) { + continue; + } + + in_addr[a].nregex = regex; + in_addr[a].regex = ngx_palloc(cf->pool, + regex * sizeof(ngx_http_server_name_t)); + + if (in_addr[a].regex == NULL) { + return NGX_CONF_ERROR; + } + + for (i = 0, s = 0; s < in_addr[a].names.nelts; s++) { + if (name[s].regex) { + in_addr[a].regex[i++] = name[s]; + } + } +#endif } in_addr = in_port[p].addrs.elts; @@ -871,9 +906,13 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } hip->addrs[i].virtual_names = vn; - vn->hash = in_addr[i].hash; - vn->wc_head = in_addr[i].wc_head; - vn->wc_tail = in_addr[i].wc_tail; + vn->names.hash = in_addr[i].hash; + vn->names.wc_head = in_addr[i].wc_head; + vn->names.wc_tail = in_addr[i].wc_tail; +#if (NGX_PCRE) + vn->nregex = in_addr[i].nregex; + vn->regex = in_addr[i].regex; +#endif } if (done) { @@ -932,7 +971,8 @@ ngx_http_add_address(ngx_conf_t *cf, ngx_http_conf_in_port_t *in_port, if (in_port->addrs.elts == NULL) { if (ngx_array_init(&in_port->addrs, cf->temp_pool, 4, - sizeof(ngx_http_conf_in_addr_t)) != NGX_OK) + sizeof(ngx_http_conf_in_addr_t)) + != NGX_OK) { return NGX_ERROR; } @@ -949,6 +989,10 @@ ngx_http_add_address(ngx_conf_t *cf, ngx_http_conf_in_port_t *in_port, in_addr->wc_head = NULL; in_addr->wc_tail = NULL; in_addr->names.elts = NULL; +#if (NGX_PCRE) + in_addr->nregex = 0; + in_addr->regex = NULL; +#endif in_addr->core_srv_conf = cscf; in_addr->default_server = lscf->conf.default_server; in_addr->bind = lscf->conf.bind; @@ -981,13 +1025,15 @@ ngx_http_add_names(ngx_conf_t *cf, ngx_http_conf_in_addr_t *in_addr, if (in_addr->names.elts == NULL) { if (ngx_array_init(&in_addr->names, cf->temp_pool, 4, - sizeof(ngx_http_server_name_t)) != NGX_OK) + sizeof(ngx_http_server_name_t)) + != NGX_OK) { return NGX_ERROR; } } server_names = cscf->server_names.elts; + for (i = 0; i < cscf->server_names.nelts; i++) { for (n = 0; n < server_names[i].name.len; n++) { @@ -998,7 +1044,6 @@ ngx_http_add_names(ngx_conf_t *cf, ngx_http_conf_in_addr_t *in_addr, ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cf->log, 0, "name: %V", &server_names[i].name); - name = ngx_array_push(&in_addr->names); if (name == NULL) { return NGX_ERROR; diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 1ef1a6c16..78ff87de0 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -2272,9 +2272,12 @@ ngx_http_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) return NGX_CONF_ERROR; } +#if (NGX_PCRE) + sn->regex = NULL; +#endif + sn->core_srv_conf = conf; sn->name.len = conf->server_name.len; sn->name.data = conf->server_name.data; - sn->core_srv_conf = conf; } ngx_conf_merge_size_value(conf->connection_pool_size, @@ -2719,6 +2722,10 @@ ngx_http_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ngx_str_t *value, name; ngx_uint_t i; ngx_http_server_name_t *sn; +#if (NGX_PCRE) + ngx_str_t err; + u_char errstr[NGX_MAX_CONF_ERRSTR]; +#endif value = cf->args->elts; @@ -2732,6 +2739,13 @@ ngx_http_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } + if (value[1].data[0] == '~') { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "first server name \"%V\" " + "must not be regular expression", &value[1]); + return NGX_CONF_ERROR; + } + name = value[1]; if (ch == '.') { @@ -2775,9 +2789,42 @@ ngx_http_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } +#if (NGX_PCRE) + sn->regex = NULL; +#endif + sn->core_srv_conf = cscf; sn->name.len = value[i].len; sn->name.data = value[i].data; - sn->core_srv_conf = cscf; + + if (value[i].data[0] != '~') { + continue; + } + +#if (NGX_PCRE) + err.len = NGX_MAX_CONF_ERRSTR; + err.data = errstr; + + value[i].len--; + value[i].data++; + + sn->regex = ngx_regex_compile(&value[i], NGX_REGEX_CASELESS, cf->pool, + &err); + + if (sn->regex == NULL) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data); + return NGX_CONF_ERROR; + } + + sn->name.len = value[i].len; + sn->name.data = value[i].data; + +#else + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "the using of the regex \"%V\" " + "requires PCRE library", &value[i]); + + return NGX_CONF_ERROR; +#endif } return NGX_CONF_OK; diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h index 52ac5ddf3..79cd1f653 100644 --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -151,8 +151,10 @@ typedef struct { typedef struct { in_addr_t addr; + /* the default server configuration for this address:port */ ngx_http_core_srv_conf_t *core_srv_conf; + ngx_http_virtual_names_t *virtual_names; } ngx_http_in_addr_t; @@ -180,6 +182,11 @@ typedef struct { ngx_array_t names; /* array of ngx_http_server_name_t */ +#if (NGX_PCRE) + ngx_uint_t nregex; + ngx_http_server_name_t *regex; +#endif + /* the default server configuration for this address:port */ ngx_http_core_srv_conf_t *core_srv_conf; @@ -190,10 +197,13 @@ typedef struct { } ngx_http_conf_in_addr_t; -typedef struct { - ngx_str_t name; +struct ngx_http_server_name_s { +#if (NGX_PCRE) + ngx_regex_t *regex; +#endif ngx_http_core_srv_conf_t *core_srv_conf; /* virtual name server conf */ -} ngx_http_server_name_t; + ngx_str_t name; +}; typedef struct { diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index bc7a92fcc..70434dcb3 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -1457,18 +1457,56 @@ static void ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host, size_t len, ngx_uint_t hash) { - ngx_http_virtual_names_t *vn; ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; +#if (NGX_PCRE) + ngx_int_t n; + ngx_uint_t i; + ngx_str_t name; + ngx_http_server_name_t *sn; +#endif - vn = r->virtual_names; - - cscf = ngx_hash_find_combined(vn, hash, host, len); + cscf = ngx_hash_find_combined(&r->virtual_names->names, hash, host, len); if (cscf) { goto found; } +#if (NGX_PCRE) + + if (r->virtual_names->nregex) { + + name.len = len; + name.data = host; + + sn = r->virtual_names->regex; + + for (i = 0; i < r->virtual_names->nregex; i++) { + + n = ngx_regex_exec(sn[i].regex, &name, NULL, 0); + + if (n == NGX_REGEX_NO_MATCHED) { + continue; + } + + if (n < 0) { + ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, + ngx_regex_exec_n + " failed: %d on \"%V\" using \"%V\"", + n, &name, &sn[i].name); + return; + } + + /* match */ + + cscf = sn[i].core_srv_conf; + + goto found; + } + } + +#endif + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); if (cscf->wildcard) { diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h index b440f14fd..0b269a893 100644 --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -275,7 +275,15 @@ typedef struct { } ngx_http_connection_t; -typedef ngx_hash_combined_t ngx_http_virtual_names_t; +typedef struct ngx_http_server_name_s ngx_http_server_name_t; + + +typedef struct { + ngx_hash_combined_t names; + + ngx_uint_t nregex; + ngx_http_server_name_t *regex; +} ngx_http_virtual_names_t; typedef void (*ngx_http_cleanup_pt)(void *data); |