From a7c4a2a6f898a0b3add9f36e56288734414a12f7 Mon Sep 17 00:00:00 2001 From: Igor Sysoev Date: Sun, 29 Aug 2004 03:55:41 +0000 Subject: nginx-0.0.10-2004-08-29-07:55:41 import --- auto/modules | 10 +- auto/options | 2 +- auto/sources | 8 +- src/core/nginx.c | 59 ---- src/core/ngx_string.c | 33 +- src/core/ngx_string.h | 8 +- src/core/ngx_times.c | 53 ++- src/core/ngx_times.h | 1 + src/http/modules/ngx_http_userid_filter.c | 506 +++++++++++++++++++++++++++++ src/http/modules/ngx_http_userid_handler.c | 421 ------------------------ src/http/ngx_http_log_handler.c | 15 + 11 files changed, 593 insertions(+), 523 deletions(-) create mode 100644 src/http/modules/ngx_http_userid_filter.c delete mode 100644 src/http/modules/ngx_http_userid_handler.c diff --git a/auto/modules b/auto/modules index a645070a1..be76fd83a 100644 --- a/auto/modules +++ b/auto/modules @@ -79,6 +79,11 @@ if [ $HTTP_SSI = YES ]; then HTTP_SRCS="$HTTP_SRCS $HTTP_SSI_SRCS" fi +if [ $HTTP_USERID = YES ]; then + HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_USERID_FILTER_MODULE" + HTTP_SRCS="$HTTP_SRCS $HTTP_USERID_SRCS" +fi + HTTP_MODULES="$HTTP_MODULES $HTTP_STATIC_MODULE $HTTP_INDEX_MODULE" if [ $HTTP_ACCESS = YES ]; then @@ -87,11 +92,6 @@ if [ $HTTP_ACCESS = YES ]; then HTTP_SRCS="$HTTP_SRCS $HTTP_ACCESS_SRCS" fi -if [ $HTTP_USERID = YES ]; then - HTTP_MODULES="$HTTP_MODULES $HTTP_USERID_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_USERID_SRCS" -fi - if [ $HTTP_STATUS = YES ]; then have=NGX_HTTP_STATUS . auto/have HTTP_MODULES="$HTTP_MODULES $HTTP_STATUS_MODULE" diff --git a/auto/options b/auto/options index f7c19904c..c88e77fc3 100644 --- a/auto/options +++ b/auto/options @@ -92,8 +92,8 @@ do --without-http_charset_module) HTTP_CHARSET=NO ;; --without-http_gzip_module) HTTP_GZIP=NO ;; --without-http_ssi_module) HTTP_SSI=NO ;; - --without-http_access_module) HTTP_ACCESS=NO ;; --without-http_userid_module) HTTP_USERID=NO ;; + --without-http_access_module) HTTP_ACCESS=NO ;; --without-http_status_module) HTTP_STATUS=NO ;; --without-http_rewrite_module) HTTP_REWRITE=NO ;; --without-http_proxy_module) HTTP_PROXY=NO ;; diff --git a/auto/sources b/auto/sources index 0f278c76d..8cbef9e42 100644 --- a/auto/sources +++ b/auto/sources @@ -257,12 +257,12 @@ HTTP_SSI_FILTER_MODULE=ngx_http_ssi_filter_module HTTP_SSI_SRCS=src/http/modules/ngx_http_ssi_filter.c -HTTP_ACCESS_MODULE=ngx_http_access_module -HTTP_ACCESS_SRCS=src/http/modules/ngx_http_access_handler.c +HTTP_USERID_FILTER_MODULE=ngx_http_userid_filter_module +HTTP_USERID_SRCS=src/http/modules/ngx_http_userid_filter.c -HTTP_USERID_MODULE=ngx_http_userid_module -HTTP_USERID_SRCS=src/http/modules/ngx_http_userid_handler.c +HTTP_ACCESS_MODULE=ngx_http_access_module +HTTP_ACCESS_SRCS=src/http/modules/ngx_http_access_handler.c HTTP_STATUS_MODULE=ngx_http_status_module diff --git a/src/core/nginx.c b/src/core/nginx.c index 17071c1c5..6d6103c0e 100644 --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -140,65 +140,6 @@ int main(int argc, char *const *argv) return 1; } -{ - ngx_str_t d, s; - - s.data = "12"; - s.len = sizeof("12") - 1; - - if (ngx_encode_base64(init_cycle.pool, &s, &d) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, log, 0, "ngx_encode_base64() failed"); - } else { - ngx_log_error(NGX_LOG_NOTICE, log, 0, "BASE64: %d:\"%s\"", d.len, d.data); - } - - s.data = "123"; - s.len = sizeof("123") - 1; - - if (ngx_encode_base64(init_cycle.pool, &s, &d) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, log, 0, "ngx_encode_base64() failed"); - } else { - ngx_log_error(NGX_LOG_NOTICE, log, 0, "BASE64: %d:\"%s\"", d.len, d.data); - } - - s.data = "1234"; - s.len = sizeof("1234") - 1; - - if (ngx_encode_base64(init_cycle.pool, &s, &d) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, log, 0, "ngx_encode_base64() failed"); - } else { - ngx_log_error(NGX_LOG_NOTICE, log, 0, "BASE64: %d:\"%s\"", d.len, d.data); - } - - s.data = "12345"; - s.len = sizeof("12345") - 1; - - if (ngx_encode_base64(init_cycle.pool, &s, &d) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, log, 0, "ngx_encode_base64() failed"); - } else { - ngx_log_error(NGX_LOG_NOTICE, log, 0, "BASE64: %d:\"%s\"", d.len, d.data); - } - - s.data = "123456"; - s.len = sizeof("123456") - 1; - - if (ngx_encode_base64(init_cycle.pool, &s, &d) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, log, 0, "ngx_encode_base64() failed"); - } else { - ngx_log_error(NGX_LOG_NOTICE, log, 0, "BASE64: %d:\"%s\"", d.len, d.data); - } - - s.data = "12345678901234567890"; - s.len = sizeof("12345678901234567890") - 1; - - if (ngx_encode_base64(init_cycle.pool, &s, &d) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, log, 0, "ngx_encode_base64() failed"); - } else { - ngx_log_error(NGX_LOG_NOTICE, log, 0, "BASE64: %d:\"%s\"", d.len, d.data); - } - -} - if (ngx_add_inherited_sockets(&init_cycle) == NGX_ERROR) { return 1; } diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c index 7231651c0..4cdb267dd 100644 --- a/src/core/ngx_string.c +++ b/src/core/ngx_string.c @@ -123,20 +123,16 @@ void ngx_md5_text(u_char *text, u_char *md5) } -ngx_int_t ngx_encode_base64(ngx_pool_t *pool, ngx_str_t *src, ngx_str_t *dst) +void ngx_encode_base64(ngx_str_t *src, ngx_str_t *dst) { u_char *d, *s; size_t len; static u_char basis64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - if (!(d = ngx_palloc(pool, ((src->len + 2) / 3) * 4 + 1))) { - return NGX_ERROR; - } - - dst->data = d; - s = src->data; len = src->len; + s = src->data; + d = dst->data; while (len > 2) { *d++ = basis64[(s[0] >> 2) & 0x3f]; @@ -164,13 +160,10 @@ ngx_int_t ngx_encode_base64(ngx_pool_t *pool, ngx_str_t *src, ngx_str_t *dst) } dst->len = d - dst->data; - *d++ = '\0'; - - return NGX_OK; } -ngx_int_t ngx_decode_base64(ngx_pool_t *pool, ngx_str_t *src, ngx_str_t *dst) +ngx_int_t ngx_decode_base64(ngx_str_t *src, ngx_str_t *dst) { size_t len; u_char *d, *s; @@ -207,33 +200,27 @@ ngx_int_t ngx_decode_base64(ngx_pool_t *pool, ngx_str_t *src, ngx_str_t *dst) return NGX_ERROR; } - if (!(d = ngx_palloc(pool, ((len + 3) / 4) * 3 + 1))) { - return NGX_ABORT; - } - - dst->data = d; - s = src->data; + d = dst->data; while (len > 3) { - *d++ = basis64[s[0]] << 2 | basis64[s[1]] >> 4; - *d++ = basis64[s[1]] << 4 | basis64[s[2]] >> 2; - *d++ = basis64[s[2]] << 6 | basis64[s[3]]; + *d++ = (u_char) (basis64[s[0]] << 2 | basis64[s[1]] >> 4); + *d++ = (u_char) (basis64[s[1]] << 4 | basis64[s[2]] >> 2); + *d++ = (u_char) (basis64[s[2]] << 6 | basis64[s[3]]); s += 4; len -= 4; } if (len > 1) { - *d++ = basis64[s[0]] << 2 | basis64[s[1]] >> 4; + *d++ = (u_char) (basis64[s[0]] << 2 | basis64[s[1]] >> 4); } if (len > 2) { - *d++ = basis64[s[1]] << 4 | basis64[s[2]] >> 2; + *d++ = (u_char) (basis64[s[1]] << 4 | basis64[s[2]] >> 2); } dst->len = d - dst->data; - *d++ = '\0'; return NGX_OK; } diff --git a/src/core/ngx_string.h b/src/core/ngx_string.h index 8a0212685..6b22a67ba 100644 --- a/src/core/ngx_string.h +++ b/src/core/ngx_string.h @@ -71,8 +71,12 @@ ngx_int_t ngx_hextoi(u_char *line, size_t n); void ngx_md5_text(u_char *text, u_char *md5); -ngx_int_t ngx_encode_base64(ngx_pool_t *pool, ngx_str_t *src, ngx_str_t *dst); -ngx_int_t ngx_decode_base64(ngx_pool_t *pool, ngx_str_t *src, ngx_str_t *dst); + +#define ngx_base64_encoded_length(len) (((len + 2) / 3) * 4) +#define ngx_base64_decoded_length(len) (((len + 3) / 4) * 3) + +void ngx_encode_base64(ngx_str_t *src, ngx_str_t *dst); +ngx_int_t ngx_decode_base64(ngx_str_t *src, ngx_str_t *dst); #define ngx_qsort qsort diff --git a/src/core/ngx_times.c b/src/core/ngx_times.c index df73a1dde..2c9985f20 100644 --- a/src/core/ngx_times.c +++ b/src/core/ngx_times.c @@ -214,14 +214,51 @@ size_t ngx_http_time(u_char *buf, time_t t) ngx_gmtime(t, &tm); return ngx_snprintf((char *) buf, sizeof("Mon, 28 Sep 1970 06:00:00 GMT"), - "%s, %02d %s %4d %02d:%02d:%02d GMT", - week[tm.ngx_tm_wday], - tm.ngx_tm_mday, - months[tm.ngx_tm_mon - 1], - tm.ngx_tm_year, - tm.ngx_tm_hour, - tm.ngx_tm_min, - tm.ngx_tm_sec); + "%s, %02d %s %4d %02d:%02d:%02d GMT", + week[tm.ngx_tm_wday], + tm.ngx_tm_mday, + months[tm.ngx_tm_mon - 1], + tm.ngx_tm_year, + tm.ngx_tm_hour, + tm.ngx_tm_min, + tm.ngx_tm_sec); +} + + +size_t ngx_http_cookie_time(u_char *buf, time_t t) +{ + ngx_tm_t tm; + + ngx_gmtime(t, &tm); + + /* + * Netscape 3.x does not understand 4-digit years at all and + * 2-digit years more than "37" + */ + + if (tm.ngx_tm_year > 2037) { + return ngx_snprintf((char *) buf, + sizeof("Mon, 28-Sep-1970 06:00:00 GMT"), + "%s, %02d-%s-%d %02d:%02d:%02d GMT", + week[tm.ngx_tm_wday], + tm.ngx_tm_mday, + months[tm.ngx_tm_mon - 1], + tm.ngx_tm_year, + tm.ngx_tm_hour, + tm.ngx_tm_min, + tm.ngx_tm_sec); + } else { + return ngx_snprintf((char *) buf, + sizeof("Mon, 28-Sep-70 06:00:00 GMT"), + "%s, %02d-%s-%02d %02d:%02d:%02d GMT", + week[tm.ngx_tm_wday], + tm.ngx_tm_mday, + months[tm.ngx_tm_mon - 1], + tm.ngx_tm_year % 100, + tm.ngx_tm_hour, + tm.ngx_tm_min, + tm.ngx_tm_sec); + } } diff --git a/src/core/ngx_times.h b/src/core/ngx_times.h index b5b6eb60a..426040577 100644 --- a/src/core/ngx_times.h +++ b/src/core/ngx_times.h @@ -9,6 +9,7 @@ void ngx_time_init(); void ngx_time_update(time_t s); size_t ngx_http_time(u_char *buf, time_t t); +size_t ngx_http_cookie_time(u_char *buf, time_t t); void ngx_gmtime(time_t t, ngx_tm_t *tp); #if (NGX_THREADS) diff --git a/src/http/modules/ngx_http_userid_filter.c b/src/http/modules/ngx_http_userid_filter.c new file mode 100644 index 000000000..9229a2b66 --- /dev/null +++ b/src/http/modules/ngx_http_userid_filter.c @@ -0,0 +1,506 @@ + +#include +#include +#include + + +#define NGX_HTTP_USERID_OFF 0 +#define NGX_HTTP_USERID_LOG 1 +#define NGX_HTTP_USERID_V1 2 +#define NGX_HTTP_USERID_ON 3 + +/* 31 Dec 2037 23:55:55 GMT */ +#define NGX_HTTP_USERID_MAX_EXPIRES 2145916555 + + +typedef struct { + ngx_flag_t enable; + + 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]; +} 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 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); + +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 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 uint32_t sequencer_v1 = 1; +static uint32_t sequencer_v2 = 0x03030302; + + +static u_char expires[] = "; expires=Thu, 31-Dec-37 23:55:55 GMT"; + + +static ngx_http_output_header_filter_pt ngx_http_next_header_filter; + + +static ngx_conf_enum_t ngx_http_userid_state[] = { + { ngx_string("off"), NGX_HTTP_USERID_OFF }, + { ngx_string("log"), NGX_HTTP_USERID_LOG }, + { ngx_string("v1"), NGX_HTTP_USERID_V1 }, + { ngx_string("on"), NGX_HTTP_USERID_ON }, + { 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_TAKE1, + ngx_conf_set_enum_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_userid_conf_t, enable), + ngx_http_userid_state}, + + { 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_TAKE1, + 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_filter_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_filter_module = { + NGX_MODULE, + &ngx_http_userid_filter_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_null_string, 0, NULL } +}; + + +static ngx_int_t ngx_http_userid_filter(ngx_http_request_t *r) +{ + ngx_int_t rc; + ngx_http_userid_ctx_t *ctx; + ngx_http_userid_conf_t *conf; + + conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_filter_module); + + if (conf->enable == NGX_HTTP_USERID_OFF) { + return ngx_http_next_header_filter(r); + } + + ngx_http_create_ctx(r, ctx, ngx_http_userid_filter_module, + sizeof(ngx_http_userid_ctx_t), + NGX_HTTP_INTERNAL_SERVER_ERROR); + + rc = ngx_http_userid_get_uid(r, ctx, conf); + + if (rc != NGX_OK) { + return rc; + } + + if (conf->enable == NGX_HTTP_USERID_LOG /* || ctx->uid_got[3] != 0 */) { + return NGX_OK; + } + + rc = ngx_http_userid_set_uid(r, ctx, conf); + + if (rc != NGX_OK) { + return rc; + } + + return ngx_http_next_header_filter(r); +} + + +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; + 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; + dst.data = (u_char *) ctx->uid_got; + + if (ngx_decode_base64(&src, &dst) == NGX_ERROR) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "client sent invalid userid cookie \"%s\"", + headers[cookies[i]].value.data); + break; + } + + ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "uid: %08X%08X%08X%08X", + ctx->uid_got[0], ctx->uid_got[1], + ctx->uid_got[2], ctx->uid_got[3]); + + return NGX_OK; + } + } + + return NGX_OK; +} + + +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) + +{ + u_char *cookie, *p; + size_t len; + ngx_str_t src, dst; + ngx_table_elt_t *set_cookie; + + /* TODO: mutex for sequencers */ + + if (conf->enable == NGX_HTTP_USERID_V1) { + 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); + 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; + } + } + + len = conf->name.len + 1 + ngx_base64_encoded_length(16) + 1; + + if (conf->expires) { + len += sizeof(expires) - 1 + 2; + } + + if (conf->domain.len > 1) { + len += sizeof("; domain=") - 1 + conf->domain.len; + } + + if (conf->path.len) { + len += sizeof("; path=") - 1 + conf->path.len; + } + + if (!(cookie = ngx_palloc(r->pool, len))) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + p = ngx_cpymem(cookie, conf->name.data, conf->name.len); + *p++ = '='; + + src.len = 16; + src.data = (u_char *) ctx->uid_set; + dst.data = p; + + ngx_encode_base64(&src, &dst); + + p += dst.len; + + if (conf->expires == NGX_HTTP_USERID_MAX_EXPIRES) { + p = ngx_cpymem(p, expires, sizeof(expires) - 1); + + } else if (conf->expires) { + p = ngx_cpymem(p, expires, sizeof("; expires=") - 1); + p += ngx_http_cookie_time(p, ngx_time() + conf->expires); + } + + if (conf->domain.len > 1) { + p = ngx_cpymem(p, "; domain=", sizeof("; domain=") - 1); + p = ngx_cpymem(p, conf->domain.data, conf->domain.len); + } + + if (conf->path.len) { + p = ngx_cpymem(p, "; path=", sizeof("; path=") - 1); + p = ngx_cpymem(p, conf->path.data, conf->path.len); + } + + *p = '\0'; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "uid cookie: \"%s\"", cookie); + + set_cookie = ngx_http_add_header(&r->headers_out, ngx_http_headers_out); + if (set_cookie == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + set_cookie->key.len = sizeof("Set-Cookie") - 1; + set_cookie->key.data = (u_char *) "Set-Cookie"; + set_cookie->value.len = p - cookie; + set_cookie->value.data = cookie; + + 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_filter_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_filter_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) +{ + ngx_http_userid_ctx_t *ctx; + ngx_http_userid_conf_t *conf; + + ctx = ngx_http_get_module_ctx(r, ngx_http_userid_filter_module); + + if (ctx == NULL || ctx->uid_set[3] == 0) { + if (buf == NULL) { + return (u_char *) 1; + } + + *buf = '-'; + return buf + 1; + } + + conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_filter_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_set[0], ctx->uid_set[1], + ctx->uid_set[2], ctx->uid_set[3]); +} + + +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->name.len = 0; + conf->name.date = NULL; + conf->domain.len = 0; + conf->domain.date = NULL; + conf->path.len = 0; + conf->path.date = NULL; + + */ + + conf->enable = NGX_CONF_UNSET; + conf->expires = NGX_CONF_UNSET; + + 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_value(conf->enable, prev->enable, 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, "/"); + + ngx_conf_merge_sec_value(conf->expires, prev->expires, 0); + + return NGX_CONF_OK; +} + + +static ngx_int_t ngx_http_userid_init(ngx_cycle_t *cycle) +{ + ngx_http_next_header_filter = ngx_http_top_header_filter; + ngx_http_top_header_filter = ngx_http_userid_filter; + + return NGX_OK; +} diff --git a/src/http/modules/ngx_http_userid_handler.c b/src/http/modules/ngx_http_userid_handler.c deleted file mode 100644 index f4bbb522b..000000000 --- a/src/http/modules/ngx_http_userid_handler.c +++ /dev/null @@ -1,421 +0,0 @@ - -#include -#include -#include - - -#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; -} diff --git a/src/http/ngx_http_log_handler.c b/src/http/ngx_http_log_handler.c index 4f63d0190..057da7815 100644 --- a/src/http/ngx_http_log_handler.c +++ b/src/http/ngx_http_log_handler.c @@ -13,6 +13,8 @@ static u_char *ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf, uintptr_t data); static u_char *ngx_http_log_time(ngx_http_request_t *r, u_char *buf, uintptr_t data); +static u_char *ngx_http_log_msec(ngx_http_request_t *r, u_char *buf, + uintptr_t data); static u_char *ngx_http_log_request(ngx_http_request_t *r, u_char *buf, uintptr_t data); static u_char *ngx_http_log_status(ngx_http_request_t *r, u_char *buf, @@ -106,6 +108,7 @@ ngx_http_log_op_name_t ngx_http_log_fmt_ops[] = { { ngx_string("pipe"), 1, ngx_http_log_pipe }, { ngx_string("time"), sizeof("28/Sep/1970:12:00:00") - 1, ngx_http_log_time }, + { ngx_string("msec"), TIME_T_LEN + 4, ngx_http_log_msec }, { ngx_string("request"), 0, ngx_http_log_request }, { ngx_string("status"), 3, ngx_http_log_status }, { ngx_string("length"), NGX_OFF_T_LEN, ngx_http_log_length }, @@ -225,6 +228,18 @@ static u_char *ngx_http_log_time(ngx_http_request_t *r, u_char *buf, } +static u_char *ngx_http_log_msec(ngx_http_request_t *r, u_char *buf, + uintptr_t data) +{ + struct timeval tv; + + ngx_gettimeofday(&tv); + + return buf + ngx_snprintf((char *) buf, TIME_T_LEN + 5, "%ld.%03ld", + tv.tv_sec, tv.tv_usec / 1000); +} + + static u_char *ngx_http_log_request(ngx_http_request_t *r, u_char *buf, uintptr_t data) { -- cgit v1.2.3