Mercurial > hg > nginx-vendor-current
comparison src/http/modules/ngx_http_userid_filter_module.c @ 376:edf1cb6c328e NGINX_0_7_0
nginx 0.7.0
*) Change: now the 0x00-0x1F, '"' and '\' characters are escaped as
\xXX in an access_log.
Thanks to Maxim Dounin.
*) Change: now nginx allows several "Host" request header line.
*) Feature: the "modified" flag in the "expires" directive.
*) Feature: the $uid_got and $uid_set variables may be used at any
request processing stage.
*) Feature: the $hostname variable.
Thanks to Andrei Nigmatulin.
*) Feature: DESTDIR support.
Thanks to Todd A. Fisher and Andras Voroskoi.
*) Bugfix: a segmentation fault might occur in worker process on Linux,
if keepalive was enabled.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Mon, 19 May 2008 00:00:00 +0400 |
parents | 54fad6c4b555 |
children | 984bb0b1399b |
comparison
equal
deleted
inserted
replaced
375:52f3c9c7eff0 | 376:edf1cb6c328e |
---|---|
39 uint32_t uid_set[4]; | 39 uint32_t uid_set[4]; |
40 ngx_str_t cookie; | 40 ngx_str_t cookie; |
41 } ngx_http_userid_ctx_t; | 41 } ngx_http_userid_ctx_t; |
42 | 42 |
43 | 43 |
44 static void ngx_http_userid_get_uid(ngx_http_request_t *r, | 44 static ngx_http_userid_ctx_t *ngx_http_userid_get_uid(ngx_http_request_t *r, |
45 ngx_http_userid_ctx_t *ctx, ngx_http_userid_conf_t *conf); | 45 ngx_http_userid_conf_t *conf); |
46 static ngx_int_t ngx_http_userid_variable(ngx_http_request_t *r, | |
47 ngx_http_variable_value_t *v, ngx_str_t *name, uint32_t *uid); | |
46 static ngx_int_t ngx_http_userid_set_uid(ngx_http_request_t *r, | 48 static ngx_int_t ngx_http_userid_set_uid(ngx_http_request_t *r, |
47 ngx_http_userid_ctx_t *ctx, ngx_http_userid_conf_t *conf); | 49 ngx_http_userid_ctx_t *ctx, ngx_http_userid_conf_t *conf); |
48 | 50 |
49 static ngx_int_t ngx_http_userid_add_variables(ngx_conf_t *cf); | 51 static ngx_int_t ngx_http_userid_add_variables(ngx_conf_t *cf); |
50 static ngx_int_t ngx_http_userid_variable(ngx_http_request_t *r, | |
51 ngx_http_variable_value_t *v, uintptr_t data); | |
52 | |
53 static ngx_int_t ngx_http_userid_init(ngx_conf_t *cf); | 52 static ngx_int_t ngx_http_userid_init(ngx_conf_t *cf); |
54 static void *ngx_http_userid_create_conf(ngx_conf_t *cf); | 53 static void *ngx_http_userid_create_conf(ngx_conf_t *cf); |
55 static char *ngx_http_userid_merge_conf(ngx_conf_t *cf, void *parent, | 54 static char *ngx_http_userid_merge_conf(ngx_conf_t *cf, void *parent, |
56 void *child); | 55 void *child); |
57 static char *ngx_http_userid_domain(ngx_conf_t *cf, void *post, void *data); | 56 static char *ngx_http_userid_domain(ngx_conf_t *cf, void *post, void *data); |
189 | 188 |
190 | 189 |
191 static ngx_int_t | 190 static ngx_int_t |
192 ngx_http_userid_filter(ngx_http_request_t *r) | 191 ngx_http_userid_filter(ngx_http_request_t *r) |
193 { | 192 { |
194 ngx_int_t rc; | |
195 ngx_http_userid_ctx_t *ctx; | 193 ngx_http_userid_ctx_t *ctx; |
196 ngx_http_userid_conf_t *conf; | 194 ngx_http_userid_conf_t *conf; |
197 | 195 |
198 if (r != r->main) { | 196 if (r != r->main) { |
199 return ngx_http_next_header_filter(r); | 197 return ngx_http_next_header_filter(r); |
200 } | 198 } |
201 | 199 |
202 conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_filter_module); | 200 conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_filter_module); |
203 | 201 |
204 if (conf->enable == NGX_HTTP_USERID_OFF) { | 202 if (conf->enable <= NGX_HTTP_USERID_LOG) { |
205 return ngx_http_next_header_filter(r); | 203 return ngx_http_next_header_filter(r); |
206 } | 204 } |
207 | 205 |
208 | 206 ctx = ngx_http_userid_get_uid(r, conf); |
209 ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_userid_ctx_t)); | 207 |
210 if (ctx == NULL) { | 208 if (ctx == NULL) { |
211 return NGX_ERROR; | 209 return NGX_ERROR; |
212 } | 210 } |
213 | 211 |
214 ngx_http_set_ctx(r, ctx, ngx_http_userid_filter_module); | |
215 | |
216 ngx_http_userid_get_uid(r, ctx, conf); | |
217 | |
218 if (conf->enable == NGX_HTTP_USERID_LOG) { | |
219 return ngx_http_next_header_filter(r); | |
220 } | |
221 | |
222 if (ctx->uid_got[3] != 0) { | 212 if (ctx->uid_got[3] != 0) { |
213 | |
223 if (conf->mark == '\0') { | 214 if (conf->mark == '\0') { |
224 return ngx_http_next_header_filter(r); | 215 return ngx_http_next_header_filter(r); |
225 | 216 |
226 } else { | 217 } else { |
227 if (ctx->cookie.len > 23 | 218 if (ctx->cookie.len > 23 |
231 return ngx_http_next_header_filter(r); | 222 return ngx_http_next_header_filter(r); |
232 } | 223 } |
233 } | 224 } |
234 } | 225 } |
235 | 226 |
236 rc = ngx_http_userid_set_uid(r, ctx, conf); | 227 /* ctx->status == NGX_DECLINED */ |
237 | 228 |
238 if (rc != NGX_OK) { | 229 if (ngx_http_userid_set_uid(r, ctx, conf) == NGX_OK) { |
239 return rc; | 230 return ngx_http_next_header_filter(r); |
240 } | 231 } |
241 | 232 |
242 return ngx_http_next_header_filter(r); | 233 return NGX_ERROR; |
243 } | 234 } |
244 | 235 |
245 | 236 |
246 static void | 237 static ngx_int_t |
247 ngx_http_userid_get_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx, | 238 ngx_http_userid_got_variable(ngx_http_request_t *r, |
248 ngx_http_userid_conf_t *conf) | 239 ngx_http_variable_value_t *v, uintptr_t data) |
249 { | 240 { |
250 ngx_int_t n; | 241 ngx_http_userid_ctx_t *ctx; |
251 ngx_str_t src, dst; | 242 ngx_http_userid_conf_t *conf; |
252 ngx_table_elt_t **cookies; | 243 |
244 conf = ngx_http_get_module_loc_conf(r->main, ngx_http_userid_filter_module); | |
245 | |
246 if (conf->enable == NGX_HTTP_USERID_OFF) { | |
247 v->not_found = 1; | |
248 return NGX_OK; | |
249 } | |
250 | |
251 ctx = ngx_http_userid_get_uid(r, conf); | |
252 | |
253 if (ctx == NULL) { | |
254 return NGX_ERROR; | |
255 } | |
256 | |
257 if (ctx->uid_got[3] != 0) { | |
258 return ngx_http_userid_variable(r, v, &conf->name, ctx->uid_got); | |
259 } | |
260 | |
261 /* ctx->status == NGX_DECLINED */ | |
262 | |
263 v->not_found = 1; | |
264 | |
265 return NGX_OK; | |
266 } | |
267 | |
268 | |
269 static ngx_int_t | |
270 ngx_http_userid_set_variable(ngx_http_request_t *r, | |
271 ngx_http_variable_value_t *v, uintptr_t data) | |
272 { | |
273 ngx_http_userid_ctx_t *ctx; | |
274 ngx_http_userid_conf_t *conf; | |
275 | |
276 ctx = ngx_http_get_module_ctx(r, ngx_http_userid_filter_module); | |
277 | |
278 if (ctx == NULL || ctx->uid_set[3] == 0) { | |
279 v->not_found = 1; | |
280 return NGX_OK; | |
281 } | |
282 | |
283 conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_filter_module); | |
284 | |
285 return ngx_http_userid_variable(r, 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 } | |
253 | 311 |
254 n = ngx_http_parse_multi_header_lines(&r->headers_in.cookies, &conf->name, | 312 n = ngx_http_parse_multi_header_lines(&r->headers_in.cookies, &conf->name, |
255 &ctx->cookie); | 313 &ctx->cookie); |
256 if (n == NGX_DECLINED) { | 314 if (n == NGX_DECLINED) { |
257 return; | 315 return ctx; |
258 } | 316 } |
259 | 317 |
260 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 318 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
261 "uid cookie: \"%V\"", &ctx->cookie); | 319 "uid cookie: \"%V\"", &ctx->cookie); |
262 | 320 |
263 if (ctx->cookie.len < 22) { | 321 if (ctx->cookie.len < 22) { |
264 cookies = r->headers_in.cookies.elts; | 322 cookies = r->headers_in.cookies.elts; |
265 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | 323 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
266 "client sent too short userid cookie \"%V\"", | 324 "client sent too short userid cookie \"%V\"", |
267 &cookies[n]->value); | 325 &cookies[n]->value); |
268 return; | 326 return ctx; |
269 } | 327 } |
270 | 328 |
271 src = ctx->cookie; | 329 src = ctx->cookie; |
272 | 330 |
273 /* | 331 /* |
284 if (ngx_decode_base64(&dst, &src) == NGX_ERROR) { | 342 if (ngx_decode_base64(&dst, &src) == NGX_ERROR) { |
285 cookies = r->headers_in.cookies.elts; | 343 cookies = r->headers_in.cookies.elts; |
286 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | 344 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
287 "client sent invalid userid cookie \"%V\"", | 345 "client sent invalid userid cookie \"%V\"", |
288 &cookies[n]->value); | 346 &cookies[n]->value); |
289 return; | 347 return ctx; |
290 } | 348 } |
291 | 349 |
292 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 350 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
293 "uid: %08XD%08XD%08XD%08XD", | 351 "uid: %08XD%08XD%08XD%08XD", |
294 ctx->uid_got[0], ctx->uid_got[1], | 352 ctx->uid_got[0], ctx->uid_got[1], |
295 ctx->uid_got[2], ctx->uid_got[3]); | 353 ctx->uid_got[2], ctx->uid_got[3]); |
354 | |
355 return ctx; | |
296 } | 356 } |
297 | 357 |
298 | 358 |
299 static ngx_int_t | 359 static ngx_int_t |
300 ngx_http_userid_set_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx, | 360 ngx_http_userid_set_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx, |
302 { | 362 { |
303 u_char *cookie, *p; | 363 u_char *cookie, *p; |
304 size_t len; | 364 size_t len; |
305 ngx_str_t src, dst; | 365 ngx_str_t src, dst; |
306 ngx_table_elt_t *set_cookie, *p3p; | 366 ngx_table_elt_t *set_cookie, *p3p; |
307 | |
308 /* | 367 /* |
309 * TODO: in the threaded mode the sequencers should be in TLS and their | 368 * TODO: in the threaded mode the sequencers should be in TLS and their |
310 * ranges should be divided between threads | 369 * ranges should be divided between threads |
311 */ | 370 */ |
312 | 371 |
431 return NGX_OK; | 490 return NGX_OK; |
432 } | 491 } |
433 | 492 |
434 | 493 |
435 static ngx_int_t | 494 static ngx_int_t |
495 ngx_http_userid_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, | |
496 ngx_str_t *name, uint32_t *uid) | |
497 { | |
498 v->len = name->len + sizeof("=00001111222233334444555566667777") - 1; | |
499 v->data = ngx_palloc(r->pool, v->len); | |
500 if (v->data == NULL) { | |
501 return NGX_ERROR; | |
502 } | |
503 | |
504 v->valid = 1; | |
505 v->no_cacheable = 0; | |
506 v->not_found = 0; | |
507 | |
508 ngx_sprintf(v->data, "%V=%08XD%08XD%08XD%08XD", | |
509 name, uid[0], uid[1], uid[2], uid[3]); | |
510 | |
511 return NGX_OK; | |
512 } | |
513 | |
514 | |
515 static ngx_int_t | |
436 ngx_http_userid_add_variables(ngx_conf_t *cf) | 516 ngx_http_userid_add_variables(ngx_conf_t *cf) |
437 { | 517 { |
438 ngx_http_variable_t *var; | 518 ngx_http_variable_t *var; |
439 | 519 |
440 var = ngx_http_add_variable(cf, &ngx_http_userid_got, NGX_HTTP_VAR_NOHASH); | 520 var = ngx_http_add_variable(cf, &ngx_http_userid_got, NGX_HTTP_VAR_NOHASH); |
441 if (var == NULL) { | 521 if (var == NULL) { |
442 return NGX_ERROR; | 522 return NGX_ERROR; |
443 } | 523 } |
444 | 524 |
445 var->get_handler = ngx_http_userid_variable; | 525 var->get_handler = ngx_http_userid_got_variable; |
446 var->data = offsetof(ngx_http_userid_ctx_t, uid_got); | |
447 | 526 |
448 var = ngx_http_add_variable(cf, &ngx_http_userid_set, NGX_HTTP_VAR_NOHASH); | 527 var = ngx_http_add_variable(cf, &ngx_http_userid_set, NGX_HTTP_VAR_NOHASH); |
449 if (var == NULL) { | 528 if (var == NULL) { |
450 return NGX_ERROR; | 529 return NGX_ERROR; |
451 } | 530 } |
452 | 531 |
453 var->get_handler = ngx_http_userid_variable; | 532 var->get_handler = ngx_http_userid_set_variable; |
454 var->data = offsetof(ngx_http_userid_ctx_t, uid_set); | |
455 | |
456 return NGX_OK; | |
457 } | |
458 | |
459 | |
460 static ngx_int_t | |
461 ngx_http_userid_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, | |
462 uintptr_t data) | |
463 { | |
464 uint32_t *uid; | |
465 ngx_http_userid_ctx_t *ctx; | |
466 ngx_http_userid_conf_t *conf; | |
467 | |
468 ctx = ngx_http_get_module_ctx(r, ngx_http_userid_filter_module); | |
469 | |
470 uid = (uint32_t *) ((char *) ctx + data); | |
471 | |
472 if (ctx == NULL || uid[3] == 0) { | |
473 v->not_found = 1; | |
474 return NGX_OK; | |
475 } | |
476 | |
477 conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_filter_module); | |
478 | |
479 v->len = conf->name.len + sizeof("=00001111222233334444555566667777") - 1; | |
480 v->data = ngx_palloc(r->pool, v->len); | |
481 if (v->data == NULL) { | |
482 return NGX_ERROR; | |
483 } | |
484 | |
485 v->valid = 1; | |
486 v->no_cacheable = 0; | |
487 v->not_found = 0; | |
488 | |
489 ngx_sprintf(v->data, "%V=%08XD%08XD%08XD%08XD", | |
490 &conf->name, uid[0], uid[1], uid[2], uid[3]); | |
491 | 533 |
492 return NGX_OK; | 534 return NGX_OK; |
493 } | 535 } |
494 | 536 |
495 | 537 |