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>