Mercurial > hg > nginx
view src/http/modules/ngx_http_userid_handler.c @ 408:d6e2b445c1b8
nginx-0.0.10-2004-08-27-19:40:59 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Fri, 27 Aug 2004 15:40:59 +0000 |
parents | |
children |
line wrap: on
line source
#include <ngx_config.h> #include <ngx_core.h> #include <ngx_http.h> #define NGX_HTTP_USERID_OFF 0x0002 #define NGX_HTTP_USERID_ON 0x0004 #define NGX_HTTP_USERID_LOGONLY 0x0008 #define NGX_HTTP_USERID_TIME 0x0010 typedef struct { ngx_flag_t enable; ngx_int_t version; ngx_int_t service; ngx_str_t name; ngx_str_t domain; ngx_str_t path; time_t expires; ngx_int_t p3p; ngx_str_t p3p_string; } ngx_http_userid_conf_t; typedef struct { uint32_t uid_got[4]; uint32_t uid_set[4]; struct timeval tv; } ngx_http_userid_ctx_t; static ngx_int_t ngx_http_userid_get_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx, ngx_http_userid_conf_t *conf); static u_char *ngx_http_userid_log_uid_got(ngx_http_request_t *r, u_char *buf, uintptr_t data); static u_char *ngx_http_userid_log_uid_set(ngx_http_request_t *r, u_char *buf, uintptr_t data); static u_char *ngx_http_userid_log_uid_time(ngx_http_request_t *r, u_char *buf, uintptr_t data); static ngx_int_t ngx_http_userid_pre_conf(ngx_conf_t *cf); static void *ngx_http_userid_create_conf(ngx_conf_t *cf); static char *ngx_http_userid_merge_conf(ngx_conf_t *cf, void *parent, void *child); static ngx_int_t ngx_http_userid_init(ngx_cycle_t *cycle); static ngx_conf_enum_t ngx_http_userid_mask[] = { { ngx_string("off"), NGX_HTTP_USERID_OFF }, { ngx_string("on"), NGX_HTTP_USERID_ON }, { ngx_string("logonly"), NGX_HTTP_USERID_LOGONLY }, { ngx_string("time"), NGX_HTTP_USERID_TIME }, { ngx_null_string, 0 } }; static ngx_command_t ngx_http_userid_commands[] = { { ngx_string("userid"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_ANY, ngx_conf_set_bitmask_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_userid_conf_t, enable), ngx_http_userid_mask}, { ngx_string("userid_service"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, ngx_conf_set_num_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_userid_conf_t, service), NULL}, { ngx_string("userid_name"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, ngx_conf_set_str_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_userid_conf_t, name), NULL}, { ngx_string("userid_domain"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, ngx_conf_set_str_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_userid_conf_t, domain), NULL}, { ngx_string("userid_path"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, ngx_conf_set_str_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_userid_conf_t, path), NULL}, { ngx_string("userid_expires"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, ngx_conf_set_sec_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_userid_conf_t, expires), NULL}, ngx_null_command }; ngx_http_module_t ngx_http_userid_module_ctx = { ngx_http_userid_pre_conf, /* pre conf */ NULL, /* create main configuration */ NULL, /* init main configuration */ NULL, /* create server configuration */ NULL, /* merge server configuration */ ngx_http_userid_create_conf, /* create location configration */ ngx_http_userid_merge_conf /* merge location configration */ }; ngx_module_t ngx_http_userid_module = { NGX_MODULE, &ngx_http_userid_module_ctx, /* module context */ ngx_http_userid_commands, /* module directives */ NGX_HTTP_MODULE, /* module type */ ngx_http_userid_init, /* init module */ NULL /* init process */ }; static ngx_http_log_op_name_t ngx_http_userid_log_fmt_ops[] = { { ngx_string("uid_got"), 0, ngx_http_userid_log_uid_got }, { ngx_string("uid_set"), 0, ngx_http_userid_log_uid_set }, { ngx_string("uid_time"), TIME_T_LEN + 4, ngx_http_userid_log_uid_time }, { ngx_null_string, 0, NULL } }; static ngx_int_t ngx_http_userid_handler(ngx_http_request_t *r) { ngx_int_t rc; struct timeval tv; ngx_http_userid_ctx_t *ctx; ngx_http_userid_conf_t *conf; conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_module); if (conf->enable & NGX_HTTP_USERID_OFF) { return NGX_OK; } ctx = ngx_http_get_module_ctx(r, ngx_http_userid_module); if (ctx) { return NGX_OK; } ngx_http_create_ctx(r, ctx, ngx_http_userid_module, sizeof(ngx_http_userid_ctx_t), NGX_HTTP_INTERNAL_SERVER_ERROR); if (conf->enable & (NGX_HTTP_USERID_ON|NGX_HTTP_USERID_LOGONLY)) { rc = ngx_http_userid_get_uid(r, ctx, conf); if (rc != NGX_OK) { return rc; } } if (conf->enable & NGX_HTTP_USERID_TIME) { ngx_gettimeofday(&ctx->tv); } return NGX_OK; } static ngx_int_t ngx_http_userid_get_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx, ngx_http_userid_conf_t *conf) { u_char *start, *last, *end; uint32_t *uid; ngx_int_t rc; ngx_uint_t *cookies, i; ngx_str_t src, dst; ngx_table_elt_t *headers; headers = r->headers_in.headers.elts; cookies = r->headers_in.cookies.elts; for (i = 0; i < r->headers_in.cookies.nelts; i++) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "cookie: %d:\"%s\"", cookies[i], headers[cookies[i]].value.data); end = headers[cookies[i]].value.data + headers[cookies[i]].value.len; for (start = headers[cookies[i]].value.data; start < end; /* void */) { if (conf->name.len >= headers[cookies[i]].value.len || ngx_strncmp(start, conf->name.data, conf->name.len) != 0) { start += conf->name.len; while (start < end && *start++ != ';') { /* void */ } for (/* void */; start < end && *start == ' '; start++) { /**/ } continue; } for (start += conf->name.len; start < end && *start == ' '; start++) { /* void */ } if (*start != '=') { break; } for (start++; start < end && *start == ' '; start++) { /* void */ } for (last = start; last < end && *last != ';'; last++) { /**/ } if (last - start < 22) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "client sent too short userid cookie \"%s\"", headers[cookies[i]].value.data); break; } /* * we have to limit encoded string to 22 characters * because there are already the millions cookies with a garbage * instead of the correct base64 trail "==" */ src.len = 22; src.data = start; rc = ngx_decode_base64(r->pool, &src, &dst); if (rc == NGX_ABORT) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (rc == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "client sent invalid userid cookie \"%s\"", headers[cookies[i]].value.data); break; } uid = (uint32_t *) dst.data; ctx->uid_got[0] = uid[0]; ctx->uid_got[1] = uid[1]; ctx->uid_got[2] = uid[2]; ctx->uid_got[3] = uid[3]; ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "uid: %08X%08X%08X%08X", uid[0], uid[1], uid[2], uid[3]); return NGX_OK; } } return NGX_OK; } static u_char *ngx_http_userid_log_uid_got(ngx_http_request_t *r, u_char *buf, uintptr_t data) { ngx_http_userid_ctx_t *ctx; ngx_http_userid_conf_t *conf; ctx = ngx_http_get_module_ctx(r, ngx_http_userid_module); if (ctx == NULL || ctx->uid_got[3] == 0) { if (buf == NULL) { return (u_char *) 1; } *buf = '-'; return buf + 1; } conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_module); if (buf == NULL) { return (u_char *) (conf->name.len + 1 + 32); } buf = ngx_cpymem(buf, conf->name.data, conf->name.len); *buf++ = '='; return buf + ngx_snprintf((char *) buf, 33, "%08X%08X%08X%08X", ctx->uid_got[0], ctx->uid_got[1], ctx->uid_got[2], ctx->uid_got[3]); } static u_char *ngx_http_userid_log_uid_set(ngx_http_request_t *r, u_char *buf, uintptr_t data) { if (buf == NULL) { return (u_char *) 1; } *buf = '-'; return buf + 1; } static u_char *ngx_http_userid_log_uid_time(ngx_http_request_t *r, u_char *buf, uintptr_t data) { ngx_http_userid_ctx_t *ctx; ctx = ngx_http_get_module_ctx(r, ngx_http_userid_module); if (ctx == NULL || ctx->tv.tv_sec == 0) { *buf = '-'; return buf + 1; } return buf + ngx_snprintf((char *) buf, TIME_T_LEN + 5, "%ld.%03ld", ctx->tv.tv_sec, ctx->tv.tv_usec / 1000); } static ngx_int_t ngx_http_userid_pre_conf(ngx_conf_t *cf) { ngx_http_log_op_name_t *op; for (op = ngx_http_userid_log_fmt_ops; op->name.len; op++) { /* void */ } op->op = NULL; op = ngx_http_log_fmt_ops; for (op = ngx_http_log_fmt_ops; op->op; op++) { if (op->name.len == 0) { op = (ngx_http_log_op_name_t *) op->op; } } op->op = (ngx_http_log_op_pt) ngx_http_userid_log_fmt_ops; return NGX_OK; } static void *ngx_http_userid_create_conf(ngx_conf_t *cf) { ngx_http_userid_conf_t *conf; if (!(conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_userid_conf_t)))) { return NGX_CONF_ERROR; } /* set by ngx_pcalloc(): conf->enable = 0; conf->name.len = 0; conf->name.date = NULL; conf->domain.len = 0; conf->domain.date = NULL; conf->path.len = 0; conf->path.date = NULL; */ return conf; } static char *ngx_http_userid_merge_conf(ngx_conf_t *cf, void *parent, void *child) { ngx_http_userid_conf_t *prev = parent; ngx_http_userid_conf_t *conf = child; ngx_conf_merge_bitmask_value(conf->enable, prev->enable, (NGX_CONF_BITMASK_SET |NGX_HTTP_USERID_OFF)); ngx_conf_merge_str_value(conf->name, prev->name, "uid"); ngx_conf_merge_str_value(conf->domain, prev->domain, "."); ngx_conf_merge_str_value(conf->path, prev->path, "/"); return NGX_CONF_OK; } static ngx_int_t ngx_http_userid_init(ngx_cycle_t *cycle) { ngx_http_handler_pt *h; ngx_http_core_main_conf_t *cmcf; cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module); h = ngx_push_array(&cmcf->phases[NGX_HTTP_MISC_PHASE].handlers); if (h == NULL) { return NGX_ERROR; } *h = ngx_http_userid_handler; return NGX_OK; }