comparison src/http/modules/ngx_http_access_module.c @ 552: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
551:c88014f74832 552: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