Annotation of embedaddon/nginx/src/http/modules/ngx_http_access_module.c, revision 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>