Annotation of embedaddon/nginx/src/http/modules/ngx_http_access_module.c, revision 1.1.1.1

1.1       misho       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; */
                     17: } ngx_http_access_rule_t;
                     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
                     34: } ngx_http_access_loc_conf_t;
                     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"),
                     56:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF
                     57:                         |NGX_CONF_TAKE1,
                     58:       ngx_http_access_rule,
                     59:       NGX_HTTP_LOC_CONF_OFFSET,
                     60:       0,
                     61:       NULL },
                     62: 
                     63:     { ngx_string("deny"),
                     64:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF
                     65:                         |NGX_CONF_TAKE1,
                     66:       ngx_http_access_rule,
                     67:       NGX_HTTP_LOC_CONF_OFFSET,
                     68:       0,
                     69:       NULL },
                     70: 
                     71:       ngx_null_command
                     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: 
                     91: ngx_module_t  ngx_http_access_module = {
                     92:     NGX_MODULE_V1,
                     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 */
                    103:     NGX_MODULE_V1_PADDING
                    104: };
                    105: 
                    106: 
                    107: static ngx_int_t
                    108: ngx_http_access_handler(ngx_http_request_t *r)
                    109: {
                    110:     struct sockaddr_in          *sin;
                    111:     ngx_http_access_loc_conf_t  *alcf;
                    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;
                    159:     ngx_http_access_rule_t  *rule;
                    160: 
                    161:     rule = alcf->rules->elts;
                    162:     for (i = 0; i < alcf->rules->nelts; i++) {
                    163: 
                    164:         ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    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: 
                    201:         ngx_log_debug6(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    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: {
                    227:     ngx_http_core_loc_conf_t  *clcf;
                    228: 
                    229:     if (deny) {
                    230:         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
                    231: 
                    232:         if (clcf->satisfy == NGX_HTTP_SATISFY_ALL) {
                    233:             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                    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;
                    253:     ngx_http_access_rule_t   *rule;
                    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) {
                    269:             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                    270:                          "invalid parameter \"%V\"", &value[1]);
                    271:             return NGX_CONF_ERROR;
                    272:         }
                    273: 
                    274:         if (rc == NGX_DONE) {
                    275:             ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
                    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: {
                    337:     ngx_http_access_loc_conf_t  *conf;
                    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: {
                    376:     ngx_http_handler_pt        *h;
                    377:     ngx_http_core_main_conf_t  *cmcf;
                    378: 
                    379:     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
                    380: 
                    381:     h = ngx_array_push(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers);
                    382:     if (h == NULL) {
                    383:         return NGX_ERROR;
                    384:     }
                    385: 
                    386:     *h = ngx_http_access_handler;
                    387: 
                    388:     return NGX_OK;
                    389: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>