Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ngx_http_access_module.c
Go to the documentation of this file.
1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) Nginx, Inc.
5  */
6 
7 
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_http.h>
11 
12 
13 typedef struct {
14  in_addr_t mask;
15  in_addr_t addr;
16  ngx_uint_t deny; /* unsigned deny:1; */
18 
19 #if (NGX_HAVE_INET6)
20 
21 typedef struct {
22  struct in6_addr addr;
23  struct in6_addr mask;
24  ngx_uint_t deny; /* unsigned deny:1; */
25 } ngx_http_access_rule6_t;
26 
27 #endif
28 
29 typedef struct {
30  ngx_array_t *rules; /* array of ngx_http_access_rule_t */
31 #if (NGX_HAVE_INET6)
32  ngx_array_t *rules6; /* array of ngx_http_access_rule6_t */
33 #endif
35 
36 
37 static ngx_int_t ngx_http_access_handler(ngx_http_request_t *r);
38 static ngx_int_t ngx_http_access_inet(ngx_http_request_t *r,
39  ngx_http_access_loc_conf_t *alcf, in_addr_t addr);
40 #if (NGX_HAVE_INET6)
41 static ngx_int_t ngx_http_access_inet6(ngx_http_request_t *r,
42  ngx_http_access_loc_conf_t *alcf, u_char *p);
43 #endif
44 static ngx_int_t ngx_http_access_found(ngx_http_request_t *r, ngx_uint_t deny);
45 static char *ngx_http_access_rule(ngx_conf_t *cf, ngx_command_t *cmd,
46  void *conf);
47 static void *ngx_http_access_create_loc_conf(ngx_conf_t *cf);
48 static char *ngx_http_access_merge_loc_conf(ngx_conf_t *cf,
49  void *parent, void *child);
50 static ngx_int_t ngx_http_access_init(ngx_conf_t *cf);
51 
52 
53 static ngx_command_t ngx_http_access_commands[] = {
54 
55  { ngx_string("allow"),
58  ngx_http_access_rule,
60  0,
61  NULL },
62 
63  { ngx_string("deny"),
66  ngx_http_access_rule,
68  0,
69  NULL },
70 
72 };
73 
74 
75 
76 static ngx_http_module_t ngx_http_access_module_ctx = {
77  NULL, /* preconfiguration */
78  ngx_http_access_init, /* postconfiguration */
79 
80  NULL, /* create main configuration */
81  NULL, /* init main configuration */
82 
83  NULL, /* create server configuration */
84  NULL, /* merge server configuration */
85 
86  ngx_http_access_create_loc_conf, /* create location configuration */
87  ngx_http_access_merge_loc_conf /* merge location configuration */
88 };
89 
90 
93  &ngx_http_access_module_ctx, /* module context */
94  ngx_http_access_commands, /* module directives */
95  NGX_HTTP_MODULE, /* module type */
96  NULL, /* init master */
97  NULL, /* init module */
98  NULL, /* init process */
99  NULL, /* init thread */
100  NULL, /* exit thread */
101  NULL, /* exit process */
102  NULL, /* exit master */
104 };
105 
106 
107 static ngx_int_t
108 ngx_http_access_handler(ngx_http_request_t *r)
109 {
110  struct sockaddr_in *sin;
112 #if (NGX_HAVE_INET6)
113  u_char *p;
114  in_addr_t addr;
115  struct sockaddr_in6 *sin6;
116 #endif
117 
118  alcf = ngx_http_get_module_loc_conf(r, ngx_http_access_module);
119 
120  switch (r->connection->sockaddr->sa_family) {
121 
122  case AF_INET:
123  if (alcf->rules) {
124  sin = (struct sockaddr_in *) r->connection->sockaddr;
125  return ngx_http_access_inet(r, alcf, sin->sin_addr.s_addr);
126  }
127  break;
128 
129 #if (NGX_HAVE_INET6)
130 
131  case AF_INET6:
132  sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
133  p = sin6->sin6_addr.s6_addr;
134 
135  if (alcf->rules && IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
136  addr = p[12] << 24;
137  addr += p[13] << 16;
138  addr += p[14] << 8;
139  addr += p[15];
140  return ngx_http_access_inet(r, alcf, htonl(addr));
141  }
142 
143  if (alcf->rules6) {
144  return ngx_http_access_inet6(r, alcf, p);
145  }
146 
147 #endif
148  }
149 
150  return NGX_DECLINED;
151 }
152 
153 
154 static ngx_int_t
155 ngx_http_access_inet(ngx_http_request_t *r, ngx_http_access_loc_conf_t *alcf,
156  in_addr_t addr)
157 {
158  ngx_uint_t i;
160 
161  rule = alcf->rules->elts;
162  for (i = 0; i < alcf->rules->nelts; i++) {
163 
165  "access: %08XD %08XD %08XD",
166  addr, rule[i].mask, rule[i].addr);
167 
168  if ((addr & rule[i].mask) == rule[i].addr) {
169  return ngx_http_access_found(r, rule[i].deny);
170  }
171  }
172 
173  return NGX_DECLINED;
174 }
175 
176 
177 #if (NGX_HAVE_INET6)
178 
179 static ngx_int_t
180 ngx_http_access_inet6(ngx_http_request_t *r, ngx_http_access_loc_conf_t *alcf,
181  u_char *p)
182 {
183  ngx_uint_t n;
184  ngx_uint_t i;
185  ngx_http_access_rule6_t *rule6;
186 
187  rule6 = alcf->rules6->elts;
188  for (i = 0; i < alcf->rules6->nelts; i++) {
189 
190 #if (NGX_DEBUG)
191  {
192  size_t cl, ml, al;
193  u_char ct[NGX_INET6_ADDRSTRLEN];
194  u_char mt[NGX_INET6_ADDRSTRLEN];
195  u_char at[NGX_INET6_ADDRSTRLEN];
196 
197  cl = ngx_inet6_ntop(p, ct, NGX_INET6_ADDRSTRLEN);
198  ml = ngx_inet6_ntop(rule6[i].mask.s6_addr, mt, NGX_INET6_ADDRSTRLEN);
199  al = ngx_inet6_ntop(rule6[i].addr.s6_addr, at, NGX_INET6_ADDRSTRLEN);
200 
202  "access: %*s %*s %*s", cl, ct, ml, mt, al, at);
203  }
204 #endif
205 
206  for (n = 0; n < 16; n++) {
207  if ((p[n] & rule6[i].mask.s6_addr[n]) != rule6[i].addr.s6_addr[n]) {
208  goto next;
209  }
210  }
211 
212  return ngx_http_access_found(r, rule6[i].deny);
213 
214  next:
215  continue;
216  }
217 
218  return NGX_DECLINED;
219 }
220 
221 #endif
222 
223 
224 static ngx_int_t
225 ngx_http_access_found(ngx_http_request_t *r, ngx_uint_t deny)
226 {
228 
229  if (deny) {
231 
232  if (clcf->satisfy == NGX_HTTP_SATISFY_ALL) {
234  "access forbidden by rule");
235  }
236 
237  return NGX_HTTP_FORBIDDEN;
238  }
239 
240  return NGX_OK;
241 }
242 
243 
244 static char *
245 ngx_http_access_rule(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
246 {
247  ngx_http_access_loc_conf_t *alcf = conf;
248 
249  ngx_int_t rc;
250  ngx_uint_t all;
251  ngx_str_t *value;
252  ngx_cidr_t cidr;
254 #if (NGX_HAVE_INET6)
255  ngx_http_access_rule6_t *rule6;
256 #endif
257 
258  ngx_memzero(&cidr, sizeof(ngx_cidr_t));
259 
260  value = cf->args->elts;
261 
262  all = (value[1].len == 3 && ngx_strcmp(value[1].data, "all") == 0);
263 
264  if (!all) {
265 
266  rc = ngx_ptocidr(&value[1], &cidr);
267 
268  if (rc == NGX_ERROR) {
270  "invalid parameter \"%V\"", &value[1]);
271  return NGX_CONF_ERROR;
272  }
273 
274  if (rc == NGX_DONE) {
276  "low address bits of %V are meaningless", &value[1]);
277  }
278  }
279 
280  switch (cidr.family) {
281 
282 #if (NGX_HAVE_INET6)
283  case AF_INET6:
284  case 0: /* all */
285 
286  if (alcf->rules6 == NULL) {
287  alcf->rules6 = ngx_array_create(cf->pool, 4,
288  sizeof(ngx_http_access_rule6_t));
289  if (alcf->rules6 == NULL) {
290  return NGX_CONF_ERROR;
291  }
292  }
293 
294  rule6 = ngx_array_push(alcf->rules6);
295  if (rule6 == NULL) {
296  return NGX_CONF_ERROR;
297  }
298 
299  rule6->mask = cidr.u.in6.mask;
300  rule6->addr = cidr.u.in6.addr;
301  rule6->deny = (value[0].data[0] == 'd') ? 1 : 0;
302 
303  if (!all) {
304  break;
305  }
306 
307  /* "all" passes through */
308 #endif
309 
310  default: /* AF_INET */
311 
312  if (alcf->rules == NULL) {
313  alcf->rules = ngx_array_create(cf->pool, 4,
314  sizeof(ngx_http_access_rule_t));
315  if (alcf->rules == NULL) {
316  return NGX_CONF_ERROR;
317  }
318  }
319 
320  rule = ngx_array_push(alcf->rules);
321  if (rule == NULL) {
322  return NGX_CONF_ERROR;
323  }
324 
325  rule->mask = cidr.u.in.mask;
326  rule->addr = cidr.u.in.addr;
327  rule->deny = (value[0].data[0] == 'd') ? 1 : 0;
328  }
329 
330  return NGX_CONF_OK;
331 }
332 
333 
334 static void *
335 ngx_http_access_create_loc_conf(ngx_conf_t *cf)
336 {
338 
339  conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_access_loc_conf_t));
340  if (conf == NULL) {
341  return NULL;
342  }
343 
344  return conf;
345 }
346 
347 
348 static char *
349 ngx_http_access_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
350 {
351  ngx_http_access_loc_conf_t *prev = parent;
352  ngx_http_access_loc_conf_t *conf = child;
353 
354 #if (NGX_HAVE_INET6)
355 
356  if (conf->rules == NULL && conf->rules6 == NULL) {
357  conf->rules = prev->rules;
358  conf->rules6 = prev->rules6;
359  }
360 
361 #else
362 
363  if (conf->rules == NULL) {
364  conf->rules = prev->rules;
365  }
366 
367 #endif
368 
369  return NGX_CONF_OK;
370 }
371 
372 
373 static ngx_int_t
374 ngx_http_access_init(ngx_conf_t *cf)
375 {
378 
380 
382  if (h == NULL) {
383  return NGX_ERROR;
384  }
385 
386  *h = ngx_http_access_handler;
387 
388  return NGX_OK;
389 }