Annotation of embedaddon/nginx/src/http/modules/ngx_http_userid_filter_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: #define NGX_HTTP_USERID_OFF   0
        !            14: #define NGX_HTTP_USERID_LOG   1
        !            15: #define NGX_HTTP_USERID_V1    2
        !            16: #define NGX_HTTP_USERID_ON    3
        !            17: 
        !            18: /* 31 Dec 2037 23:55:55 GMT */
        !            19: #define NGX_HTTP_USERID_MAX_EXPIRES  2145916555
        !            20: 
        !            21: 
        !            22: typedef struct {
        !            23:     ngx_uint_t  enable;
        !            24: 
        !            25:     ngx_int_t   service;
        !            26: 
        !            27:     ngx_str_t   name;
        !            28:     ngx_str_t   domain;
        !            29:     ngx_str_t   path;
        !            30:     ngx_str_t   p3p;
        !            31: 
        !            32:     time_t      expires;
        !            33: 
        !            34:     u_char      mark;
        !            35: } ngx_http_userid_conf_t;
        !            36: 
        !            37: 
        !            38: typedef struct {
        !            39:     uint32_t    uid_got[4];
        !            40:     uint32_t    uid_set[4];
        !            41:     ngx_str_t   cookie;
        !            42:     ngx_uint_t  reset;
        !            43: } ngx_http_userid_ctx_t;
        !            44: 
        !            45: 
        !            46: static ngx_http_userid_ctx_t *ngx_http_userid_get_uid(ngx_http_request_t *r,
        !            47:     ngx_http_userid_conf_t *conf);
        !            48: static ngx_int_t ngx_http_userid_variable(ngx_http_request_t *r,
        !            49:     ngx_http_variable_value_t *v, ngx_str_t *name, uint32_t *uid);
        !            50: static ngx_int_t ngx_http_userid_set_uid(ngx_http_request_t *r,
        !            51:     ngx_http_userid_ctx_t *ctx, ngx_http_userid_conf_t *conf);
        !            52: static ngx_int_t ngx_http_userid_create_uid(ngx_http_request_t *r,
        !            53:     ngx_http_userid_ctx_t *ctx, ngx_http_userid_conf_t *conf);
        !            54: 
        !            55: static ngx_int_t ngx_http_userid_add_variables(ngx_conf_t *cf);
        !            56: static ngx_int_t ngx_http_userid_init(ngx_conf_t *cf);
        !            57: static void *ngx_http_userid_create_conf(ngx_conf_t *cf);
        !            58: static char *ngx_http_userid_merge_conf(ngx_conf_t *cf, void *parent,
        !            59:     void *child);
        !            60: static char *ngx_http_userid_domain(ngx_conf_t *cf, void *post, void *data);
        !            61: static char *ngx_http_userid_path(ngx_conf_t *cf, void *post, void *data);
        !            62: static char *ngx_http_userid_expires(ngx_conf_t *cf, ngx_command_t *cmd,
        !            63:     void *conf);
        !            64: static char *ngx_http_userid_p3p(ngx_conf_t *cf, void *post, void *data);
        !            65: static char *ngx_http_userid_mark(ngx_conf_t *cf, ngx_command_t *cmd,
        !            66:     void *conf);
        !            67: static ngx_int_t ngx_http_userid_init_worker(ngx_cycle_t *cycle);
        !            68: 
        !            69: 
        !            70: 
        !            71: static uint32_t  start_value;
        !            72: static uint32_t  sequencer_v1 = 1;
        !            73: static uint32_t  sequencer_v2 = 0x03030302;
        !            74: 
        !            75: 
        !            76: static u_char expires[] = "; expires=Thu, 31-Dec-37 23:55:55 GMT";
        !            77: 
        !            78: 
        !            79: static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
        !            80: 
        !            81: 
        !            82: static ngx_conf_enum_t  ngx_http_userid_state[] = {
        !            83:     { ngx_string("off"), NGX_HTTP_USERID_OFF },
        !            84:     { ngx_string("log"), NGX_HTTP_USERID_LOG },
        !            85:     { ngx_string("v1"), NGX_HTTP_USERID_V1 },
        !            86:     { ngx_string("on"), NGX_HTTP_USERID_ON },
        !            87:     { ngx_null_string, 0 }
        !            88: };
        !            89: 
        !            90: 
        !            91: static ngx_conf_post_handler_pt  ngx_http_userid_domain_p =
        !            92:     ngx_http_userid_domain;
        !            93: static ngx_conf_post_handler_pt  ngx_http_userid_path_p = ngx_http_userid_path;
        !            94: static ngx_conf_post_handler_pt  ngx_http_userid_p3p_p = ngx_http_userid_p3p;
        !            95: 
        !            96: 
        !            97: static ngx_command_t  ngx_http_userid_commands[] = {
        !            98: 
        !            99:     { ngx_string("userid"),
        !           100:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !           101:       ngx_conf_set_enum_slot,
        !           102:       NGX_HTTP_LOC_CONF_OFFSET,
        !           103:       offsetof(ngx_http_userid_conf_t, enable),
        !           104:       ngx_http_userid_state },
        !           105: 
        !           106:     { ngx_string("userid_service"),
        !           107:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !           108:       ngx_conf_set_num_slot,
        !           109:       NGX_HTTP_LOC_CONF_OFFSET,
        !           110:       offsetof(ngx_http_userid_conf_t, service),
        !           111:       NULL },
        !           112: 
        !           113:     { ngx_string("userid_name"),
        !           114:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !           115:       ngx_conf_set_str_slot,
        !           116:       NGX_HTTP_LOC_CONF_OFFSET,
        !           117:       offsetof(ngx_http_userid_conf_t, name),
        !           118:       NULL },
        !           119: 
        !           120:     { ngx_string("userid_domain"),
        !           121:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !           122:       ngx_conf_set_str_slot,
        !           123:       NGX_HTTP_LOC_CONF_OFFSET,
        !           124:       offsetof(ngx_http_userid_conf_t, domain),
        !           125:       &ngx_http_userid_domain_p },
        !           126: 
        !           127:     { ngx_string("userid_path"),
        !           128:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !           129:       ngx_conf_set_str_slot,
        !           130:       NGX_HTTP_LOC_CONF_OFFSET,
        !           131:       offsetof(ngx_http_userid_conf_t, path),
        !           132:       &ngx_http_userid_path_p },
        !           133: 
        !           134:     { ngx_string("userid_expires"),
        !           135:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !           136:       ngx_http_userid_expires,
        !           137:       NGX_HTTP_LOC_CONF_OFFSET,
        !           138:       0,
        !           139:       NULL },
        !           140: 
        !           141:     { ngx_string("userid_p3p"),
        !           142:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !           143:       ngx_conf_set_str_slot,
        !           144:       NGX_HTTP_LOC_CONF_OFFSET,
        !           145:       offsetof(ngx_http_userid_conf_t, p3p),
        !           146:       &ngx_http_userid_p3p_p },
        !           147: 
        !           148:     { ngx_string("userid_mark"),
        !           149:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !           150:       ngx_http_userid_mark,
        !           151:       NGX_HTTP_LOC_CONF_OFFSET,
        !           152:       0,
        !           153:       NULL },
        !           154: 
        !           155:       ngx_null_command
        !           156: };
        !           157: 
        !           158: 
        !           159: static ngx_http_module_t  ngx_http_userid_filter_module_ctx = {
        !           160:     ngx_http_userid_add_variables,         /* preconfiguration */
        !           161:     ngx_http_userid_init,                  /* postconfiguration */
        !           162: 
        !           163:     NULL,                                  /* create main configuration */
        !           164:     NULL,                                  /* init main configuration */
        !           165: 
        !           166:     NULL,                                  /* create server configuration */
        !           167:     NULL,                                  /* merge server configuration */
        !           168: 
        !           169:     ngx_http_userid_create_conf,           /* create location configuration */
        !           170:     ngx_http_userid_merge_conf             /* merge location configuration */
        !           171: };
        !           172: 
        !           173: 
        !           174: ngx_module_t  ngx_http_userid_filter_module = {
        !           175:     NGX_MODULE_V1,
        !           176:     &ngx_http_userid_filter_module_ctx,    /* module context */
        !           177:     ngx_http_userid_commands,              /* module directives */
        !           178:     NGX_HTTP_MODULE,                       /* module type */
        !           179:     NULL,                                  /* init master */
        !           180:     NULL,                                  /* init module */
        !           181:     ngx_http_userid_init_worker,           /* init process */
        !           182:     NULL,                                  /* init thread */
        !           183:     NULL,                                  /* exit thread */
        !           184:     NULL,                                  /* exit process */
        !           185:     NULL,                                  /* exit master */
        !           186:     NGX_MODULE_V1_PADDING
        !           187: };
        !           188: 
        !           189: 
        !           190: static ngx_str_t   ngx_http_userid_got = ngx_string("uid_got");
        !           191: static ngx_str_t   ngx_http_userid_set = ngx_string("uid_set");
        !           192: static ngx_str_t   ngx_http_userid_reset = ngx_string("uid_reset");
        !           193: static ngx_uint_t  ngx_http_userid_reset_index;
        !           194: 
        !           195: 
        !           196: static ngx_int_t
        !           197: ngx_http_userid_filter(ngx_http_request_t *r)
        !           198: {
        !           199:     ngx_http_userid_ctx_t   *ctx;
        !           200:     ngx_http_userid_conf_t  *conf;
        !           201: 
        !           202:     if (r != r->main) {
        !           203:         return ngx_http_next_header_filter(r);
        !           204:     }
        !           205: 
        !           206:     conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_filter_module);
        !           207: 
        !           208:     if (conf->enable < NGX_HTTP_USERID_V1) {
        !           209:         return ngx_http_next_header_filter(r);
        !           210:     }
        !           211: 
        !           212:     ctx = ngx_http_userid_get_uid(r, conf);
        !           213: 
        !           214:     if (ctx == NULL) {
        !           215:         return NGX_ERROR;
        !           216:     }
        !           217: 
        !           218:     if (ngx_http_userid_set_uid(r, ctx, conf) == NGX_OK) {
        !           219:         return ngx_http_next_header_filter(r);
        !           220:     }
        !           221: 
        !           222:     return NGX_ERROR;
        !           223: }
        !           224: 
        !           225: 
        !           226: static ngx_int_t
        !           227: ngx_http_userid_got_variable(ngx_http_request_t *r,
        !           228:     ngx_http_variable_value_t *v, uintptr_t data)
        !           229: {
        !           230:     ngx_http_userid_ctx_t   *ctx;
        !           231:     ngx_http_userid_conf_t  *conf;
        !           232: 
        !           233:     conf = ngx_http_get_module_loc_conf(r->main, ngx_http_userid_filter_module);
        !           234: 
        !           235:     if (conf->enable == NGX_HTTP_USERID_OFF) {
        !           236:         v->not_found = 1;
        !           237:         return NGX_OK;
        !           238:     }
        !           239: 
        !           240:     ctx = ngx_http_userid_get_uid(r->main, conf);
        !           241: 
        !           242:     if (ctx == NULL) {
        !           243:         return NGX_ERROR;
        !           244:     }
        !           245: 
        !           246:     if (ctx->uid_got[3] != 0) {
        !           247:         return ngx_http_userid_variable(r->main, v, &conf->name, ctx->uid_got);
        !           248:     }
        !           249: 
        !           250:     v->not_found = 1;
        !           251: 
        !           252:     return NGX_OK;
        !           253: }
        !           254: 
        !           255: 
        !           256: static ngx_int_t
        !           257: ngx_http_userid_set_variable(ngx_http_request_t *r,
        !           258:     ngx_http_variable_value_t *v, uintptr_t data)
        !           259: {
        !           260:     ngx_http_userid_ctx_t   *ctx;
        !           261:     ngx_http_userid_conf_t  *conf;
        !           262: 
        !           263:     conf = ngx_http_get_module_loc_conf(r->main, ngx_http_userid_filter_module);
        !           264: 
        !           265:     if (conf->enable < NGX_HTTP_USERID_V1) {
        !           266:         v->not_found = 1;
        !           267:         return NGX_OK;
        !           268:     }
        !           269: 
        !           270:     ctx = ngx_http_userid_get_uid(r->main, conf);
        !           271: 
        !           272:     if (ctx == NULL) {
        !           273:         return NGX_ERROR;
        !           274:     }
        !           275: 
        !           276:     if (ngx_http_userid_create_uid(r->main, ctx, conf) != NGX_OK) {
        !           277:         return NGX_ERROR;
        !           278:     }
        !           279: 
        !           280:     if (ctx->uid_set[3] == 0) {
        !           281:         v->not_found = 1;
        !           282:         return NGX_OK;
        !           283:     }
        !           284: 
        !           285:     return ngx_http_userid_variable(r->main, v, &conf->name, ctx->uid_set);
        !           286: }
        !           287: 
        !           288: 
        !           289: static ngx_http_userid_ctx_t *
        !           290: ngx_http_userid_get_uid(ngx_http_request_t *r, ngx_http_userid_conf_t *conf)
        !           291: {
        !           292:     ngx_int_t                n;
        !           293:     ngx_str_t                src, dst;
        !           294:     ngx_table_elt_t        **cookies;
        !           295:     ngx_http_userid_ctx_t   *ctx;
        !           296: 
        !           297:     ctx = ngx_http_get_module_ctx(r, ngx_http_userid_filter_module);
        !           298: 
        !           299:     if (ctx) {
        !           300:         return ctx;
        !           301:     }
        !           302: 
        !           303:     if (ctx == NULL) {
        !           304:         ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_userid_ctx_t));
        !           305:         if (ctx == NULL) {
        !           306:             return NULL;
        !           307:         }
        !           308: 
        !           309:         ngx_http_set_ctx(r, ctx, ngx_http_userid_filter_module);
        !           310:     }
        !           311: 
        !           312:     n = ngx_http_parse_multi_header_lines(&r->headers_in.cookies, &conf->name,
        !           313:                                           &ctx->cookie);
        !           314:     if (n == NGX_DECLINED) {
        !           315:         return ctx;
        !           316:     }
        !           317: 
        !           318:     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !           319:                    "uid cookie: \"%V\"", &ctx->cookie);
        !           320: 
        !           321:     if (ctx->cookie.len < 22) {
        !           322:         cookies = r->headers_in.cookies.elts;
        !           323:         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
        !           324:                       "client sent too short userid cookie \"%V\"",
        !           325:                       &cookies[n]->value);
        !           326:         return ctx;
        !           327:     }
        !           328: 
        !           329:     src = ctx->cookie;
        !           330: 
        !           331:     /*
        !           332:      * we have to limit the encoded string to 22 characters because
        !           333:      *  1) cookie may be marked by "userid_mark",
        !           334:      *  2) and there are already the millions cookies with a garbage
        !           335:      *     instead of the correct base64 trail "=="
        !           336:      */
        !           337: 
        !           338:     src.len = 22;
        !           339: 
        !           340:     dst.data = (u_char *) ctx->uid_got;
        !           341: 
        !           342:     if (ngx_decode_base64(&dst, &src) == NGX_ERROR) {
        !           343:         cookies = r->headers_in.cookies.elts;
        !           344:         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
        !           345:                       "client sent invalid userid cookie \"%V\"",
        !           346:                       &cookies[n]->value);
        !           347:         return ctx;
        !           348:     }
        !           349: 
        !           350:     ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !           351:                    "uid: %08XD%08XD%08XD%08XD",
        !           352:                    ctx->uid_got[0], ctx->uid_got[1],
        !           353:                    ctx->uid_got[2], ctx->uid_got[3]);
        !           354: 
        !           355:     return ctx;
        !           356: }
        !           357: 
        !           358: 
        !           359: static ngx_int_t
        !           360: ngx_http_userid_set_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx,
        !           361:     ngx_http_userid_conf_t *conf)
        !           362: {
        !           363:     u_char           *cookie, *p;
        !           364:     size_t            len;
        !           365:     ngx_str_t         src, dst;
        !           366:     ngx_table_elt_t  *set_cookie, *p3p;
        !           367: 
        !           368:     if (ngx_http_userid_create_uid(r, ctx, conf) != NGX_OK) {
        !           369:         return NGX_ERROR;
        !           370:     }
        !           371: 
        !           372:     if (ctx->uid_set[3] == 0) {
        !           373:         return NGX_OK;
        !           374:     }
        !           375: 
        !           376:     len = conf->name.len + 1 + ngx_base64_encoded_length(16) + conf->path.len;
        !           377: 
        !           378:     if (conf->expires) {
        !           379:         len += sizeof(expires) - 1 + 2;
        !           380:     }
        !           381: 
        !           382:     if (conf->domain.len) {
        !           383:         len += conf->domain.len;
        !           384:     }
        !           385: 
        !           386:     cookie = ngx_pnalloc(r->pool, len);
        !           387:     if (cookie == NULL) {
        !           388:         return NGX_ERROR;
        !           389:     }
        !           390: 
        !           391:     p = ngx_copy(cookie, conf->name.data, conf->name.len);
        !           392:     *p++ = '=';
        !           393: 
        !           394:     if (ctx->uid_got[3] == 0 || ctx->reset) {
        !           395:         src.len = 16;
        !           396:         src.data = (u_char *) ctx->uid_set;
        !           397:         dst.data = p;
        !           398: 
        !           399:         ngx_encode_base64(&dst, &src);
        !           400: 
        !           401:         p += dst.len;
        !           402: 
        !           403:         if (conf->mark) {
        !           404:             *(p - 2) = conf->mark;
        !           405:         }
        !           406: 
        !           407:     } else {
        !           408:         p = ngx_cpymem(p, ctx->cookie.data, 22);
        !           409:         *p++ = conf->mark;
        !           410:         *p++ = '=';
        !           411:     }
        !           412: 
        !           413:     if (conf->expires == NGX_HTTP_USERID_MAX_EXPIRES) {
        !           414:         p = ngx_cpymem(p, expires, sizeof(expires) - 1);
        !           415: 
        !           416:     } else if (conf->expires) {
        !           417:         p = ngx_cpymem(p, expires, sizeof("; expires=") - 1);
        !           418:         p = ngx_http_cookie_time(p, ngx_time() + conf->expires);
        !           419:     }
        !           420: 
        !           421:     p = ngx_copy(p, conf->domain.data, conf->domain.len);
        !           422: 
        !           423:     p = ngx_copy(p, conf->path.data, conf->path.len);
        !           424: 
        !           425:     set_cookie = ngx_list_push(&r->headers_out.headers);
        !           426:     if (set_cookie == NULL) {
        !           427:         return NGX_ERROR;
        !           428:     }
        !           429: 
        !           430:     set_cookie->hash = 1;
        !           431:     ngx_str_set(&set_cookie->key, "Set-Cookie");
        !           432:     set_cookie->value.len = p - cookie;
        !           433:     set_cookie->value.data = cookie;
        !           434: 
        !           435:     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !           436:                    "uid cookie: \"%V\"", &set_cookie->value);
        !           437: 
        !           438:     if (conf->p3p.len == 0) {
        !           439:         return NGX_OK;
        !           440:     }
        !           441: 
        !           442:     p3p = ngx_list_push(&r->headers_out.headers);
        !           443:     if (p3p == NULL) {
        !           444:         return NGX_ERROR;
        !           445:     }
        !           446: 
        !           447:     p3p->hash = 1;
        !           448:     ngx_str_set(&p3p->key, "P3P");
        !           449:     p3p->value = conf->p3p;
        !           450: 
        !           451:     return NGX_OK;
        !           452: }
        !           453: 
        !           454: 
        !           455: static ngx_int_t
        !           456: ngx_http_userid_create_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx,
        !           457:     ngx_http_userid_conf_t *conf)
        !           458: {
        !           459:     ngx_connection_t           *c;
        !           460:     struct sockaddr_in         *sin;
        !           461:     ngx_http_variable_value_t  *vv;
        !           462: #if (NGX_HAVE_INET6)
        !           463:     u_char                     *p;
        !           464:     struct sockaddr_in6        *sin6;
        !           465: #endif
        !           466: 
        !           467:     if (ctx->uid_set[3] != 0) {
        !           468:         return NGX_OK;
        !           469:     }
        !           470: 
        !           471:     if (ctx->uid_got[3] != 0) {
        !           472: 
        !           473:         vv = ngx_http_get_indexed_variable(r, ngx_http_userid_reset_index);
        !           474: 
        !           475:         if (vv->len == 0 || (vv->len == 1 && vv->data[0] == '0')) {
        !           476: 
        !           477:             if (conf->mark == '\0'
        !           478:                 || (ctx->cookie.len > 23
        !           479:                     && ctx->cookie.data[22] == conf->mark
        !           480:                     && ctx->cookie.data[23] == '='))
        !           481:             {
        !           482:                 return NGX_OK;
        !           483:             }
        !           484: 
        !           485:             ctx->uid_set[0] = ctx->uid_got[0];
        !           486:             ctx->uid_set[1] = ctx->uid_got[1];
        !           487:             ctx->uid_set[2] = ctx->uid_got[2];
        !           488:             ctx->uid_set[3] = ctx->uid_got[3];
        !           489: 
        !           490:             return NGX_OK;
        !           491: 
        !           492:         } else {
        !           493:             ctx->reset = 1;
        !           494: 
        !           495:             if (vv->len == 3 && ngx_strncmp(vv->data, "log", 3) == 0) {
        !           496:                 ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
        !           497:                         "userid cookie \"%V=%08XD%08XD%08XD%08XD\" was reset",
        !           498:                         &conf->name, ctx->uid_got[0], ctx->uid_got[1],
        !           499:                         ctx->uid_got[2], ctx->uid_got[3]);
        !           500:             }
        !           501:         }
        !           502:     }
        !           503: 
        !           504:     /*
        !           505:      * TODO: in the threaded mode the sequencers should be in TLS and their
        !           506:      * ranges should be divided between threads
        !           507:      */
        !           508: 
        !           509:     if (conf->enable == NGX_HTTP_USERID_V1) {
        !           510:         if (conf->service == NGX_CONF_UNSET) {
        !           511:             ctx->uid_set[0] = 0;
        !           512:         } else {
        !           513:             ctx->uid_set[0] = conf->service;
        !           514:         }
        !           515:         ctx->uid_set[1] = (uint32_t) ngx_time();
        !           516:         ctx->uid_set[2] = start_value;
        !           517:         ctx->uid_set[3] = sequencer_v1;
        !           518:         sequencer_v1 += 0x100;
        !           519: 
        !           520:     } else {
        !           521:         if (conf->service == NGX_CONF_UNSET) {
        !           522: 
        !           523:             c = r->connection;
        !           524: 
        !           525:             if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
        !           526:                 return NGX_ERROR;
        !           527:             }
        !           528: 
        !           529:             switch (c->local_sockaddr->sa_family) {
        !           530: 
        !           531: #if (NGX_HAVE_INET6)
        !           532:             case AF_INET6:
        !           533:                 sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
        !           534: 
        !           535:                 p = (u_char *) &ctx->uid_set[0];
        !           536: 
        !           537:                 *p++ = sin6->sin6_addr.s6_addr[12];
        !           538:                 *p++ = sin6->sin6_addr.s6_addr[13];
        !           539:                 *p++ = sin6->sin6_addr.s6_addr[14];
        !           540:                 *p = sin6->sin6_addr.s6_addr[15];
        !           541: 
        !           542:                 break;
        !           543: #endif
        !           544:             default: /* AF_INET */
        !           545:                 sin = (struct sockaddr_in *) c->local_sockaddr;
        !           546:                 ctx->uid_set[0] = sin->sin_addr.s_addr;
        !           547:                 break;
        !           548:             }
        !           549: 
        !           550:         } else {
        !           551:             ctx->uid_set[0] = htonl(conf->service);
        !           552:         }
        !           553: 
        !           554:         ctx->uid_set[1] = htonl((uint32_t) ngx_time());
        !           555:         ctx->uid_set[2] = htonl(start_value);
        !           556:         ctx->uid_set[3] = htonl(sequencer_v2);
        !           557:         sequencer_v2 += 0x100;
        !           558:         if (sequencer_v2 < 0x03030302) {
        !           559:             sequencer_v2 = 0x03030302;
        !           560:         }
        !           561:     }
        !           562: 
        !           563:     return NGX_OK;
        !           564: }
        !           565: 
        !           566: 
        !           567: static ngx_int_t
        !           568: ngx_http_userid_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
        !           569:     ngx_str_t *name, uint32_t *uid)
        !           570: {
        !           571:     v->len = name->len + sizeof("=00001111222233334444555566667777") - 1;
        !           572:     v->data = ngx_pnalloc(r->pool, v->len);
        !           573:     if (v->data == NULL) {
        !           574:         return NGX_ERROR;
        !           575:     }
        !           576: 
        !           577:     v->valid = 1;
        !           578:     v->no_cacheable = 0;
        !           579:     v->not_found = 0;
        !           580: 
        !           581:     ngx_sprintf(v->data, "%V=%08XD%08XD%08XD%08XD",
        !           582:                 name, uid[0], uid[1], uid[2], uid[3]);
        !           583: 
        !           584:     return NGX_OK;
        !           585: }
        !           586: 
        !           587: 
        !           588: static ngx_int_t
        !           589: ngx_http_userid_reset_variable(ngx_http_request_t *r,
        !           590:     ngx_http_variable_value_t *v, uintptr_t data)
        !           591: {
        !           592:     *v = ngx_http_variable_null_value;
        !           593: 
        !           594:     return NGX_OK;
        !           595: }
        !           596: 
        !           597: 
        !           598: static ngx_int_t
        !           599: ngx_http_userid_add_variables(ngx_conf_t *cf)
        !           600: {
        !           601:     ngx_int_t             n;
        !           602:     ngx_http_variable_t  *var;
        !           603: 
        !           604:     var = ngx_http_add_variable(cf, &ngx_http_userid_got, 0);
        !           605:     if (var == NULL) {
        !           606:         return NGX_ERROR;
        !           607:     }
        !           608: 
        !           609:     var->get_handler = ngx_http_userid_got_variable;
        !           610: 
        !           611:     var = ngx_http_add_variable(cf, &ngx_http_userid_set, 0);
        !           612:     if (var == NULL) {
        !           613:         return NGX_ERROR;
        !           614:     }
        !           615: 
        !           616:     var->get_handler = ngx_http_userid_set_variable;
        !           617: 
        !           618:     var = ngx_http_add_variable(cf, &ngx_http_userid_reset,
        !           619:                                 NGX_HTTP_VAR_CHANGEABLE);
        !           620:     if (var == NULL) {
        !           621:         return NGX_ERROR;
        !           622:     }
        !           623: 
        !           624:     var->get_handler = ngx_http_userid_reset_variable;
        !           625: 
        !           626:     n = ngx_http_get_variable_index(cf, &ngx_http_userid_reset);
        !           627:     if (n == NGX_ERROR) {
        !           628:         return NGX_ERROR;
        !           629:     }
        !           630: 
        !           631:     ngx_http_userid_reset_index = n;
        !           632: 
        !           633:     return NGX_OK;
        !           634: }
        !           635: 
        !           636: 
        !           637: static void *
        !           638: ngx_http_userid_create_conf(ngx_conf_t *cf)
        !           639: {
        !           640:     ngx_http_userid_conf_t  *conf;
        !           641: 
        !           642:     conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_userid_conf_t));
        !           643:     if (conf == NULL) {
        !           644:         return NULL;
        !           645:     }
        !           646: 
        !           647:     /*
        !           648:      * set by ngx_pcalloc():
        !           649:      *
        !           650:      *     conf->name = { 0, NULL };
        !           651:      *     conf->domain = { 0, NULL };
        !           652:      *     conf->path = { 0, NULL };
        !           653:      *     conf->p3p = { 0, NULL };
        !           654:      */
        !           655: 
        !           656:     conf->enable = NGX_CONF_UNSET_UINT;
        !           657:     conf->service = NGX_CONF_UNSET;
        !           658:     conf->expires = NGX_CONF_UNSET;
        !           659:     conf->mark = (u_char) '\xFF';
        !           660: 
        !           661:     return conf;
        !           662: }
        !           663: 
        !           664: 
        !           665: static char *
        !           666: ngx_http_userid_merge_conf(ngx_conf_t *cf, void *parent, void *child)
        !           667: {
        !           668:     ngx_http_userid_conf_t *prev = parent;
        !           669:     ngx_http_userid_conf_t *conf = child;
        !           670: 
        !           671:     ngx_conf_merge_uint_value(conf->enable, prev->enable,
        !           672:                               NGX_HTTP_USERID_OFF);
        !           673: 
        !           674:     ngx_conf_merge_str_value(conf->name, prev->name, "uid");
        !           675:     ngx_conf_merge_str_value(conf->domain, prev->domain, "");
        !           676:     ngx_conf_merge_str_value(conf->path, prev->path, "; path=/");
        !           677:     ngx_conf_merge_str_value(conf->p3p, prev->p3p, "");
        !           678: 
        !           679:     ngx_conf_merge_value(conf->service, prev->service, NGX_CONF_UNSET);
        !           680:     ngx_conf_merge_sec_value(conf->expires, prev->expires, 0);
        !           681: 
        !           682:     if (conf->mark == (u_char) '\xFF') {
        !           683:         if (prev->mark == (u_char) '\xFF') {
        !           684:             conf->mark = '\0';
        !           685:         } else {
        !           686:             conf->mark = prev->mark;
        !           687:         }
        !           688:     }
        !           689: 
        !           690:     return NGX_CONF_OK;
        !           691: }
        !           692: 
        !           693: 
        !           694: static ngx_int_t
        !           695: ngx_http_userid_init(ngx_conf_t *cf)
        !           696: {
        !           697:     ngx_http_next_header_filter = ngx_http_top_header_filter;
        !           698:     ngx_http_top_header_filter = ngx_http_userid_filter;
        !           699: 
        !           700:     return NGX_OK;
        !           701: }
        !           702: 
        !           703: 
        !           704: static char *
        !           705: ngx_http_userid_domain(ngx_conf_t *cf, void *post, void *data)
        !           706: {
        !           707:     ngx_str_t  *domain = data;
        !           708: 
        !           709:     u_char  *p, *new;
        !           710: 
        !           711:     if (ngx_strcmp(domain->data, "none") == 0) {
        !           712:         ngx_str_set(domain, "");
        !           713:         return NGX_CONF_OK;
        !           714:     }
        !           715: 
        !           716:     new = ngx_pnalloc(cf->pool, sizeof("; domain=") - 1 + domain->len);
        !           717:     if (new == NULL) {
        !           718:         return NGX_CONF_ERROR;
        !           719:     }
        !           720: 
        !           721:     p = ngx_cpymem(new, "; domain=", sizeof("; domain=") - 1);
        !           722:     ngx_memcpy(p, domain->data, domain->len);
        !           723: 
        !           724:     domain->len += sizeof("; domain=") - 1;
        !           725:     domain->data = new;
        !           726: 
        !           727:     return NGX_CONF_OK;
        !           728: }
        !           729: 
        !           730: 
        !           731: static char *
        !           732: ngx_http_userid_path(ngx_conf_t *cf, void *post, void *data)
        !           733: {
        !           734:     ngx_str_t  *path = data;
        !           735: 
        !           736:     u_char  *p, *new;
        !           737: 
        !           738:     new = ngx_pnalloc(cf->pool, sizeof("; path=") - 1 + path->len);
        !           739:     if (new == NULL) {
        !           740:         return NGX_CONF_ERROR;
        !           741:     }
        !           742: 
        !           743:     p = ngx_cpymem(new, "; path=", sizeof("; path=") - 1);
        !           744:     ngx_memcpy(p, path->data, path->len);
        !           745: 
        !           746:     path->len += sizeof("; path=") - 1;
        !           747:     path->data = new;
        !           748: 
        !           749:     return NGX_CONF_OK;
        !           750: }
        !           751: 
        !           752: 
        !           753: static char *
        !           754: ngx_http_userid_expires(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
        !           755: {
        !           756:     ngx_http_userid_conf_t *ucf = conf;
        !           757: 
        !           758:     ngx_str_t  *value;
        !           759: 
        !           760:     if (ucf->expires != NGX_CONF_UNSET) {
        !           761:         return "is duplicate";
        !           762:     }
        !           763: 
        !           764:     value = cf->args->elts;
        !           765: 
        !           766:     if (ngx_strcmp(value[1].data, "max") == 0) {
        !           767:         ucf->expires = NGX_HTTP_USERID_MAX_EXPIRES;
        !           768:         return NGX_CONF_OK;
        !           769:     }
        !           770: 
        !           771:     if (ngx_strcmp(value[1].data, "off") == 0) {
        !           772:         ucf->expires = 0;
        !           773:         return NGX_CONF_OK;
        !           774:     }
        !           775: 
        !           776:     ucf->expires = ngx_parse_time(&value[1], 1);
        !           777:     if (ucf->expires == (time_t) NGX_ERROR) {
        !           778:         return "invalid value";
        !           779:     }
        !           780: 
        !           781:     return NGX_CONF_OK;
        !           782: }
        !           783: 
        !           784: 
        !           785: static char *
        !           786: ngx_http_userid_p3p(ngx_conf_t *cf, void *post, void *data)
        !           787: {
        !           788:     ngx_str_t  *p3p = data;
        !           789: 
        !           790:     if (ngx_strcmp(p3p->data, "none") == 0) {
        !           791:         ngx_str_set(p3p, "");
        !           792:     }
        !           793: 
        !           794:     return NGX_CONF_OK;
        !           795: }
        !           796: 
        !           797: 
        !           798: static char *
        !           799: ngx_http_userid_mark(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
        !           800: {
        !           801:     ngx_http_userid_conf_t *ucf = conf;
        !           802: 
        !           803:     ngx_str_t  *value;
        !           804: 
        !           805:     if (ucf->mark != (u_char) '\xFF') {
        !           806:         return "is duplicate";
        !           807:     }
        !           808: 
        !           809:     value = cf->args->elts;
        !           810: 
        !           811:     if (ngx_strcmp(value[1].data, "off") == 0) {
        !           812:         ucf->mark = '\0';
        !           813:         return NGX_CONF_OK;
        !           814:     }
        !           815: 
        !           816:     if (value[1].len != 1
        !           817:         || !((value[1].data[0] >= '0' && value[1].data[0] <= '9')
        !           818:               || (value[1].data[0] >= 'A' && value[1].data[0] <= 'Z')
        !           819:               || (value[1].data[0] >= 'a' && value[1].data[0] <= 'z')
        !           820:               || value[1].data[0] == '='))
        !           821:     {
        !           822:         return "value must be \"off\" or a single letter, digit or \"=\"";
        !           823:     }
        !           824: 
        !           825:     ucf->mark = value[1].data[0];
        !           826: 
        !           827:     return NGX_CONF_OK;
        !           828: }
        !           829: 
        !           830: 
        !           831: static ngx_int_t
        !           832: ngx_http_userid_init_worker(ngx_cycle_t *cycle)
        !           833: {
        !           834:     struct timeval  tp;
        !           835: 
        !           836:     ngx_gettimeofday(&tp);
        !           837: 
        !           838:     /* use the most significant usec part that fits to 16 bits */
        !           839:     start_value = ((tp.tv_usec / 20) << 16) | ngx_pid;
        !           840: 
        !           841:     return NGX_OK;
        !           842: }

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