Mercurial > hg > nginx-vendor-0-8
comparison src/http/modules/ngx_http_access_module.c @ 540:c04fa65fe604 NGINX_0_8_22
nginx 0.8.22
*) Feature: the "proxy_bind", "fastcgi_bind", and "memcached_bind"
directives.
*) Feature: the "access" and the "deny" directives support IPv6.
*) Feature: the "set_real_ip_from" directive supports IPv6 addresses in
request headers.
*) Feature: the "unix:" parameter of the "set_real_ip_from" directive.
*) Bugfix: nginx did not delete unix domain socket after configuration
testing.
*) Bugfix: nginx deleted unix domain socket while online upgrade.
*) Bugfix: the "!-x" operator did not work.
Thanks to Maxim Dounin.
*) Bugfix: a segmentation fault might occur in a worker process, if
limit_rate was used in HTTPS server.
Thanks to Maxim Dounin.
*) Bugfix: a segmentation fault might occur in a worker process while
$limit_rate logging.
Thanks to Maxim Dounin.
*) Bugfix: a segmentation fault might occur in a worker process, if
there was no "listen" directive in "server" block; the bug had
appeared in 0.8.21.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Tue, 03 Nov 2009 00:00:00 +0300 |
parents | f39b9e29530d |
children | 53f5f04a64b8 |
comparison
equal
deleted
inserted
replaced
539:c88014f74832 | 540:c04fa65fe604 |
---|---|
8 #include <ngx_core.h> | 8 #include <ngx_core.h> |
9 #include <ngx_http.h> | 9 #include <ngx_http.h> |
10 | 10 |
11 | 11 |
12 typedef struct { | 12 typedef struct { |
13 in_addr_t mask; | 13 in_addr_t mask; |
14 in_addr_t addr; | 14 in_addr_t addr; |
15 ngx_uint_t deny; /* unsigned deny:1; */ | 15 ngx_uint_t deny; /* unsigned deny:1; */ |
16 } ngx_http_access_rule_t; | 16 } ngx_http_access_rule_t; |
17 | 17 |
18 #if (NGX_HAVE_INET6) | |
18 | 19 |
19 typedef struct { | 20 typedef struct { |
20 ngx_array_t *rules; /* array of ngx_http_access_rule_t */ | 21 struct in6_addr addr; |
22 struct in6_addr mask; | |
23 ngx_uint_t deny; /* unsigned deny:1; */ | |
24 } ngx_http_access_rule6_t; | |
25 | |
26 #endif | |
27 | |
28 typedef struct { | |
29 ngx_array_t *rules; /* array of ngx_http_access_rule_t */ | |
30 #if (NGX_HAVE_INET6) | |
31 ngx_array_t *rules6; /* array of ngx_http_access_rule6_t */ | |
32 #endif | |
21 } ngx_http_access_loc_conf_t; | 33 } ngx_http_access_loc_conf_t; |
22 | 34 |
23 | 35 |
24 static ngx_int_t ngx_http_access_handler(ngx_http_request_t *r); | 36 static ngx_int_t ngx_http_access_handler(ngx_http_request_t *r); |
37 static ngx_int_t ngx_http_access_inet(ngx_http_request_t *r, | |
38 ngx_http_access_loc_conf_t *alcf, in_addr_t addr); | |
39 #if (NGX_HAVE_INET6) | |
40 static ngx_int_t ngx_http_access_inet6(ngx_http_request_t *r, | |
41 ngx_http_access_loc_conf_t *alcf, u_char *p); | |
42 #endif | |
43 static ngx_int_t ngx_http_access_found(ngx_http_request_t *r, ngx_uint_t deny); | |
25 static char *ngx_http_access_rule(ngx_conf_t *cf, ngx_command_t *cmd, | 44 static char *ngx_http_access_rule(ngx_conf_t *cf, ngx_command_t *cmd, |
26 void *conf); | 45 void *conf); |
27 static void *ngx_http_access_create_loc_conf(ngx_conf_t *cf); | 46 static void *ngx_http_access_create_loc_conf(ngx_conf_t *cf); |
28 static char *ngx_http_access_merge_loc_conf(ngx_conf_t *cf, | 47 static char *ngx_http_access_merge_loc_conf(ngx_conf_t *cf, |
29 void *parent, void *child); | 48 void *parent, void *child); |
85 | 104 |
86 | 105 |
87 static ngx_int_t | 106 static ngx_int_t |
88 ngx_http_access_handler(ngx_http_request_t *r) | 107 ngx_http_access_handler(ngx_http_request_t *r) |
89 { | 108 { |
90 ngx_uint_t i; | |
91 struct sockaddr_in *sin; | 109 struct sockaddr_in *sin; |
92 ngx_http_access_rule_t *rule; | |
93 ngx_http_core_loc_conf_t *clcf; | |
94 ngx_http_access_loc_conf_t *alcf; | 110 ngx_http_access_loc_conf_t *alcf; |
95 | 111 |
96 alcf = ngx_http_get_module_loc_conf(r, ngx_http_access_module); | 112 alcf = ngx_http_get_module_loc_conf(r, ngx_http_access_module); |
97 | 113 |
98 if (alcf->rules == NULL) { | 114 #if (NGX_HAVE_INET6) |
99 return NGX_DECLINED; | 115 |
100 } | 116 if (alcf->rules6 && r->connection->sockaddr->sa_family == AF_INET6) { |
101 | 117 u_char *p; |
102 /* AF_INET only */ | 118 in_addr_t addr; |
103 | 119 struct sockaddr_in6 *sin6; |
104 if (r->connection->sockaddr->sa_family != AF_INET) { | 120 |
105 return NGX_DECLINED; | 121 sin6 = (struct sockaddr_in6 *) r->connection->sockaddr; |
106 } | 122 p = sin6->sin6_addr.s6_addr; |
107 | 123 |
108 sin = (struct sockaddr_in *) r->connection->sockaddr; | 124 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { |
125 addr = p[12] << 24; | |
126 addr += p[13] << 16; | |
127 addr += p[14] << 8; | |
128 addr += p[15]; | |
129 return ngx_http_access_inet(r, alcf, htonl(addr)); | |
130 } | |
131 | |
132 return ngx_http_access_inet6(r, alcf, p); | |
133 } | |
134 | |
135 #endif | |
136 | |
137 if (alcf->rules && r->connection->sockaddr->sa_family == AF_INET) { | |
138 sin = (struct sockaddr_in *) r->connection->sockaddr; | |
139 return ngx_http_access_inet(r, alcf, sin->sin_addr.s_addr); | |
140 } | |
141 | |
142 return NGX_DECLINED; | |
143 } | |
144 | |
145 | |
146 static ngx_int_t | |
147 ngx_http_access_inet(ngx_http_request_t *r, ngx_http_access_loc_conf_t *alcf, | |
148 in_addr_t addr) | |
149 { | |
150 ngx_uint_t i; | |
151 ngx_http_access_rule_t *rule; | |
109 | 152 |
110 rule = alcf->rules->elts; | 153 rule = alcf->rules->elts; |
111 for (i = 0; i < alcf->rules->nelts; i++) { | 154 for (i = 0; i < alcf->rules->nelts; i++) { |
112 | 155 |
113 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 156 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
114 "access: %08XD %08XD %08XD", | 157 "access: %08XD %08XD %08XD", |
115 sin->sin_addr.s_addr, rule[i].mask, rule[i].addr); | 158 addr, rule[i].mask, rule[i].addr); |
116 | 159 |
117 if ((sin->sin_addr.s_addr & rule[i].mask) == rule[i].addr) { | 160 if ((addr & rule[i].mask) == rule[i].addr) { |
118 if (rule[i].deny) { | 161 return ngx_http_access_found(r, rule[i].deny); |
119 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | 162 } |
120 | 163 } |
121 if (clcf->satisfy == NGX_HTTP_SATISFY_ALL) { | 164 |
122 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | 165 return NGX_DECLINED; |
123 "access forbidden by rule"); | 166 } |
124 } | 167 |
125 | 168 |
126 return NGX_HTTP_FORBIDDEN; | 169 #if (NGX_HAVE_INET6) |
170 | |
171 static ngx_int_t | |
172 ngx_http_access_inet6(ngx_http_request_t *r, ngx_http_access_loc_conf_t *alcf, | |
173 u_char *p) | |
174 { | |
175 ngx_uint_t n; | |
176 ngx_uint_t i; | |
177 ngx_http_access_rule6_t *rule6; | |
178 | |
179 rule6 = alcf->rules6->elts; | |
180 for (i = 0; i < alcf->rules6->nelts; i++) { | |
181 | |
182 #if (NGX_DEBUG) | |
183 { | |
184 size_t cl, ml, al; | |
185 u_char ct[NGX_INET6_ADDRSTRLEN]; | |
186 u_char mt[NGX_INET6_ADDRSTRLEN]; | |
187 u_char at[NGX_INET6_ADDRSTRLEN]; | |
188 | |
189 cl = ngx_inet6_ntop(p, ct, NGX_INET6_ADDRSTRLEN); | |
190 ml = ngx_inet6_ntop(rule6[i].mask.s6_addr, mt, NGX_INET6_ADDRSTRLEN); | |
191 al = ngx_inet6_ntop(rule6[i].addr.s6_addr, at, NGX_INET6_ADDRSTRLEN); | |
192 | |
193 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
194 "access: %*s %*s %*s", cl, ct, ml, mt, al, at); | |
195 } | |
196 #endif | |
197 | |
198 for (n = 0; n < 16; n++) { | |
199 if ((p[n] & rule6[i].mask.s6_addr[n]) != rule6[i].addr.s6_addr[n]) { | |
200 goto next; | |
127 } | 201 } |
128 | 202 } |
129 return NGX_OK; | 203 |
130 } | 204 return ngx_http_access_found(r, rule6[i].deny); |
205 | |
206 next: | |
207 continue; | |
131 } | 208 } |
132 | 209 |
133 return NGX_DECLINED; | 210 return NGX_DECLINED; |
211 } | |
212 | |
213 #endif | |
214 | |
215 | |
216 static ngx_int_t | |
217 ngx_http_access_found(ngx_http_request_t *r, ngx_uint_t deny) | |
218 { | |
219 ngx_http_core_loc_conf_t *clcf; | |
220 | |
221 if (deny) { | |
222 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
223 | |
224 if (clcf->satisfy == NGX_HTTP_SATISFY_ALL) { | |
225 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
226 "access forbidden by rule"); | |
227 } | |
228 | |
229 return NGX_HTTP_FORBIDDEN; | |
230 } | |
231 | |
232 return NGX_OK; | |
134 } | 233 } |
135 | 234 |
136 | 235 |
137 static char * | 236 static char * |
138 ngx_http_access_rule(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 237 ngx_http_access_rule(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
139 { | 238 { |
140 ngx_http_access_loc_conf_t *alcf = conf; | 239 ngx_http_access_loc_conf_t *alcf = conf; |
141 | 240 |
142 ngx_int_t rc; | 241 ngx_int_t rc; |
143 ngx_str_t *value; | 242 ngx_uint_t all; |
144 ngx_cidr_t cidr; | 243 ngx_str_t *value; |
145 ngx_http_access_rule_t *rule; | 244 ngx_cidr_t cidr; |
146 | 245 ngx_http_access_rule_t *rule; |
147 if (alcf->rules == NULL) { | 246 #if (NGX_HAVE_INET6) |
148 alcf->rules = ngx_array_create(cf->pool, 4, | 247 ngx_http_access_rule6_t *rule6; |
149 sizeof(ngx_http_access_rule_t)); | 248 #endif |
249 | |
250 ngx_memzero(&cidr, sizeof(ngx_cidr_t)); | |
251 | |
252 value = cf->args->elts; | |
253 | |
254 all = (value[1].len == 3 && ngx_strcmp(value[1].data, "all") == 0); | |
255 | |
256 if (!all) { | |
257 | |
258 rc = ngx_ptocidr(&value[1], &cidr); | |
259 | |
260 if (rc == NGX_ERROR) { | |
261 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
262 "invalid parameter \"%V\"", &value[1]); | |
263 return NGX_CONF_ERROR; | |
264 } | |
265 | |
266 if (rc == NGX_DONE) { | |
267 ngx_conf_log_error(NGX_LOG_WARN, cf, 0, | |
268 "low address bits of %V are meaningless", &value[1]); | |
269 } | |
270 } | |
271 | |
272 switch (cidr.family) { | |
273 | |
274 #if (NGX_HAVE_INET6) | |
275 case AF_INET6: | |
276 case 0: /* all */ | |
277 | |
278 if (alcf->rules6 == NULL) { | |
279 alcf->rules6 = ngx_array_create(cf->pool, 4, | |
280 sizeof(ngx_http_access_rule6_t)); | |
281 if (alcf->rules6 == NULL) { | |
282 return NGX_CONF_ERROR; | |
283 } | |
284 } | |
285 | |
286 rule6 = ngx_array_push(alcf->rules6); | |
287 if (rule6 == NULL) { | |
288 return NGX_CONF_ERROR; | |
289 } | |
290 | |
291 rule6->mask = cidr.u.in6.mask; | |
292 rule6->addr = cidr.u.in6.addr; | |
293 rule6->deny = (value[0].data[0] == 'd') ? 1 : 0; | |
294 | |
295 if (!all) { | |
296 break; | |
297 } | |
298 | |
299 /* "all" passes through */ | |
300 #endif | |
301 | |
302 default: /* AF_INET */ | |
303 | |
150 if (alcf->rules == NULL) { | 304 if (alcf->rules == NULL) { |
305 alcf->rules = ngx_array_create(cf->pool, 4, | |
306 sizeof(ngx_http_access_rule_t)); | |
307 if (alcf->rules == NULL) { | |
308 return NGX_CONF_ERROR; | |
309 } | |
310 } | |
311 | |
312 rule = ngx_array_push(alcf->rules); | |
313 if (rule == NULL) { | |
151 return NGX_CONF_ERROR; | 314 return NGX_CONF_ERROR; |
152 } | 315 } |
153 } | 316 |
154 | 317 rule->mask = cidr.u.in.mask; |
155 rule = ngx_array_push(alcf->rules); | 318 rule->addr = cidr.u.in.addr; |
156 if (rule == NULL) { | 319 rule->deny = (value[0].data[0] == 'd') ? 1 : 0; |
157 return NGX_CONF_ERROR; | 320 } |
158 } | |
159 | |
160 value = cf->args->elts; | |
161 | |
162 rule->deny = (value[0].data[0] == 'd') ? 1 : 0; | |
163 | |
164 if (value[1].len == 3 && ngx_strcmp(value[1].data, "all") == 0) { | |
165 rule->mask = 0; | |
166 rule->addr = 0; | |
167 | |
168 return NGX_CONF_OK; | |
169 } | |
170 | |
171 rc = ngx_ptocidr(&value[1], &cidr); | |
172 | |
173 if (rc == NGX_ERROR) { | |
174 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", | |
175 &value[1]); | |
176 return NGX_CONF_ERROR; | |
177 } | |
178 | |
179 if (cidr.family != AF_INET) { | |
180 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
181 "\"allow\" supports IPv4 only"); | |
182 return NGX_CONF_ERROR; | |
183 } | |
184 | |
185 if (rc == NGX_DONE) { | |
186 ngx_conf_log_error(NGX_LOG_WARN, cf, 0, | |
187 "low address bits of %V are meaningless", &value[1]); | |
188 } | |
189 | |
190 rule->mask = cidr.u.in.mask; | |
191 rule->addr = cidr.u.in.addr; | |
192 | 321 |
193 return NGX_CONF_OK; | 322 return NGX_CONF_OK; |
194 } | 323 } |
195 | 324 |
196 | 325 |
216 | 345 |
217 if (conf->rules == NULL) { | 346 if (conf->rules == NULL) { |
218 conf->rules = prev->rules; | 347 conf->rules = prev->rules; |
219 } | 348 } |
220 | 349 |
350 #if (NGX_HAVE_INET6) | |
351 if (conf->rules6 == NULL) { | |
352 conf->rules6 = prev->rules6; | |
353 } | |
354 #endif | |
355 | |
221 return NGX_CONF_OK; | 356 return NGX_CONF_OK; |
222 } | 357 } |
223 | 358 |
224 | 359 |
225 static ngx_int_t | 360 static ngx_int_t |