Mercurial > hg > nginx-vendor-current
diff src/http/modules/ngx_http_userid_filter_module.c @ 88:e916a291e9aa NGINX_0_1_44
nginx 0.1.44
*) Feature: the IMAP/POP3 proxy supports SSL.
*) Feature: the "proxy_timeout" directive of the ngx_imap_proxy_module.
*) Feature: the "userid_mark" directive.
*) Feature: the $remote_user variable value is determined independently
of authorization use.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Tue, 06 Sep 2005 00:00:00 +0400 |
parents | b55cbf18157e |
children | 71c46860eb55 |
line wrap: on
line diff
--- a/src/http/modules/ngx_http_userid_filter_module.c +++ b/src/http/modules/ngx_http_userid_filter_module.c @@ -26,18 +26,22 @@ typedef struct { ngx_str_t name; ngx_str_t domain; ngx_str_t path; + ngx_str_t p3p; + time_t expires; - ngx_str_t p3p; + + u_char mark; } ngx_http_userid_conf_t; typedef struct { uint32_t uid_got[4]; uint32_t uid_set[4]; + ngx_str_t cookie; } ngx_http_userid_ctx_t; -static ngx_int_t ngx_http_userid_get_uid(ngx_http_request_t *r, +static void ngx_http_userid_get_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx, ngx_http_userid_conf_t *conf); static ngx_int_t ngx_http_userid_set_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx, ngx_http_userid_conf_t *conf); @@ -61,6 +65,9 @@ static char *ngx_http_userid_path(ngx_co static char *ngx_http_userid_expires(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_http_userid_p3p(ngx_conf_t *cf, void *post, void *data); +static char *ngx_http_userid_mark(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); + static uint32_t sequencer_v1 = 1; @@ -84,7 +91,6 @@ static ngx_conf_enum_t ngx_http_userid_ static ngx_conf_post_handler_pt ngx_http_userid_domain_p = ngx_http_userid_domain; - static ngx_conf_post_handler_pt ngx_http_userid_path_p = ngx_http_userid_path; static ngx_conf_post_handler_pt ngx_http_userid_p3p_p = ngx_http_userid_p3p; @@ -99,28 +105,28 @@ static ngx_command_t ngx_http_userid_co ngx_http_userid_state }, { ngx_string("userid_service"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, 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_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, 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_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_str_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_userid_conf_t, domain), &ngx_http_userid_domain_p }, { ngx_string("userid_path"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_str_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_userid_conf_t, path), @@ -140,6 +146,13 @@ static ngx_command_t ngx_http_userid_co offsetof(ngx_http_userid_conf_t, p3p), &ngx_http_userid_p3p_p }, + { ngx_string("userid_mark"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_http_userid_mark, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, + ngx_null_command }; @@ -205,15 +218,24 @@ ngx_http_userid_filter(ngx_http_request_ ngx_http_set_ctx(r, ctx, ngx_http_userid_filter_module); - - rc = ngx_http_userid_get_uid(r, ctx, conf); + ngx_http_userid_get_uid(r, ctx, conf); - if (rc != NGX_OK) { - return rc; + if (conf->enable == NGX_HTTP_USERID_LOG) { + return ngx_http_next_header_filter(r); } - if (conf->enable == NGX_HTTP_USERID_LOG || ctx->uid_got[3] != 0) { - return ngx_http_next_header_filter(r); + if (ctx->uid_got[3] != 0) { + if (conf->mark == '\0') { + return ngx_http_next_header_filter(r); + + } else { + if (ctx->cookie.len > 23 + && ctx->cookie.data[22] == conf->mark + && ctx->cookie.data[23] == '=') + { + return ngx_http_next_header_filter(r); + } + } } rc = ngx_http_userid_set_uid(r, ctx, conf); @@ -226,7 +248,7 @@ ngx_http_userid_filter(ngx_http_request_ } -static ngx_int_t +static void ngx_http_userid_get_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx, ngx_http_userid_conf_t *conf) { @@ -235,23 +257,29 @@ ngx_http_userid_get_uid(ngx_http_request ngx_table_elt_t **cookies; n = ngx_http_parse_multi_header_lines(&r->headers_in.cookies, &conf->name, - &src); + &ctx->cookie); if (n == NGX_DECLINED) { - return NGX_OK; + return; } - if (src.len < 22) { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "uid cookie: \"%V\"", &ctx->cookie); + + if (ctx->cookie.len < 22) { cookies = r->headers_in.cookies.elts; ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "client sent too short userid cookie \"%V\"", &cookies[n]->value); - return NGX_OK; + return; } + src = ctx->cookie; + /* - * 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 "==" + * we have to limit the encoded string to 22 characters because + * 1) cookie may be marked by "userid_mark", + * 2) and there are already the millions cookies with a garbage + * instead of the correct base64 trail "==" */ src.len = 22; @@ -263,15 +291,13 @@ ngx_http_userid_get_uid(ngx_http_request ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "client sent invalid userid cookie \"%V\"", &cookies[n]->value); - return NGX_OK; + return; } ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "uid: %08XD%08XD%08XD%08XD", ctx->uid_got[0], ctx->uid_got[1], ctx->uid_got[2], ctx->uid_got[3]); - - return NGX_OK; } @@ -286,47 +312,58 @@ ngx_http_userid_set_uid(ngx_http_request ngx_str_t src, dst; ngx_table_elt_t *set_cookie, *p3p; - /* TODO: mutex for sequencers */ + /* + * TODO: in the threaded mode the sequencers should be in TLS and their + * ranges should be divided between threads + */ + + if (ctx->uid_got[3] == 0) { - if (conf->enable == NGX_HTTP_USERID_V1) { - if (conf->service == NGX_CONF_UNSET) { - ctx->uid_set[0] = 0; + if (conf->enable == NGX_HTTP_USERID_V1) { + if (conf->service == NGX_CONF_UNSET) { + ctx->uid_set[0] = 0; + } else { + ctx->uid_set[0] = conf->service; + } + ctx->uid_set[1] = ngx_time(); + ctx->uid_set[2] = ngx_pid; + ctx->uid_set[3] = sequencer_v1; + sequencer_v1 += 0x100; + } else { - ctx->uid_set[0] = htonl(conf->service); - } + if (conf->service == NGX_CONF_UNSET) { + if (r->in_addr == 0) { + slen = sizeof(struct sockaddr_in); + if (getsockname(r->connection->fd, + (struct sockaddr *) &sin, &slen) == -1) + { + ngx_log_error(NGX_LOG_CRIT, r->connection->log, + ngx_socket_errno, "getsockname() failed"); + } + + r->in_addr = sin.sin_addr.s_addr; + } - ctx->uid_set[1] = ngx_time(); - ctx->uid_set[2] = ngx_pid; - ctx->uid_set[3] = sequencer_v1; - sequencer_v1 += 0x100; + ctx->uid_set[0] = htonl(r->in_addr); + + } else { + ctx->uid_set[0] = htonl(conf->service); + } + + ctx->uid_set[1] = htonl(ngx_time()); + ctx->uid_set[2] = htonl(ngx_pid); + ctx->uid_set[3] = htonl(sequencer_v2); + sequencer_v2 += 0x100; + if (sequencer_v2 < 0x03030302) { + sequencer_v2 = 0x03030302; + } + } } else { - if (conf->service == NGX_CONF_UNSET) { - if (r->in_addr == 0) { - slen = sizeof(struct sockaddr_in); - if (getsockname(r->connection->fd, - (struct sockaddr *) &sin, &slen) == -1) - { - ngx_log_error(NGX_LOG_CRIT, r->connection->log, - ngx_socket_errno, "getsockname() failed"); - } - - r->in_addr = sin.sin_addr.s_addr; - } - - ctx->uid_set[0] = htonl(r->in_addr); - - } else { - ctx->uid_set[0] = htonl(conf->service); - } - - ctx->uid_set[1] = htonl(ngx_time()); - ctx->uid_set[2] = htonl(ngx_pid); - ctx->uid_set[3] = htonl(sequencer_v2); - sequencer_v2 += 0x100; - if (sequencer_v2 < 0x03030302) { - sequencer_v2 = 0x03030302; - } + ctx->uid_set[0] = ctx->uid_got[0]; + ctx->uid_set[1] = ctx->uid_got[1]; + ctx->uid_set[2] = ctx->uid_got[2]; + ctx->uid_set[3] = ctx->uid_got[3]; } len = conf->name.len + 1 + ngx_base64_encoded_length(16) + conf->path.len; @@ -347,13 +384,24 @@ ngx_http_userid_set_uid(ngx_http_request p = ngx_cpymem(cookie, conf->name.data, conf->name.len); *p++ = '='; - src.len = 16; - src.data = (u_char *) ctx->uid_set; - dst.data = p; + if (ctx->uid_got[3] == 0) { + src.len = 16; + src.data = (u_char *) ctx->uid_set; + dst.data = p; + + ngx_encode_base64(&dst, &src); + + p += dst.len; - ngx_encode_base64(&dst, &src); + if (conf->mark) { + *(p - 2) = conf->mark; + } - p += dst.len; + } else { + p = ngx_cpymem(p, ctx->cookie.data, 22); + *p++ = conf->mark; + *p++ = '='; + } if (conf->expires == NGX_HTTP_USERID_MAX_EXPIRES) { p = ngx_cpymem(p, expires, sizeof(expires) - 1); @@ -545,6 +593,7 @@ ngx_http_userid_create_conf(ngx_conf_t * conf->enable = NGX_CONF_UNSET_UINT; conf->service = NGX_CONF_UNSET; conf->expires = NGX_CONF_UNSET; + conf->mark = (u_char) '\xFF'; return conf; } @@ -567,6 +616,14 @@ ngx_http_userid_merge_conf(ngx_conf_t *c ngx_conf_merge_value(conf->service, prev->service, NGX_CONF_UNSET); ngx_conf_merge_sec_value(conf->expires, prev->expires, 0); + if (conf->mark == (u_char) '\xFF') { + if (prev->mark == (u_char) '\xFF') { + conf->mark = '\0'; + } else { + conf->mark = prev->mark; + } + } + return NGX_CONF_OK; } @@ -627,7 +684,7 @@ ngx_http_userid_expires(ngx_conf_t *cf, { ngx_http_userid_conf_t *ucf = conf; - ngx_str_t *value; + ngx_str_t *value; if (ucf->expires != NGX_CONF_UNSET) { return "is duplicate"; @@ -670,3 +727,36 @@ ngx_http_userid_p3p(ngx_conf_t *cf, void return NGX_CONF_OK; } + + +static char * +ngx_http_userid_mark(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_http_userid_conf_t *ucf = conf; + + ngx_str_t *value; + + if (ucf->mark != (u_char) '\xFF') { + return "is duplicate"; + } + + value = cf->args->elts; + + if (ngx_strcmp(value[1].data, "off") == 0) { + ucf->mark = '\0'; + return NGX_CONF_OK; + } + + if (value[1].len != 1 + || !((value[1].data[0] >= '0' && value[1].data[0] <= '9') + || (value[1].data[0] >= 'A' && value[1].data[0] <= 'Z') + || (value[1].data[0] >= 'a' && value[1].data[0] <= 'z') + || value[1].data[0] == '=')) + { + return "value must be \"off\" or a single letter, digit or \"=\""; + } + + ucf->mark = value[1].data[0]; + + return NGX_CONF_OK; +}