diff options
Diffstat (limited to 'usr.sbin/nginx/src/http/modules/ngx_http_referer_module.c')
| -rw-r--r-- | usr.sbin/nginx/src/http/modules/ngx_http_referer_module.c | 206 |
1 files changed, 132 insertions, 74 deletions
diff --git a/usr.sbin/nginx/src/http/modules/ngx_http_referer_module.c b/usr.sbin/nginx/src/http/modules/ngx_http_referer_module.c index d8a014c5be6..b417eb227b0 100644 --- a/usr.sbin/nginx/src/http/modules/ngx_http_referer_module.c +++ b/usr.sbin/nginx/src/http/modules/ngx_http_referer_module.c @@ -12,22 +12,18 @@ #define NGX_HTTP_REFERER_NO_URI_PART ((void *) 4) -#if !(NGX_PCRE) - -#define ngx_regex_t void - -#endif - typedef struct { ngx_hash_combined_t hash; #if (NGX_PCRE) ngx_array_t *regex; + ngx_array_t *server_name_regex; #endif ngx_flag_t no_referer; ngx_flag_t blocked_referer; + ngx_flag_t server_names; ngx_hash_keys_arrays_t *keys; @@ -41,10 +37,14 @@ static char * ngx_http_referer_merge_conf(ngx_conf_t *cf, void *parent, void *child); 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 ngx_int_t ngx_http_add_referer(ngx_conf_t *cf, + ngx_hash_keys_arrays_t *keys, ngx_str_t *value, ngx_str_t *uri); +static ngx_int_t ngx_http_add_regex_referer(ngx_conf_t *cf, + ngx_http_referer_conf_t *rlcf, ngx_str_t *name); +#if (NGX_PCRE) +static ngx_int_t ngx_http_add_regex_server_name(ngx_conf_t *cf, + ngx_http_referer_conf_t *rlcf, ngx_http_regex_t *regex); +#endif static int ngx_libc_cdecl ngx_http_cmp_referer_wildcards(const void *one, const void *two); @@ -117,6 +117,10 @@ ngx_http_referer_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, ngx_uint_t i, key; ngx_http_referer_conf_t *rlcf; u_char buf[256]; +#if (NGX_PCRE) + ngx_int_t rc; + ngx_str_t referer; +#endif rlcf = ngx_http_get_module_loc_conf(r, ngx_http_referer_module); @@ -125,6 +129,7 @@ ngx_http_referer_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, && rlcf->hash.wc_tail == NULL #if (NGX_PCRE) && rlcf->regex == NULL + && rlcf->server_name_regex == NULL #endif ) { @@ -147,10 +152,12 @@ ngx_http_referer_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, if (ngx_strncasecmp(ref, (u_char *) "http://", 7) == 0) { ref += 7; + len -= 7; goto valid_scheme; } else if (ngx_strncasecmp(ref, (u_char *) "https://", 8) == 0) { ref += 8; + len -= 8; goto valid_scheme; } } @@ -171,12 +178,12 @@ valid_scheme: break; } - buf[i] = ngx_tolower(*p); - key = ngx_hash(key, buf[i++]); - if (i == 256) { goto invalid; } + + buf[i] = ngx_tolower(*p); + key = ngx_hash(key, buf[i++]); } uri = ngx_hash_find_combined(&rlcf->hash, key, buf, p - ref); @@ -187,11 +194,26 @@ valid_scheme: #if (NGX_PCRE) - if (rlcf->regex) { - ngx_int_t rc; - ngx_str_t referer; + if (rlcf->server_name_regex) { + referer.len = p - ref; + referer.data = buf; + + rc = ngx_regex_exec_array(rlcf->server_name_regex, &referer, + r->connection->log); + + if (rc == NGX_OK) { + goto valid; + } + + if (rc == NGX_ERROR) { + return rc; + } + + /* NGX_DECLINED */ + } - referer.len = len - 7; + if (rlcf->regex) { + referer.len = len; referer.data = ref; rc = ngx_regex_exec_array(rlcf->regex, &referer, r->connection->log); @@ -251,8 +273,17 @@ ngx_http_referer_create_conf(ngx_conf_t *cf) return NULL; } + /* + * set by ngx_pcalloc(): + * + * conf->hash = { NULL }; + * conf->server_names = 0; + * conf->keys = NULL; + */ + #if (NGX_PCRE) conf->regex = NGX_CONF_UNSET_PTR; + conf->server_name_regex = NGX_CONF_UNSET_PTR; #endif conf->no_referer = NGX_CONF_UNSET; @@ -270,13 +301,18 @@ ngx_http_referer_merge_conf(ngx_conf_t *cf, void *parent, void *child) ngx_http_referer_conf_t *prev = parent; ngx_http_referer_conf_t *conf = child; - ngx_hash_init_t hash; + ngx_uint_t n; + ngx_hash_init_t hash; + ngx_http_server_name_t *sn; + ngx_http_core_srv_conf_t *cscf; if (conf->keys == NULL) { conf->hash = prev->hash; #if (NGX_PCRE) ngx_conf_merge_ptr_value(conf->regex, prev->regex, NULL); + ngx_conf_merge_ptr_value(conf->server_name_regex, + prev->server_name_regex, NULL); #endif ngx_conf_merge_value(conf->no_referer, prev->no_referer, 0); ngx_conf_merge_value(conf->blocked_referer, prev->blocked_referer, 0); @@ -288,6 +324,33 @@ ngx_http_referer_merge_conf(ngx_conf_t *cf, void *parent, void *child) return NGX_CONF_OK; } + if (conf->server_names == 1) { + cscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_core_module); + + 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_server_name(cf, conf, sn[n].regex) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + + continue; + } +#endif + + if (ngx_http_add_referer(cf, conf->keys, &sn[n].name, NULL) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + } + } + if ((conf->no_referer == 1 || conf->blocked_referer == 1) && conf->keys->keys.nelts == 0 && conf->keys->dns_wc_head.nelts == 0 @@ -366,6 +429,8 @@ ngx_http_referer_merge_conf(ngx_conf_t *cf, void *parent, void *child) #if (NGX_PCRE) ngx_conf_merge_ptr_value(conf->regex, prev->regex, NULL); + ngx_conf_merge_ptr_value(conf->server_name_regex, prev->server_name_regex, + NULL); #endif if (conf->no_referer == NGX_CONF_UNSET) { @@ -389,15 +454,12 @@ ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) u_char *p; ngx_str_t *value, uri, name; - ngx_uint_t i, n; + ngx_uint_t i; ngx_http_variable_t *var; - ngx_http_server_name_t *sn; - ngx_http_core_srv_conf_t *cscf; ngx_str_set(&name, "invalid_referer"); - var = ngx_http_add_variable(cf, &name, - NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOHASH); + var = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE); if (var == NULL) { return NGX_CONF_ERROR; } @@ -437,48 +499,21 @@ ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) continue; } - ngx_str_null(&uri); - if (ngx_strcmp(value[i].data, "server_names") == 0) { - - cscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_core_module); - - 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->regex) - != NGX_OK) - { - return NGX_CONF_ERROR; - } - - continue; - } -#endif - - if (ngx_http_add_referer(cf, rlcf->keys, &sn[n].name, &uri) - != NGX_OK) - { - return NGX_CONF_ERROR; - } - } - + rlcf->server_names = 1; continue; } if (value[i].data[0] == '~') { - if (ngx_http_add_regex_referer(cf, rlcf, &value[i], NULL) != NGX_OK) - { + if (ngx_http_add_regex_referer(cf, rlcf, &value[i]) != NGX_OK) { return NGX_CONF_ERROR; } continue; } + ngx_str_null(&uri); + p = (u_char *) ngx_strchr(value[i].data, '/'); if (p) { @@ -496,20 +531,20 @@ ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } -static char * +static ngx_int_t ngx_http_add_referer(ngx_conf_t *cf, ngx_hash_keys_arrays_t *keys, ngx_str_t *value, ngx_str_t *uri) { ngx_int_t rc; ngx_str_t *u; - if (uri->len == 0) { + if (uri == NULL || uri->len == 0) { u = NGX_HTTP_REFERER_NO_URI_PART; } else { u = ngx_palloc(cf->pool, sizeof(ngx_str_t)); if (u == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } *u = *uri; @@ -518,7 +553,7 @@ ngx_http_add_referer(ngx_conf_t *cf, ngx_hash_keys_arrays_t *keys, rc = ngx_hash_add_key(keys, value, u, NGX_HASH_WILDCARD_KEY); if (rc == NGX_OK) { - return NGX_CONF_OK; + return NGX_OK; } if (rc == NGX_DECLINED) { @@ -531,13 +566,13 @@ ngx_http_add_referer(ngx_conf_t *cf, ngx_hash_keys_arrays_t *keys, "conflicting parameter \"%V\"", value); } - return NGX_CONF_ERROR; + return NGX_ERROR; } -static char * +static ngx_int_t ngx_http_add_regex_referer(ngx_conf_t *cf, ngx_http_referer_conf_t *rlcf, - ngx_str_t *name, ngx_regex_t *regex) + ngx_str_t *name) { #if (NGX_PCRE) ngx_regex_elt_t *re; @@ -546,26 +581,19 @@ ngx_http_add_regex_referer(ngx_conf_t *cf, ngx_http_referer_conf_t *rlcf, if (name->len == 1) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "empty regex in \"%V\"", name); - return NGX_CONF_ERROR; + return NGX_ERROR; } if (rlcf->regex == NGX_CONF_UNSET_PTR) { rlcf->regex = ngx_array_create(cf->pool, 2, sizeof(ngx_regex_elt_t)); if (rlcf->regex == NULL) { - return NGX_CONF_ERROR; + return NGX_ERROR; } } re = ngx_array_push(rlcf->regex); if (re == NULL) { - return NGX_CONF_ERROR; - } - - if (regex) { - re->regex = regex; - re->name = name->data; - - return NGX_CONF_OK; + return NGX_ERROR; } name->len--; @@ -581,13 +609,13 @@ ngx_http_add_regex_referer(ngx_conf_t *cf, ngx_http_referer_conf_t *rlcf, if (ngx_regex_compile(&rc) != NGX_OK) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err); - return NGX_CONF_ERROR; + return NGX_ERROR; } re->regex = rc.regex; re->name = name->data; - return NGX_CONF_OK; + return NGX_OK; #else @@ -595,12 +623,42 @@ ngx_http_add_regex_referer(ngx_conf_t *cf, ngx_http_referer_conf_t *rlcf, "the using of the regex \"%V\" requires PCRE library", name); - return NGX_CONF_ERROR; + return NGX_ERROR; #endif } +#if (NGX_PCRE) + +static ngx_int_t +ngx_http_add_regex_server_name(ngx_conf_t *cf, ngx_http_referer_conf_t *rlcf, + ngx_http_regex_t *regex) +{ + ngx_regex_elt_t *re; + + if (rlcf->server_name_regex == NGX_CONF_UNSET_PTR) { + rlcf->server_name_regex = ngx_array_create(cf->pool, 2, + sizeof(ngx_regex_elt_t)); + if (rlcf->server_name_regex == NULL) { + return NGX_ERROR; + } + } + + re = ngx_array_push(rlcf->server_name_regex); + if (re == NULL) { + return NGX_ERROR; + } + + re->regex = regex->regex; + re->name = regex->name.data; + + return NGX_OK; +} + +#endif + + static int ngx_libc_cdecl ngx_http_cmp_referer_wildcards(const void *one, const void *two) { |
