diff --git a/auto/modules b/auto/modules index ce6096791..a645070a1 100644 --- a/auto/modules +++ b/auto/modules @@ -87,6 +87,11 @@ 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 5aea141d6..f7c19904c 100644 --- a/auto/options +++ b/auto/options @@ -34,6 +34,7 @@ HTTP_GZIP=YES HTTP_SSL=NO HTTP_SSI=YES HTTP_ACCESS=YES +HTTP_USERID=YES HTTP_STATUS=YES HTTP_REWRITE=YES HTTP_PROXY=YES @@ -92,6 +93,7 @@ do --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_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 6b66e51b1..0f278c76d 100644 --- a/auto/sources +++ b/auto/sources @@ -261,6 +261,10 @@ HTTP_ACCESS_MODULE=ngx_http_access_module HTTP_ACCESS_SRCS=src/http/modules/ngx_http_access_handler.c +HTTP_USERID_MODULE=ngx_http_userid_module +HTTP_USERID_SRCS=src/http/modules/ngx_http_userid_handler.c + + HTTP_STATUS_MODULE=ngx_http_status_module HTTP_STATUS_SRCS=src/http/modules/ngx_http_status_handler.c diff --git a/src/core/nginx.c b/src/core/nginx.c index 6d6103c0e..17071c1c5 100644 --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -140,6 +140,65 @@ 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_conf_file.h b/src/core/ngx_conf_file.h index c09ee552b..7286dbf41 100644 --- a/src/core/ngx_conf_file.h +++ b/src/core/ngx_conf_file.h @@ -276,7 +276,6 @@ char *ngx_conf_set_num_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char *ngx_conf_set_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char *ngx_conf_set_msec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char *ngx_conf_set_sec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -char *ngx_conf_set_time_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char *ngx_conf_set_bufs_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char *ngx_conf_set_enum_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char *ngx_conf_set_bitmask_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); diff --git a/src/core/ngx_output_chain.c b/src/core/ngx_output_chain.c index db4321bc0..f177076de 100644 --- a/src/core/ngx_output_chain.c +++ b/src/core/ngx_output_chain.c @@ -275,6 +275,10 @@ ngx_int_t ngx_chain_writer(void *data, ngx_chain_t *in) for (/* void */; in; in = in->next) { + + ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->connection->log, 0, + "WRITER buf: %d", ngx_buf_size(in->buf)); + ngx_alloc_link_and_set_buf(cl, in->buf, ctx->pool, NGX_ERROR); *ctx->last = cl; ctx->last = &cl->next; diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c index f14040f3f..7231651c0 100644 --- a/src/core/ngx_string.c +++ b/src/core/ngx_string.c @@ -126,7 +126,7 @@ 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) { u_char *d, *s; - ngx_uint_t i; + size_t len; static u_char basis64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; @@ -136,24 +136,28 @@ ngx_int_t ngx_encode_base64(ngx_pool_t *pool, ngx_str_t *src, ngx_str_t *dst) dst->data = d; s = src->data; + len = src->len; - for (i = 0; i < src->len - 2; i += 3) { - *d++ = basis64[(s[i] >> 2) & 0x3f]; - *d++ = basis64[((s[i] & 3) << 4) | (s[i + 1] >> 4)]; - *d++ = basis64[((s[i + 1] & 0x0f) << 2) | (s[i + 2] >> 6)]; - *d++ = basis64[s[i + 2] & 0x3f]; + while (len > 2) { + *d++ = basis64[(s[0] >> 2) & 0x3f]; + *d++ = basis64[((s[0] & 3) << 4) | (s[1] >> 4)]; + *d++ = basis64[((s[1] & 0x0f) << 2) | (s[2] >> 6)]; + *d++ = basis64[s[2] & 0x3f]; + + s += 3; + len -= 3; } - if (i < src->len) { - *d++ = basis64[(s[i] >> 2) & 0x3f]; + if (len) { + *d++ = basis64[(s[0] >> 2) & 0x3f]; - if (i == src->len - 1) { - *d++ = basis64[(s[i] & 3) << 4]; + if (len == 1) { + *d++ = basis64[(s[0] & 3) << 4]; *d++ = '='; } else { - *d++ = basis64[((s[i] & 3) << 4) | (s[i + 1] >> 4)]; - *d++ = basis64[(s[i + 1] & 0x0f) << 2]; + *d++ = basis64[((s[0] & 3) << 4) | (s[1] >> 4)]; + *d++ = basis64[(s[1] & 0x0f) << 2]; } *d++ = '='; @@ -168,34 +172,69 @@ 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) { - u_char *d, *s, c; + size_t len; + u_char *d, *s; + static u_char basis64[] = + { 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 62, 77, 77, 77, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 77, 77, 77, 77, 77, 77, + 77, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 77, 77, 77, 77, 77, + 77, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 77, 77, 77, 77, 77, - if (!(d = ngx_palloc(pool, ((src->len + 3) / 4) * 3))) { + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77 }; + + for (len = 0; len < src->len; len++) { + if (src->data[len] == '=') { + break; + } + + if (basis64[src->data[len]] == 77) { + return NGX_ERROR; + } + } + + if (len % 4 == 1) { + return NGX_ERROR; + } + + if (!(d = ngx_palloc(pool, ((len + 3) / 4) * 3 + 1))) { return NGX_ABORT; } dst->data = d; + s = src->data; - if (*s == '+') { - c = 62; + 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]]; - } else if (*s == '/') { - c = 63; - - } else if (*s >= '0' && *s <= '9') { - c = *s - '0' + 52; - - } else if (*s >= 'A' && *s <= 'Z') { - c = *s - 'A'; - - } else if (*s >= 'a' && *s <= 'z') { - c = *s - 'a' + 26; - - } else { - return NGX_ERROR; + s += 4; + len -= 4; } + if (len > 1) { + *d++ = basis64[s[0]] << 2 | basis64[s[1]] >> 4; + } + + if (len > 2) { + *d++ = 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 d087e3e96..8a0212685 100644 --- a/src/core/ngx_string.h +++ b/src/core/ngx_string.h @@ -71,6 +71,9 @@ 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_qsort qsort diff --git a/src/http/modules/ngx_http_access_handler.c b/src/http/modules/ngx_http_access_handler.c index 6dd572931..086f2fc0e 100644 --- a/src/http/modules/ngx_http_access_handler.c +++ b/src/http/modules/ngx_http_access_handler.c @@ -68,7 +68,7 @@ ngx_module_t ngx_http_access_module = { ngx_http_access_commands, /* module directives */ NGX_HTTP_MODULE, /* module type */ ngx_http_access_init, /* init module */ - NULL /* init child */ + NULL /* init process */ }; diff --git a/src/http/modules/ngx_http_userid_handler.c b/src/http/modules/ngx_http_userid_handler.c new file mode 100644 index 000000000..f4bbb522b --- /dev/null +++ b/src/http/modules/ngx_http_userid_handler.c @@ -0,0 +1,421 @@ + +#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/modules/proxy/ngx_http_proxy_upstream.c b/src/http/modules/proxy/ngx_http_proxy_upstream.c index 3599f0abd..80759aebf 100644 --- a/src/http/modules/proxy/ngx_http_proxy_upstream.c +++ b/src/http/modules/proxy/ngx_http_proxy_upstream.c @@ -627,6 +627,8 @@ static void ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p) output->allocated = 1; r->request_body->buf->pos = r->request_body->buf->start; + r->request_body->buf->last = r->request_body->buf->start; + r->request_body->buf->tag = (ngx_buf_tag_t) &ngx_http_proxy_module; } p->request_sent = 0; diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c index 492ba6f8a..b8b246196 100644 --- a/src/http/ngx_http.c +++ b/src/http/ngx_http.c @@ -257,6 +257,11 @@ static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) *h = ngx_http_find_location_config; + ngx_init_array(cmcf->phases[NGX_HTTP_MISC_PHASE].handlers, + cf->cycle->pool, 10, sizeof(ngx_http_handler_pt), + NGX_CONF_ERROR); + cmcf->phases[NGX_HTTP_MISC_PHASE].type = NGX_DECLINED; + ngx_init_array(cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers, cf->cycle->pool, 10, sizeof(ngx_http_handler_pt), NGX_CONF_ERROR); diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h index 6c0e7a1b0..75bb6b3af 100644 --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -23,6 +23,7 @@ typedef enum { NGX_HTTP_FIND_CONFIG_PHASE, + NGX_HTTP_MISC_PHASE, NGX_HTTP_ACCESS_PHASE, NGX_HTTP_CONTENT_PHASE, diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index 95e6d5f2b..b05ea92ce 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -617,12 +617,28 @@ static void ngx_http_process_request_line(ngx_event_t *rev) return; } - /* r->headers_in.headers.elts = NULL; */ /* r->headers_in.headers.nelts = 0; */ r->headers_in.headers.size = sizeof(ngx_table_elt_t); r->headers_in.headers.nalloc = 20; r->headers_in.headers.pool = r->pool; + + /* init the r->headers_in.cookies array */ + + r->headers_in.cookies.elts = ngx_pcalloc(r->pool, + 5 * sizeof(ngx_uint_t)); + if (r->headers_in.cookies.elts == NULL) { + ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + ngx_http_close_connection(c); + return; + } + + /* r->headers_in.cookies.nelts = 0; */ + r->headers_in.cookies.size = sizeof(ngx_uint_t); + r->headers_in.cookies.nalloc = 5; + r->headers_in.cookies.pool = r->pool; + + ctx = c->log->data; ctx->action = "reading client request headers"; ctx->url = r->unparsed_uri.data; @@ -715,6 +731,7 @@ static void ngx_http_process_request_headers(ngx_event_t *rev) { ssize_t n; ngx_int_t rc, i, offset; + ngx_uint_t *cookie; ngx_table_elt_t *h; ngx_connection_t *c; ngx_http_request_t *r; @@ -783,17 +800,31 @@ static void ngx_http_process_request_headers(ngx_event_t *rev) h->value.data[h->value.len] = '\0'; } - for (i = 0; ngx_http_headers_in[i].name.len != 0; i++) { - if (ngx_http_headers_in[i].name.len != h->key.len) { - continue; + if (h->key.len == sizeof("Cookie") - 1 + && ngx_strcasecmp(h->key.data, "Cookie") == 0) + { + if (!(cookie = ngx_push_array(&r->headers_in.cookies))) { + ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + ngx_http_close_connection(c); + return; } - if (ngx_strcasecmp(ngx_http_headers_in[i].name.data, - h->key.data) == 0) - { - *((ngx_table_elt_t **) ((char *) &r->headers_in + *cookie = r->headers_in.headers.nelts - 1; + + } else { + + for (i = 0; ngx_http_headers_in[i].name.len != 0; i++) { + if (ngx_http_headers_in[i].name.len != h->key.len) { + continue; + } + + if (ngx_strcasecmp(ngx_http_headers_in[i].name.data, + h->key.data) == 0) + { + *((ngx_table_elt_t **) ((char *) &r->headers_in + ngx_http_headers_in[i].offset)) = h; - break; + break; + } } } diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h index d987c515a..470dcc16d 100644 --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -138,6 +138,8 @@ typedef struct { ngx_table_elt_t *x_forwarded_for; #endif + ngx_array_t cookies; + size_t host_name_len; ssize_t content_length_n; size_t connection_type;