comparison src/http/modules/ngx_http_userid_filter_module.c @ 3648:67dc5dbbcca3

Now $uid_set may be used at any time, r2013 states the same is wrong. Besides, now $uid_set is not cacheable and may have two values: before and after header filter processing. This allows to log case, when uid cookie is remarked.
author Igor Sysoev <igor@sysoev.ru>
date Fri, 25 Jun 2010 12:16:31 +0000
parents ba0db579aeb6
children fd6f0f1a9055
comparison
equal deleted inserted replaced
3647:ba0db579aeb6 3648:67dc5dbbcca3
44 static ngx_http_userid_ctx_t *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_conf_t *conf); 45 ngx_http_userid_conf_t *conf);
46 static ngx_int_t ngx_http_userid_variable(ngx_http_request_t *r, 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); 47 ngx_http_variable_value_t *v, ngx_str_t *name, uint32_t *uid);
48 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,
49 ngx_http_userid_ctx_t *ctx, ngx_http_userid_conf_t *conf);
50 static ngx_int_t ngx_http_userid_create_uid(ngx_http_request_t *r,
49 ngx_http_userid_ctx_t *ctx, ngx_http_userid_conf_t *conf); 51 ngx_http_userid_ctx_t *ctx, ngx_http_userid_conf_t *conf);
50 52
51 static ngx_int_t ngx_http_userid_add_variables(ngx_conf_t *cf); 53 static ngx_int_t ngx_http_userid_add_variables(ngx_conf_t *cf);
52 static ngx_int_t ngx_http_userid_init(ngx_conf_t *cf); 54 static ngx_int_t ngx_http_userid_init(ngx_conf_t *cf);
53 static void *ngx_http_userid_create_conf(ngx_conf_t *cf); 55 static void *ngx_http_userid_create_conf(ngx_conf_t *cf);
267 ngx_http_variable_value_t *v, uintptr_t data) 269 ngx_http_variable_value_t *v, uintptr_t data)
268 { 270 {
269 ngx_http_userid_ctx_t *ctx; 271 ngx_http_userid_ctx_t *ctx;
270 ngx_http_userid_conf_t *conf; 272 ngx_http_userid_conf_t *conf;
271 273
272 ctx = ngx_http_get_module_ctx(r, ngx_http_userid_filter_module); 274 conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_filter_module);
273 275
274 if (ctx == NULL || ctx->uid_set[3] == 0) { 276 if (conf->enable < NGX_HTTP_USERID_V1) {
275 v->not_found = 1; 277 v->not_found = 1;
276 return NGX_OK; 278 return NGX_OK;
277 } 279 }
278 280
279 conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_filter_module); 281 ctx = ngx_http_userid_get_uid(r, conf);
282
283 if (ctx == NULL) {
284 return NGX_ERROR;
285 }
286
287 if (ctx->uid_set[3] == 0) {
288
289 if (ctx->uid_got[3] != 0) {
290 v->not_found = 1;
291 return NGX_OK;
292 }
293
294 if (ngx_http_userid_create_uid(r, ctx, conf) != NGX_OK) {
295 return NGX_ERROR;
296 }
297 }
280 298
281 return ngx_http_userid_variable(r, v, &conf->name, ctx->uid_set); 299 return ngx_http_userid_variable(r, v, &conf->name, ctx->uid_set);
282 } 300 }
283 301
284 302
354 372
355 static ngx_int_t 373 static ngx_int_t
356 ngx_http_userid_set_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx, 374 ngx_http_userid_set_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx,
357 ngx_http_userid_conf_t *conf) 375 ngx_http_userid_conf_t *conf)
358 { 376 {
359 u_char *cookie, *p; 377 u_char *cookie, *p;
360 size_t len; 378 size_t len;
361 ngx_str_t src, dst; 379 ngx_str_t src, dst;
362 ngx_table_elt_t *set_cookie, *p3p; 380 ngx_table_elt_t *set_cookie, *p3p;
381
382 if (ctx->uid_set[3] == 0) {
383 if (ctx->uid_got[3] == 0) {
384 if (ngx_http_userid_create_uid(r, ctx, conf) != NGX_OK) {
385 return NGX_ERROR;
386 }
387
388 } else {
389 ctx->uid_set[0] = ctx->uid_got[0];
390 ctx->uid_set[1] = ctx->uid_got[1];
391 ctx->uid_set[2] = ctx->uid_got[2];
392 ctx->uid_set[3] = ctx->uid_got[3];
393 }
394 }
395
396 len = conf->name.len + 1 + ngx_base64_encoded_length(16) + conf->path.len;
397
398 if (conf->expires) {
399 len += sizeof(expires) - 1 + 2;
400 }
401
402 if (conf->domain.len) {
403 len += conf->domain.len;
404 }
405
406 cookie = ngx_pnalloc(r->pool, len);
407 if (cookie == NULL) {
408 return NGX_ERROR;
409 }
410
411 p = ngx_copy(cookie, conf->name.data, conf->name.len);
412 *p++ = '=';
413
414 if (ctx->uid_got[3] == 0) {
415 src.len = 16;
416 src.data = (u_char *) ctx->uid_set;
417 dst.data = p;
418
419 ngx_encode_base64(&dst, &src);
420
421 p += dst.len;
422
423 if (conf->mark) {
424 *(p - 2) = conf->mark;
425 }
426
427 } else {
428 p = ngx_cpymem(p, ctx->cookie.data, 22);
429 *p++ = conf->mark;
430 *p++ = '=';
431 }
432
433 if (conf->expires == NGX_HTTP_USERID_MAX_EXPIRES) {
434 p = ngx_cpymem(p, expires, sizeof(expires) - 1);
435
436 } else if (conf->expires) {
437 p = ngx_cpymem(p, expires, sizeof("; expires=") - 1);
438 p = ngx_http_cookie_time(p, ngx_time() + conf->expires);
439 }
440
441 p = ngx_copy(p, conf->domain.data, conf->domain.len);
442
443 p = ngx_copy(p, conf->path.data, conf->path.len);
444
445 set_cookie = ngx_list_push(&r->headers_out.headers);
446 if (set_cookie == NULL) {
447 return NGX_ERROR;
448 }
449
450 set_cookie->hash = 1;
451 ngx_str_set(&set_cookie->key, "Set-Cookie");
452 set_cookie->value.len = p - cookie;
453 set_cookie->value.data = cookie;
454
455 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
456 "uid cookie: \"%V\"", &set_cookie->value);
457
458 if (conf->p3p.len == 0) {
459 return NGX_OK;
460 }
461
462 p3p = ngx_list_push(&r->headers_out.headers);
463 if (p3p == NULL) {
464 return NGX_ERROR;
465 }
466
467 p3p->hash = 1;
468 ngx_str_set(&p3p->key, "P3P");
469 p3p->value = conf->p3p;
470
471 return NGX_OK;
472 }
473
474
475 static ngx_int_t
476 ngx_http_userid_create_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx,
477 ngx_http_userid_conf_t *conf)
478 {
479 u_char *p;
363 ngx_connection_t *c; 480 ngx_connection_t *c;
364 struct sockaddr_in *sin; 481 struct sockaddr_in *sin;
365 #if (NGX_HAVE_INET6) 482 #if (NGX_HAVE_INET6)
366 struct sockaddr_in6 *sin6; 483 struct sockaddr_in6 *sin6;
367 #endif 484 #endif
369 /* 486 /*
370 * TODO: in the threaded mode the sequencers should be in TLS and their 487 * TODO: in the threaded mode the sequencers should be in TLS and their
371 * ranges should be divided between threads 488 * ranges should be divided between threads
372 */ 489 */
373 490
374 if (ctx->uid_got[3] == 0) { 491 if (conf->enable == NGX_HTTP_USERID_V1) {
375 492 if (conf->service == NGX_CONF_UNSET) {
376 if (conf->enable == NGX_HTTP_USERID_V1) { 493 ctx->uid_set[0] = 0;
377 if (conf->service == NGX_CONF_UNSET) { 494 } else {
378 ctx->uid_set[0] = 0; 495 ctx->uid_set[0] = conf->service;
379 } else { 496 }
380 ctx->uid_set[0] = conf->service; 497 ctx->uid_set[1] = (uint32_t) ngx_time();
498 ctx->uid_set[2] = start_value;
499 ctx->uid_set[3] = sequencer_v1;
500 sequencer_v1 += 0x100;
501
502 } else {
503 if (conf->service == NGX_CONF_UNSET) {
504
505 c = r->connection;
506
507 if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
508 return NGX_ERROR;
381 } 509 }
382 ctx->uid_set[1] = (uint32_t) ngx_time(); 510
383 ctx->uid_set[2] = start_value; 511 switch (c->local_sockaddr->sa_family) {
384 ctx->uid_set[3] = sequencer_v1; 512
385 sequencer_v1 += 0x100; 513 #if (NGX_HAVE_INET6)
514 case AF_INET6:
515 sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
516
517 p = (u_char *) &ctx->uid_set[0];
518
519 *p++ = sin6->sin6_addr.s6_addr[12];
520 *p++ = sin6->sin6_addr.s6_addr[13];
521 *p++ = sin6->sin6_addr.s6_addr[14];
522 *p = sin6->sin6_addr.s6_addr[15];
523
524 break;
525 #endif
526 default: /* AF_INET */
527 sin = (struct sockaddr_in *) c->local_sockaddr;
528 ctx->uid_set[0] = sin->sin_addr.s_addr;
529 break;
530 }
386 531
387 } else { 532 } else {
388 if (conf->service == NGX_CONF_UNSET) { 533 ctx->uid_set[0] = htonl(conf->service);
389 534 }
390 c = r->connection; 535
391 536 ctx->uid_set[1] = htonl((uint32_t) ngx_time());
392 if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) { 537 ctx->uid_set[2] = htonl(start_value);
393 return NGX_ERROR; 538 ctx->uid_set[3] = htonl(sequencer_v2);
394 } 539 sequencer_v2 += 0x100;
395 540 if (sequencer_v2 < 0x03030302) {
396 switch (c->local_sockaddr->sa_family) { 541 sequencer_v2 = 0x03030302;
397 542 }
398 #if (NGX_HAVE_INET6) 543 }
399 case AF_INET6:
400 sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
401
402 p = (u_char *) &ctx->uid_set[0];
403
404 *p++ = sin6->sin6_addr.s6_addr[12];
405 *p++ = sin6->sin6_addr.s6_addr[13];
406 *p++ = sin6->sin6_addr.s6_addr[14];
407 *p = sin6->sin6_addr.s6_addr[15];
408
409 break;
410 #endif
411 default: /* AF_INET */
412 sin = (struct sockaddr_in *) c->local_sockaddr;
413 ctx->uid_set[0] = sin->sin_addr.s_addr;
414 break;
415 }
416
417 } else {
418 ctx->uid_set[0] = htonl(conf->service);
419 }
420
421 ctx->uid_set[1] = htonl((uint32_t) ngx_time());
422 ctx->uid_set[2] = htonl(start_value);
423 ctx->uid_set[3] = htonl(sequencer_v2);
424 sequencer_v2 += 0x100;
425 if (sequencer_v2 < 0x03030302) {
426 sequencer_v2 = 0x03030302;
427 }
428 }
429
430 } else {
431 ctx->uid_set[0] = ctx->uid_got[0];
432 ctx->uid_set[1] = ctx->uid_got[1];
433 ctx->uid_set[2] = ctx->uid_got[2];
434 ctx->uid_set[3] = ctx->uid_got[3];
435 }
436
437 len = conf->name.len + 1 + ngx_base64_encoded_length(16) + conf->path.len;
438
439 if (conf->expires) {
440 len += sizeof(expires) - 1 + 2;
441 }
442
443 if (conf->domain.len) {
444 len += conf->domain.len;
445 }
446
447 cookie = ngx_pnalloc(r->pool, len);
448 if (cookie == NULL) {
449 return NGX_ERROR;
450 }
451
452 p = ngx_copy(cookie, conf->name.data, conf->name.len);
453 *p++ = '=';
454
455 if (ctx->uid_got[3] == 0) {
456 src.len = 16;
457 src.data = (u_char *) ctx->uid_set;
458 dst.data = p;
459
460 ngx_encode_base64(&dst, &src);
461
462 p += dst.len;
463
464 if (conf->mark) {
465 *(p - 2) = conf->mark;
466 }
467
468 } else {
469 p = ngx_cpymem(p, ctx->cookie.data, 22);
470 *p++ = conf->mark;
471 *p++ = '=';
472 }
473
474 if (conf->expires == NGX_HTTP_USERID_MAX_EXPIRES) {
475 p = ngx_cpymem(p, expires, sizeof(expires) - 1);
476
477 } else if (conf->expires) {
478 p = ngx_cpymem(p, expires, sizeof("; expires=") - 1);
479 p = ngx_http_cookie_time(p, ngx_time() + conf->expires);
480 }
481
482 p = ngx_copy(p, conf->domain.data, conf->domain.len);
483
484 p = ngx_copy(p, conf->path.data, conf->path.len);
485
486 set_cookie = ngx_list_push(&r->headers_out.headers);
487 if (set_cookie == NULL) {
488 return NGX_ERROR;
489 }
490
491 set_cookie->hash = 1;
492 ngx_str_set(&set_cookie->key, "Set-Cookie");
493 set_cookie->value.len = p - cookie;
494 set_cookie->value.data = cookie;
495
496 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
497 "uid cookie: \"%V\"", &set_cookie->value);
498
499 if (conf->p3p.len == 0) {
500 return NGX_OK;
501 }
502
503 p3p = ngx_list_push(&r->headers_out.headers);
504 if (p3p == NULL) {
505 return NGX_ERROR;
506 }
507
508 p3p->hash = 1;
509 ngx_str_set(&p3p->key, "P3P");
510 p3p->value = conf->p3p;
511 544
512 return NGX_OK; 545 return NGX_OK;
513 } 546 }
514 547
515 548
544 return NGX_ERROR; 577 return NGX_ERROR;
545 } 578 }
546 579
547 var->get_handler = ngx_http_userid_got_variable; 580 var->get_handler = ngx_http_userid_got_variable;
548 581
549 var = ngx_http_add_variable(cf, &ngx_http_userid_set, NGX_HTTP_VAR_NOHASH); 582 var = ngx_http_add_variable(cf, &ngx_http_userid_set,
583 NGX_HTTP_VAR_NOCACHEABLE);
550 if (var == NULL) { 584 if (var == NULL) {
551 return NGX_ERROR; 585 return NGX_ERROR;
552 } 586 }
553 587
554 var->get_handler = ngx_http_userid_set_variable; 588 var->get_handler = ngx_http_userid_set_variable;