Mercurial > hg > nginx
annotate src/http/modules/ngx_http_referer_module.c @ 4437:3a1507f48686 stable-1.0
Merge of r4372, r4373, r4374:
SCGI fixes:
*) Fixed incorrect use of r->http_version in scgi module.
The r->http_version is a version of client's request, and modules
must not set it unless they are really willing to downgrade protocol
version used for a response (i.e. to HTTP/0.9 if no response headers
are available). In neither case r->http_version may be upgraded.
The former code downgraded response from HTTP/1.1 to HTTP/1.0 for no
reason, causing various problems (see ticket #66). It was also
possible that HTTP/0.9 requests were upgraded to HTTP/1.0.
*) Removed duplicate function declaration.
*) Removed error if there is no Status header.
The SCGI specification doesn't specify format of the response, and
assuming CGI specs should be used there is no reason to complain.
RFC 3875 explicitly states that "A Status header field is optional,
and status 200 'OK' is assumed if it is omitted".
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Sun, 05 Feb 2012 13:53:50 +0000 |
parents | 6afb20bf2ad5 |
children | d620f497c50f |
rev | line source |
---|---|
577 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4 */ | |
5 | |
6 | |
7 #include <ngx_config.h> | |
8 #include <ngx_core.h> | |
9 #include <ngx_http.h> | |
10 | |
11 | |
595 | 12 #define NGX_HTTP_REFERER_NO_URI_PART ((void *) 4) |
13 | |
1785 | 14 #if !(NGX_PCRE) |
1388 | 15 |
16 #define ngx_regex_t void | |
17 | |
18 #endif | |
19 | |
20 | |
577 | 21 typedef struct { |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
22 ngx_hash_combined_t hash; |
577 | 23 |
1388 | 24 #if (NGX_PCRE) |
25 ngx_array_t *regex; | |
26 #endif | |
27 | |
593 | 28 ngx_flag_t no_referer; |
29 ngx_flag_t blocked_referer; | |
577 | 30 |
593 | 31 ngx_hash_keys_arrays_t *keys; |
3939
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
32 |
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
33 ngx_uint_t referer_hash_max_size; |
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
34 ngx_uint_t referer_hash_bucket_size; |
577 | 35 } ngx_http_referer_conf_t; |
36 | |
37 | |
38 static void * ngx_http_referer_create_conf(ngx_conf_t *cf); | |
39 static char * ngx_http_referer_merge_conf(ngx_conf_t *cf, void *parent, | |
40 void *child); | |
41 static char *ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, | |
42 void *conf); | |
593 | 43 static char *ngx_http_add_referer(ngx_conf_t *cf, ngx_hash_keys_arrays_t *keys, |
595 | 44 ngx_str_t *value, ngx_str_t *uri); |
1388 | 45 static char *ngx_http_add_regex_referer(ngx_conf_t *cf, |
46 ngx_http_referer_conf_t *rlcf, ngx_str_t *name, ngx_regex_t *regex); | |
593 | 47 static int ngx_libc_cdecl ngx_http_cmp_referer_wildcards(const void *one, |
48 const void *two); | |
577 | 49 |
50 | |
51 static ngx_command_t ngx_http_referer_commands[] = { | |
52 | |
53 { ngx_string("valid_referers"), | |
54 NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, | |
55 ngx_http_valid_referers, | |
56 NGX_HTTP_LOC_CONF_OFFSET, | |
57 0, | |
58 NULL }, | |
59 | |
3939
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
60 { ngx_string("referer_hash_max_size"), |
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
61 NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
62 ngx_conf_set_num_slot, |
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
63 NGX_HTTP_LOC_CONF_OFFSET, |
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
64 offsetof(ngx_http_referer_conf_t, referer_hash_max_size), |
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
65 NULL }, |
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
66 |
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
67 { ngx_string("referer_hash_bucket_size"), |
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
68 NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
69 ngx_conf_set_num_slot, |
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
70 NGX_HTTP_LOC_CONF_OFFSET, |
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
71 offsetof(ngx_http_referer_conf_t, referer_hash_bucket_size), |
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
72 NULL }, |
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
73 |
577 | 74 ngx_null_command |
75 }; | |
76 | |
77 | |
78 static ngx_http_module_t ngx_http_referer_module_ctx = { | |
79 NULL, /* preconfiguration */ | |
80 NULL, /* postconfiguration */ | |
81 | |
82 NULL, /* create main configuration */ | |
83 NULL, /* init main configuration */ | |
84 | |
85 NULL, /* create server configuration */ | |
86 NULL, /* merge server configuration */ | |
87 | |
88 ngx_http_referer_create_conf, /* create location configuration */ | |
89 ngx_http_referer_merge_conf /* merge location configuration */ | |
90 }; | |
91 | |
92 | |
93 ngx_module_t ngx_http_referer_module = { | |
94 NGX_MODULE_V1, | |
95 &ngx_http_referer_module_ctx, /* module context */ | |
96 ngx_http_referer_commands, /* module directives */ | |
97 NGX_HTTP_MODULE, /* module type */ | |
98 NULL, /* init master */ | |
99 NULL, /* init module */ | |
100 NULL, /* init process */ | |
101 NULL, /* init thread */ | |
102 NULL, /* exit thread */ | |
103 NULL, /* exit process */ | |
104 NULL, /* exit master */ | |
105 NGX_MODULE_V1_PADDING | |
106 }; | |
107 | |
108 | |
109 static ngx_int_t | |
110 ngx_http_referer_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, | |
111 uintptr_t data) | |
112 { | |
1388 | 113 u_char *p, *ref, *last; |
114 size_t len; | |
115 ngx_str_t *uri; | |
116 ngx_uint_t i, key; | |
117 ngx_http_referer_conf_t *rlcf; | |
118 u_char buf[256]; | |
577 | 119 |
593 | 120 rlcf = ngx_http_get_module_loc_conf(r, ngx_http_referer_module); |
577 | 121 |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
122 if (rlcf->hash.hash.buckets == NULL |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
123 && rlcf->hash.wc_head == NULL |
1388 | 124 && rlcf->hash.wc_tail == NULL |
125 #if (NGX_PCRE) | |
126 && rlcf->regex == NULL | |
127 #endif | |
128 ) | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
129 { |
595 | 130 goto valid; |
577 | 131 } |
132 | |
133 if (r->headers_in.referer == NULL) { | |
593 | 134 if (rlcf->no_referer) { |
595 | 135 goto valid; |
136 } | |
577 | 137 |
595 | 138 goto invalid; |
577 | 139 } |
140 | |
141 len = r->headers_in.referer->value.len; | |
142 ref = r->headers_in.referer->value.data; | |
143 | |
3459 | 144 if (len >= sizeof("http://i.ru") - 1) { |
145 last = ref + len; | |
146 | |
147 if (ngx_strncasecmp(ref, (u_char *) "http://", 7) == 0) { | |
148 ref += 7; | |
149 goto valid_scheme; | |
150 | |
151 } else if (ngx_strncasecmp(ref, (u_char *) "https://", 8) == 0) { | |
152 ref += 8; | |
153 goto valid_scheme; | |
595 | 154 } |
577 | 155 } |
156 | |
3459 | 157 if (rlcf->blocked_referer) { |
158 goto valid; | |
159 } | |
160 | |
161 goto invalid; | |
162 | |
163 valid_scheme: | |
164 | |
595 | 165 i = 0; |
166 key = 0; | |
577 | 167 |
595 | 168 for (p = ref; p < last; p++) { |
593 | 169 if (*p == '/' || *p == ':') { |
170 break; | |
577 | 171 } |
595 | 172 |
173 buf[i] = ngx_tolower(*p); | |
174 key = ngx_hash(key, buf[i++]); | |
175 | |
176 if (i == 256) { | |
177 goto invalid; | |
178 } | |
593 | 179 } |
577 | 180 |
1388 | 181 uri = ngx_hash_find_combined(&rlcf->hash, key, buf, p - ref); |
577 | 182 |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
183 if (uri) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
184 goto uri; |
577 | 185 } |
186 | |
1388 | 187 #if (NGX_PCRE) |
188 | |
189 if (rlcf->regex) { | |
1785 | 190 ngx_int_t rc; |
191 ngx_str_t referer; | |
1388 | 192 |
193 referer.len = len - 7; | |
194 referer.data = ref; | |
195 | |
1785 | 196 rc = ngx_regex_exec_array(rlcf->regex, &referer, r->connection->log); |
1388 | 197 |
1785 | 198 if (rc == NGX_OK) { |
1388 | 199 goto valid; |
200 } | |
1785 | 201 |
202 if (rc == NGX_ERROR) { | |
203 return rc; | |
204 } | |
205 | |
206 /* NGX_DECLINED */ | |
1388 | 207 } |
208 | |
209 #endif | |
210 | |
595 | 211 invalid: |
212 | |
577 | 213 *v = ngx_http_variable_true_value; |
214 | |
215 return NGX_OK; | |
595 | 216 |
217 uri: | |
218 | |
219 for ( /* void */ ; p < last; p++) { | |
220 if (*p == '/') { | |
221 break; | |
222 } | |
223 } | |
224 | |
225 len = last - p; | |
226 | |
227 if (uri == NGX_HTTP_REFERER_NO_URI_PART) { | |
228 goto valid; | |
229 } | |
230 | |
231 if (len < uri->len || ngx_strncmp(uri->data, p, uri->len) != 0) { | |
232 goto invalid; | |
233 } | |
234 | |
235 valid: | |
236 | |
237 *v = ngx_http_variable_null_value; | |
238 | |
239 return NGX_OK; | |
577 | 240 } |
241 | |
242 | |
243 static void * | |
244 ngx_http_referer_create_conf(ngx_conf_t *cf) | |
245 { | |
246 ngx_http_referer_conf_t *conf; | |
247 | |
593 | 248 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_referer_conf_t)); |
577 | 249 if (conf == NULL) { |
2912
c7d57b539248
return NULL instead of NGX_CONF_ERROR on a create conf failure
Igor Sysoev <igor@sysoev.ru>
parents:
1800
diff
changeset
|
250 return NULL; |
577 | 251 } |
252 | |
1782
db07cb9d1cbc
regex valid_referers were not inherited
Igor Sysoev <igor@sysoev.ru>
parents:
1704
diff
changeset
|
253 #if (NGX_PCRE) |
db07cb9d1cbc
regex valid_referers were not inherited
Igor Sysoev <igor@sysoev.ru>
parents:
1704
diff
changeset
|
254 conf->regex = NGX_CONF_UNSET_PTR; |
db07cb9d1cbc
regex valid_referers were not inherited
Igor Sysoev <igor@sysoev.ru>
parents:
1704
diff
changeset
|
255 #endif |
db07cb9d1cbc
regex valid_referers were not inherited
Igor Sysoev <igor@sysoev.ru>
parents:
1704
diff
changeset
|
256 |
577 | 257 conf->no_referer = NGX_CONF_UNSET; |
258 conf->blocked_referer = NGX_CONF_UNSET; | |
3939
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
259 conf->referer_hash_max_size = NGX_CONF_UNSET_UINT; |
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
260 conf->referer_hash_bucket_size = NGX_CONF_UNSET_UINT; |
577 | 261 |
262 return conf; | |
263 } | |
264 | |
265 | |
266 static char * | |
267 ngx_http_referer_merge_conf(ngx_conf_t *cf, void *parent, void *child) | |
268 { | |
269 ngx_http_referer_conf_t *prev = parent; | |
270 ngx_http_referer_conf_t *conf = child; | |
271 | |
593 | 272 ngx_hash_init_t hash; |
273 | |
274 if (conf->keys == NULL) { | |
275 conf->hash = prev->hash; | |
276 | |
1800 | 277 #if (NGX_PCRE) |
1782
db07cb9d1cbc
regex valid_referers were not inherited
Igor Sysoev <igor@sysoev.ru>
parents:
1704
diff
changeset
|
278 ngx_conf_merge_ptr_value(conf->regex, prev->regex, NULL); |
1800 | 279 #endif |
577 | 280 ngx_conf_merge_value(conf->no_referer, prev->no_referer, 0); |
281 ngx_conf_merge_value(conf->blocked_referer, prev->blocked_referer, 0); | |
3939
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
282 ngx_conf_merge_uint_value(conf->referer_hash_max_size, |
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
283 prev->referer_hash_max_size, 2048); |
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
284 ngx_conf_merge_uint_value(conf->referer_hash_bucket_size, |
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
285 prev->referer_hash_bucket_size, 64); |
593 | 286 |
287 return NGX_CONF_OK; | |
288 } | |
289 | |
603 | 290 if ((conf->no_referer == 1 || conf->blocked_referer == 1) |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
291 && conf->keys->keys.nelts == 0 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
292 && conf->keys->dns_wc_head.nelts == 0 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
293 && conf->keys->dns_wc_tail.nelts == 0) |
603 | 294 { |
295 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, | |
296 "the \"none\" or \"blocked\" referers are specified " | |
297 "in the \"valid_referers\" directive " | |
298 "without any valid referer"); | |
299 return NGX_CONF_ERROR; | |
300 } | |
301 | |
3939
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
302 ngx_conf_merge_uint_value(conf->referer_hash_max_size, |
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
303 prev->referer_hash_max_size, 2048); |
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
304 ngx_conf_merge_uint_value(conf->referer_hash_bucket_size, |
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
305 prev->referer_hash_bucket_size, 64); |
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
306 conf->referer_hash_bucket_size = ngx_align(conf->referer_hash_bucket_size, |
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
307 ngx_cacheline_size); |
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
308 |
593 | 309 hash.key = ngx_hash_key_lc; |
3939
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
310 hash.max_size = conf->referer_hash_max_size; |
3cbbe86a7a95
referer_hash_max_size and referer_hash_bucket_size directives
Igor Sysoev <igor@sysoev.ru>
parents:
3516
diff
changeset
|
311 hash.bucket_size = conf->referer_hash_bucket_size; |
4241
6afb20bf2ad5
Merging r4009, r4133, r4184, r4201, r4202, r4203, r4204, r4205:
Igor Sysoev <igor@sysoev.ru>
parents:
3939
diff
changeset
|
312 hash.name = "referer_hash"; |
593 | 313 hash.pool = cf->pool; |
314 | |
315 if (conf->keys->keys.nelts) { | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
316 hash.hash = &conf->hash.hash; |
593 | 317 hash.temp_pool = NULL; |
318 | |
319 if (ngx_hash_init(&hash, conf->keys->keys.elts, conf->keys->keys.nelts) | |
320 != NGX_OK) | |
321 { | |
322 return NGX_CONF_ERROR; | |
323 } | |
324 } | |
325 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
326 if (conf->keys->dns_wc_head.nelts) { |
593 | 327 |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
328 ngx_qsort(conf->keys->dns_wc_head.elts, |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
329 (size_t) conf->keys->dns_wc_head.nelts, |
593 | 330 sizeof(ngx_hash_key_t), |
331 ngx_http_cmp_referer_wildcards); | |
332 | |
333 hash.hash = NULL; | |
334 hash.temp_pool = cf->temp_pool; | |
335 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
336 if (ngx_hash_wildcard_init(&hash, conf->keys->dns_wc_head.elts, |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
337 conf->keys->dns_wc_head.nelts) |
593 | 338 != NGX_OK) |
339 { | |
340 return NGX_CONF_ERROR; | |
341 } | |
342 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
343 conf->hash.wc_head = (ngx_hash_wildcard_t *) hash.hash; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
344 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
345 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
346 if (conf->keys->dns_wc_tail.nelts) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
347 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
348 ngx_qsort(conf->keys->dns_wc_tail.elts, |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
349 (size_t) conf->keys->dns_wc_tail.nelts, |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
350 sizeof(ngx_hash_key_t), |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
351 ngx_http_cmp_referer_wildcards); |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
352 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
353 hash.hash = NULL; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
354 hash.temp_pool = cf->temp_pool; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
355 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
356 if (ngx_hash_wildcard_init(&hash, conf->keys->dns_wc_tail.elts, |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
357 conf->keys->dns_wc_tail.nelts) |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
358 != NGX_OK) |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
359 { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
360 return NGX_CONF_ERROR; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
361 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
362 |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
363 conf->hash.wc_tail = (ngx_hash_wildcard_t *) hash.hash; |
577 | 364 } |
365 | |
1800 | 366 #if (NGX_PCRE) |
1782
db07cb9d1cbc
regex valid_referers were not inherited
Igor Sysoev <igor@sysoev.ru>
parents:
1704
diff
changeset
|
367 ngx_conf_merge_ptr_value(conf->regex, prev->regex, NULL); |
1800 | 368 #endif |
1782
db07cb9d1cbc
regex valid_referers were not inherited
Igor Sysoev <igor@sysoev.ru>
parents:
1704
diff
changeset
|
369 |
577 | 370 if (conf->no_referer == NGX_CONF_UNSET) { |
371 conf->no_referer = 0; | |
372 } | |
373 | |
374 if (conf->blocked_referer == NGX_CONF_UNSET) { | |
375 conf->blocked_referer = 0; | |
376 } | |
377 | |
611 | 378 conf->keys = NULL; |
379 | |
577 | 380 return NGX_CONF_OK; |
381 } | |
382 | |
383 | |
384 static char * | |
385 ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
386 { | |
593 | 387 ngx_http_referer_conf_t *rlcf = conf; |
577 | 388 |
593 | 389 u_char *p; |
595 | 390 ngx_str_t *value, uri, name; |
593 | 391 ngx_uint_t i, n; |
577 | 392 ngx_http_variable_t *var; |
393 ngx_http_server_name_t *sn; | |
394 ngx_http_core_srv_conf_t *cscf; | |
395 | |
3516
dd1570b6f237
ngx_str_set() and ngx_str_null()
Igor Sysoev <igor@sysoev.ru>
parents:
3459
diff
changeset
|
396 ngx_str_set(&name, "invalid_referer"); |
577 | 397 |
583 | 398 var = ngx_http_add_variable(cf, &name, |
1565 | 399 NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOHASH); |
577 | 400 if (var == NULL) { |
401 return NGX_CONF_ERROR; | |
402 } | |
403 | |
637 | 404 var->get_handler = ngx_http_referer_variable; |
577 | 405 |
593 | 406 if (rlcf->keys == NULL) { |
407 rlcf->keys = ngx_pcalloc(cf->temp_pool, sizeof(ngx_hash_keys_arrays_t)); | |
408 if (rlcf->keys == NULL) { | |
409 return NGX_CONF_ERROR; | |
410 } | |
577 | 411 |
593 | 412 rlcf->keys->pool = cf->pool; |
413 rlcf->keys->temp_pool = cf->pool; | |
414 | |
415 if (ngx_hash_keys_array_init(rlcf->keys, NGX_HASH_SMALL) != NGX_OK) { | |
577 | 416 return NGX_CONF_ERROR; |
417 } | |
418 } | |
419 | |
420 value = cf->args->elts; | |
421 | |
422 for (i = 1; i < cf->args->nelts; i++) { | |
423 if (value[i].len == 0) { | |
424 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
425 "invalid referer \"%V\"", &value[i]); | |
426 return NGX_CONF_ERROR; | |
427 } | |
428 | |
429 if (ngx_strcmp(value[i].data, "none") == 0) { | |
593 | 430 rlcf->no_referer = 1; |
577 | 431 continue; |
432 } | |
433 | |
434 if (ngx_strcmp(value[i].data, "blocked") == 0) { | |
593 | 435 rlcf->blocked_referer = 1; |
577 | 436 continue; |
437 } | |
438 | |
3516
dd1570b6f237
ngx_str_set() and ngx_str_null()
Igor Sysoev <igor@sysoev.ru>
parents:
3459
diff
changeset
|
439 ngx_str_null(&uri); |
595 | 440 |
577 | 441 if (ngx_strcmp(value[i].data, "server_names") == 0) { |
593 | 442 |
443 cscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_core_module); | |
577 | 444 |
593 | 445 sn = cscf->server_names.elts; |
446 for (n = 0; n < cscf->server_names.nelts; n++) { | |
1388 | 447 |
448 #if (NGX_PCRE) | |
449 if (sn[n].regex) { | |
450 | |
451 if (ngx_http_add_regex_referer(cf, rlcf, &sn[n].name, | |
3325 | 452 sn[n].regex->regex) |
1388 | 453 != NGX_OK) |
454 { | |
455 return NGX_CONF_ERROR; | |
456 } | |
457 | |
458 continue; | |
459 } | |
460 #endif | |
461 | |
595 | 462 if (ngx_http_add_referer(cf, rlcf->keys, &sn[n].name, &uri) |
463 != NGX_OK) | |
464 { | |
593 | 465 return NGX_CONF_ERROR; |
466 } | |
467 } | |
577 | 468 |
469 continue; | |
470 } | |
471 | |
1388 | 472 if (value[i].data[0] == '~') { |
473 if (ngx_http_add_regex_referer(cf, rlcf, &value[i], NULL) != NGX_OK) | |
474 { | |
475 return NGX_CONF_ERROR; | |
476 } | |
477 | |
478 continue; | |
479 } | |
480 | |
1242 | 481 p = (u_char *) ngx_strchr(value[i].data, '/'); |
577 | 482 |
593 | 483 if (p) { |
595 | 484 uri.len = (value[i].data + value[i].len) - p; |
485 uri.data = p; | |
593 | 486 value[i].len = p - value[i].data; |
577 | 487 } |
488 | |
595 | 489 if (ngx_http_add_referer(cf, rlcf->keys, &value[i], &uri) != NGX_OK) { |
577 | 490 return NGX_CONF_ERROR; |
491 } | |
492 } | |
493 | |
494 return NGX_CONF_OK; | |
495 } | |
593 | 496 |
497 | |
498 static char * | |
499 ngx_http_add_referer(ngx_conf_t *cf, ngx_hash_keys_arrays_t *keys, | |
595 | 500 ngx_str_t *value, ngx_str_t *uri) |
593 | 501 { |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
502 ngx_int_t rc; |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
503 ngx_str_t *u; |
593 | 504 |
595 | 505 if (uri->len == 0) { |
506 u = NGX_HTTP_REFERER_NO_URI_PART; | |
507 | |
508 } else { | |
509 u = ngx_palloc(cf->pool, sizeof(ngx_str_t)); | |
510 if (u == NULL) { | |
511 return NGX_CONF_ERROR; | |
512 } | |
513 | |
514 *u = *uri; | |
515 } | |
516 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
517 rc = ngx_hash_add_key(keys, value, u, NGX_HASH_WILDCARD_KEY); |
593 | 518 |
519 if (rc == NGX_OK) { | |
520 return NGX_CONF_OK; | |
521 } | |
522 | |
1253
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
523 if (rc == NGX_DECLINED) { |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
524 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
525 "invalid hostname or wildcard \"%V\"", value); |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
526 } |
8ef04207c84f
the "www.example.*" wildcard hash support
Igor Sysoev <igor@sysoev.ru>
parents:
1242
diff
changeset
|
527 |
593 | 528 if (rc == NGX_BUSY) { |
529 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
530 "conflicting parameter \"%V\"", value); | |
531 } | |
532 | |
533 return NGX_CONF_ERROR; | |
534 } | |
535 | |
536 | |
1388 | 537 static char * |
538 ngx_http_add_regex_referer(ngx_conf_t *cf, ngx_http_referer_conf_t *rlcf, | |
539 ngx_str_t *name, ngx_regex_t *regex) | |
540 { | |
541 #if (NGX_PCRE) | |
3325 | 542 ngx_regex_elt_t *re; |
543 ngx_regex_compile_t rc; | |
544 u_char errstr[NGX_MAX_CONF_ERRSTR]; | |
1388 | 545 |
3122
3e994ac670dc
test space between "~" and regex in server_name and invalid_referers
Igor Sysoev <igor@sysoev.ru>
parents:
3116
diff
changeset
|
546 if (name->len == 1) { |
3e994ac670dc
test space between "~" and regex in server_name and invalid_referers
Igor Sysoev <igor@sysoev.ru>
parents:
3116
diff
changeset
|
547 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "empty regex in \"%V\"", name); |
3e994ac670dc
test space between "~" and regex in server_name and invalid_referers
Igor Sysoev <igor@sysoev.ru>
parents:
3116
diff
changeset
|
548 return NGX_CONF_ERROR; |
3e994ac670dc
test space between "~" and regex in server_name and invalid_referers
Igor Sysoev <igor@sysoev.ru>
parents:
3116
diff
changeset
|
549 } |
3e994ac670dc
test space between "~" and regex in server_name and invalid_referers
Igor Sysoev <igor@sysoev.ru>
parents:
3116
diff
changeset
|
550 |
1782
db07cb9d1cbc
regex valid_referers were not inherited
Igor Sysoev <igor@sysoev.ru>
parents:
1704
diff
changeset
|
551 if (rlcf->regex == NGX_CONF_UNSET_PTR) { |
1785 | 552 rlcf->regex = ngx_array_create(cf->pool, 2, sizeof(ngx_regex_elt_t)); |
1388 | 553 if (rlcf->regex == NULL) { |
554 return NGX_CONF_ERROR; | |
555 } | |
556 } | |
557 | |
1785 | 558 re = ngx_array_push(rlcf->regex); |
559 if (re == NULL) { | |
1388 | 560 return NGX_CONF_ERROR; |
561 } | |
562 | |
563 if (regex) { | |
1785 | 564 re->regex = regex; |
565 re->name = name->data; | |
1388 | 566 |
567 return NGX_CONF_OK; | |
568 } | |
569 | |
570 name->len--; | |
571 name->data++; | |
572 | |
3325 | 573 ngx_memzero(&rc, sizeof(ngx_regex_compile_t)); |
1388 | 574 |
3325 | 575 rc.pattern = *name; |
576 rc.pool = cf->pool; | |
577 rc.options = NGX_REGEX_CASELESS; | |
578 rc.err.len = NGX_MAX_CONF_ERRSTR; | |
579 rc.err.data = errstr; | |
580 | |
581 if (ngx_regex_compile(&rc) != NGX_OK) { | |
582 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err); | |
1388 | 583 return NGX_CONF_ERROR; |
584 } | |
585 | |
3325 | 586 re->regex = rc.regex; |
1785 | 587 re->name = name->data; |
1388 | 588 |
589 return NGX_CONF_OK; | |
590 | |
591 #else | |
592 | |
593 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
594 "the using of the regex \"%V\" requires PCRE library", | |
595 name); | |
596 | |
597 return NGX_CONF_ERROR; | |
598 | |
599 #endif | |
600 } | |
601 | |
602 | |
593 | 603 static int ngx_libc_cdecl |
604 ngx_http_cmp_referer_wildcards(const void *one, const void *two) | |
605 { | |
606 ngx_hash_key_t *first, *second; | |
607 | |
608 first = (ngx_hash_key_t *) one; | |
609 second = (ngx_hash_key_t *) two; | |
610 | |
3116
98e288c6dac3
If .domain.com, .sub.domain.com, and .domain-some.com were defined,
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
611 return ngx_dns_strcmp(first->key.data, second->key.data); |
593 | 612 } |