static char * ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_referer_conf_t *rlcf = conf; u_char *p; ngx_str_t *value, uri; ngx_uint_t i; if (rlcf->keys == NULL) { rlcf->keys = ngx_pcalloc(cf->temp_pool, sizeof(ngx_hash_keys_arrays_t)); if (rlcf->keys == NULL) { return NGX_CONF_ERROR; } rlcf->keys->pool = cf->pool; rlcf->keys->temp_pool = cf->pool; if (ngx_hash_keys_array_init(rlcf->keys, NGX_HASH_SMALL) != NGX_OK) { return NGX_CONF_ERROR; } } value = cf->args->elts; for (i = 1; i < cf->args->nelts; i++) { if (value[i].len == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid referer \"%V\"", &value[i]); return NGX_CONF_ERROR; } if (ngx_strcmp(value[i].data, "none") == 0) { rlcf->no_referer = 1; continue; } if (ngx_strcmp(value[i].data, "blocked") == 0) { rlcf->blocked_referer = 1; continue; } if (ngx_strcmp(value[i].data, "server_names") == 0) { rlcf->server_names = 1; continue; } if (value[i].data[0] == '~') { 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) { uri.len = (value[i].data + value[i].len) - p; uri.data = p; value[i].len = p - value[i].data; } if (ngx_http_add_referer(cf, rlcf->keys, &value[i], &uri) != NGX_OK) { return NGX_CONF_ERROR; } } return NGX_CONF_OK; }
static char * ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_referer_conf_t *rlcf = conf; u_char *p; ngx_str_t *value, uri, name; ngx_uint_t i, n; 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); if (var == NULL) { return NGX_CONF_ERROR; } var->get_handler = ngx_http_referer_variable; if (rlcf->keys == NULL) { rlcf->keys = ngx_pcalloc(cf->temp_pool, sizeof(ngx_hash_keys_arrays_t)); if (rlcf->keys == NULL) { return NGX_CONF_ERROR; } rlcf->keys->pool = cf->pool; rlcf->keys->temp_pool = cf->pool; if (ngx_hash_keys_array_init(rlcf->keys, NGX_HASH_SMALL) != NGX_OK) { return NGX_CONF_ERROR; } } value = cf->args->elts; for (i = 1; i < cf->args->nelts; i++) { if (value[i].len == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid referer \"%V\"", &value[i]); return NGX_CONF_ERROR; } if (ngx_strcmp(value[i].data, "none") == 0) { rlcf->no_referer = 1; continue; } if (ngx_strcmp(value[i].data, "blocked") == 0) { rlcf->blocked_referer = 1; 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; } } 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) { uri.len = (value[i].data + value[i].len) - p; uri.data = p; value[i].len = p - value[i].data; } if (ngx_http_add_referer(cf, rlcf->keys, &value[i], &uri) != NGX_OK) { return NGX_CONF_ERROR; } } return NGX_CONF_OK; }
static char * 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_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); ngx_conf_merge_uint_value(conf->referer_hash_max_size, prev->referer_hash_max_size, 2048); ngx_conf_merge_uint_value(conf->referer_hash_bucket_size, prev->referer_hash_bucket_size, 64); 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 && conf->keys->dns_wc_tail.nelts == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "the \"none\" or \"blocked\" referers are specified " "in the \"valid_referers\" directive " "without any valid referer"); return NGX_CONF_ERROR; } ngx_conf_merge_uint_value(conf->referer_hash_max_size, prev->referer_hash_max_size, 2048); ngx_conf_merge_uint_value(conf->referer_hash_bucket_size, prev->referer_hash_bucket_size, 64); conf->referer_hash_bucket_size = ngx_align(conf->referer_hash_bucket_size, ngx_cacheline_size); hash.key = ngx_hash_key_lc; hash.max_size = conf->referer_hash_max_size; hash.bucket_size = conf->referer_hash_bucket_size; hash.name = "referer_hash"; hash.pool = cf->pool; if (conf->keys->keys.nelts) { hash.hash = &conf->hash.hash; hash.temp_pool = NULL; if (ngx_hash_init(&hash, conf->keys->keys.elts, conf->keys->keys.nelts) != NGX_OK) { return NGX_CONF_ERROR; } } if (conf->keys->dns_wc_head.nelts) { ngx_qsort(conf->keys->dns_wc_head.elts, (size_t) conf->keys->dns_wc_head.nelts, sizeof(ngx_hash_key_t), ngx_http_cmp_referer_wildcards); hash.hash = NULL; hash.temp_pool = cf->temp_pool; if (ngx_hash_wildcard_init(&hash, conf->keys->dns_wc_head.elts, conf->keys->dns_wc_head.nelts) != NGX_OK) { return NGX_CONF_ERROR; } conf->hash.wc_head = (ngx_hash_wildcard_t *) hash.hash; } if (conf->keys->dns_wc_tail.nelts) { ngx_qsort(conf->keys->dns_wc_tail.elts, (size_t) conf->keys->dns_wc_tail.nelts, sizeof(ngx_hash_key_t), ngx_http_cmp_referer_wildcards); hash.hash = NULL; hash.temp_pool = cf->temp_pool; if (ngx_hash_wildcard_init(&hash, conf->keys->dns_wc_tail.elts, conf->keys->dns_wc_tail.nelts) != NGX_OK) { return NGX_CONF_ERROR; } conf->hash.wc_tail = (ngx_hash_wildcard_t *) hash.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 if (conf->no_referer == NGX_CONF_UNSET) { conf->no_referer = 0; } if (conf->blocked_referer == NGX_CONF_UNSET) { conf->blocked_referer = 0; } conf->keys = NULL; return NGX_CONF_OK; }