comparison src/http/modules/ngx_http_userid_filter.c @ 10:46833bd150cb NGINX_0_1_5

nginx 0.1.5 *) Bugfix: on Solaris and Linux there may be too many "recvmsg() returned not enough data" alerts. *) Bugfix: there were the "writev() failed (22: Invalid argument)" errors on Solaris in proxy mode without sendfile. On other platforms that do not support sendfile at all the process got caught in an endless loop. *) Bugfix: segmentation fault on Solaris in proxy mode and using sendfile. *) Bugfix: segmentation fault on Solaris. *) Bugfix: on-line upgrade did not work on Linux. *) Bugfix: the ngx_http_autoindex_module module did not escape the spaces, the quotes, and the percent signs in the directory listing. *) Change: the decrease of the copy operations. *) Feature: the userid_p3p directive.
author Igor Sysoev <http://sysoev.ru>
date Thu, 11 Nov 2004 00:00:00 +0300
parents 4b2dafa26fe2
children 7ca9bdc82b3f
comparison
equal deleted inserted replaced
9:77eee314ddbd 10:46833bd150cb
25 25
26 ngx_str_t name; 26 ngx_str_t name;
27 ngx_str_t domain; 27 ngx_str_t domain;
28 ngx_str_t path; 28 ngx_str_t path;
29 time_t expires; 29 time_t expires;
30 30 ngx_str_t p3p;
31 ngx_int_t p3p;
32 ngx_str_t p3p_string;
33 } ngx_http_userid_conf_t; 31 } ngx_http_userid_conf_t;
34 32
35 33
36 typedef struct { 34 typedef struct {
37 uint32_t uid_got[4]; 35 uint32_t uid_got[4];
38 uint32_t uid_set[4]; 36 uint32_t uid_set[4];
39 } ngx_http_userid_ctx_t; 37 } ngx_http_userid_ctx_t;
40 38
41 39
42 static ngx_int_t ngx_http_userid_get_uid(ngx_http_request_t *r, 40 static ngx_int_t ngx_http_userid_get_uid(ngx_http_request_t *r,
43 ngx_http_userid_ctx_t *ctx, 41 ngx_http_userid_ctx_t *ctx,
54 static ngx_int_t ngx_http_userid_init(ngx_cycle_t *cycle); 52 static ngx_int_t ngx_http_userid_init(ngx_cycle_t *cycle);
55 static ngx_int_t ngx_http_userid_pre_conf(ngx_conf_t *cf); 53 static ngx_int_t ngx_http_userid_pre_conf(ngx_conf_t *cf);
56 static void *ngx_http_userid_create_conf(ngx_conf_t *cf); 54 static void *ngx_http_userid_create_conf(ngx_conf_t *cf);
57 static char *ngx_http_userid_merge_conf(ngx_conf_t *cf, void *parent, 55 static char *ngx_http_userid_merge_conf(ngx_conf_t *cf, void *parent,
58 void *child); 56 void *child);
59 char *ngx_conf_check_domain(ngx_conf_t *cf, void *post, void *data); 57 char *ngx_http_userid_domain(ngx_conf_t *cf, void *post, void *data);
58 char *ngx_http_userid_path(ngx_conf_t *cf, void *post, void *data);
60 char *ngx_http_userid_expires(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); 59 char *ngx_http_userid_expires(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
60 char *ngx_http_userid_p3p(ngx_conf_t *cf, void *post, void *data);
61 61
62 62
63 static uint32_t sequencer_v1 = 1; 63 static uint32_t sequencer_v1 = 1;
64 static uint32_t sequencer_v2 = 0x03030302; 64 static uint32_t sequencer_v2 = 0x03030302;
65 65
77 { ngx_string("on"), NGX_HTTP_USERID_ON }, 77 { ngx_string("on"), NGX_HTTP_USERID_ON },
78 { ngx_null_string, 0 } 78 { ngx_null_string, 0 }
79 }; 79 };
80 80
81 81
82 static ngx_conf_post_handler_pt ngx_conf_check_domain_p = 82 static ngx_conf_post_handler_pt ngx_http_userid_domain_p =
83 ngx_conf_check_domain; 83 ngx_http_userid_domain;
84
85 static ngx_conf_post_handler_pt ngx_http_userid_path_p = ngx_http_userid_path;
86 static ngx_conf_post_handler_pt ngx_http_userid_p3p_p = ngx_http_userid_p3p;
84 87
85 88
86 static ngx_command_t ngx_http_userid_commands[] = { 89 static ngx_command_t ngx_http_userid_commands[] = {
87 90
88 { ngx_string("userid"), 91 { ngx_string("userid"),
109 { ngx_string("userid_domain"), 112 { ngx_string("userid_domain"),
110 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, 113 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
111 ngx_conf_set_str_slot, 114 ngx_conf_set_str_slot,
112 NGX_HTTP_LOC_CONF_OFFSET, 115 NGX_HTTP_LOC_CONF_OFFSET,
113 offsetof(ngx_http_userid_conf_t, domain), 116 offsetof(ngx_http_userid_conf_t, domain),
114 &ngx_conf_check_domain_p }, 117 &ngx_http_userid_domain_p },
115 118
116 { ngx_string("userid_path"), 119 { ngx_string("userid_path"),
117 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, 120 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
118 ngx_conf_set_str_slot, 121 ngx_conf_set_str_slot,
119 NGX_HTTP_LOC_CONF_OFFSET, 122 NGX_HTTP_LOC_CONF_OFFSET,
120 offsetof(ngx_http_userid_conf_t, path), 123 offsetof(ngx_http_userid_conf_t, path),
121 NULL }, 124 &ngx_http_userid_path_p },
122 125
123 { ngx_string("userid_expires"), 126 { ngx_string("userid_expires"),
124 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, 127 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
125 ngx_http_userid_expires, 128 ngx_http_userid_expires,
126 NGX_HTTP_LOC_CONF_OFFSET, 129 NGX_HTTP_LOC_CONF_OFFSET,
127 0, 130 0,
128 NULL }, 131 NULL },
132
133 { ngx_string("userid_p3p"),
134 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
135 ngx_conf_set_str_slot,
136 NGX_HTTP_LOC_CONF_OFFSET,
137 offsetof(ngx_http_userid_conf_t, p3p),
138 &ngx_http_userid_p3p_p },
129 139
130 ngx_null_command 140 ngx_null_command
131 }; 141 };
132 142
133 143
208 218
209 cookies = r->headers_in.cookies.elts; 219 cookies = r->headers_in.cookies.elts;
210 220
211 for (i = 0; i < r->headers_in.cookies.nelts; i++) { 221 for (i = 0; i < r->headers_in.cookies.nelts; i++) {
212 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 222 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
213 "cookie: \"%s\"", cookies[i]->value.data); 223 "cookie: \"%V\"", &cookies[i]->value);
214 224
225 if (conf->name.len >= cookies[i]->value.len) {
226 continue;
227 }
228
229 start = cookies[i]->value.data;
215 end = cookies[i]->value.data + cookies[i]->value.len; 230 end = cookies[i]->value.data + cookies[i]->value.len;
216 231
217 for (start = cookies[i]->value.data; start < end; /* void */) { 232 while (start < end) {
218 233
219 if (conf->name.len >= cookies[i]->value.len 234 if (ngx_strncmp(start, conf->name.data, conf->name.len) != 0) {
220 || ngx_strncmp(start, conf->name.data, conf->name.len) != 0) 235
221 {
222 start += conf->name.len;
223 while (start < end && *start++ != ';') { /* void */ } 236 while (start < end && *start++ != ';') { /* void */ }
224 237 while (start < end && *start == ' ') { start++; }
225 for (/* void */; start < end && *start == ' '; start++) { /**/ }
226 238
227 continue; 239 continue;
228 } 240 }
229 241
230 for (start += conf->name.len; start < end && *start == ' '; start++) 242 start += conf->name.len;
231 { 243
232 /* void */ 244 while (start < end && *start == ' ') { start++; }
233 } 245
234 246 if (start == end || *start++ != '=') {
235 if (*start != '=') { 247 /* the invalid "Cookie" header */
236 break; 248 break;
237 } 249 }
238 250
239 for (start++; start < end && *start == ' '; start++) { /* void */ } 251 while (start < end && *start == ' ') { start++; }
240 252
241 for (last = start; last < end && *last != ';'; last++) { /**/ } 253 last = start;
254
255 while (last < end && *last++ != ';') { /* void */ }
242 256
243 if (last - start < 22) { 257 if (last - start < 22) {
244 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 258 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
245 "client sent too short userid cookie \"%s\"", 259 "client sent too short userid cookie \"%V\"",
246 cookies[i]->value.data); 260 &cookies[i]->value);
247 break; 261 break;
248 } 262 }
249 263
250 /* 264 /*
251 * we have to limit encoded string to 22 characters 265 * we have to limit encoded string to 22 characters
257 src.data = start; 271 src.data = start;
258 dst.data = (u_char *) ctx->uid_got; 272 dst.data = (u_char *) ctx->uid_got;
259 273
260 if (ngx_decode_base64(&dst, &src) == NGX_ERROR) { 274 if (ngx_decode_base64(&dst, &src) == NGX_ERROR) {
261 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 275 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
262 "client sent invalid userid cookie \"%s\"", 276 "client sent invalid userid cookie \"%V\"",
263 cookies[i]->value.data); 277 &cookies[i]->value);
264 break; 278 break;
265 } 279 }
266 280
267 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 281 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
268 "uid: %08X%08X%08X%08X", 282 "uid: %08XD%08XD%08XD%08XD",
269 ctx->uid_got[0], ctx->uid_got[1], 283 ctx->uid_got[0], ctx->uid_got[1],
270 ctx->uid_got[2], ctx->uid_got[3]); 284 ctx->uid_got[2], ctx->uid_got[3]);
271 285
272 return NGX_OK; 286 return NGX_OK;
273 } 287 }
278 292
279 293
280 static ngx_int_t ngx_http_userid_set_uid(ngx_http_request_t *r, 294 static ngx_int_t ngx_http_userid_set_uid(ngx_http_request_t *r,
281 ngx_http_userid_ctx_t *ctx, 295 ngx_http_userid_ctx_t *ctx,
282 ngx_http_userid_conf_t *conf) 296 ngx_http_userid_conf_t *conf)
283
284 { 297 {
285 u_char *cookie, *p; 298 u_char *cookie, *p;
286 size_t len; 299 size_t len;
287 socklen_t slen; 300 socklen_t slen;
288 struct sockaddr_in addr_in; 301 struct sockaddr_in addr_in;
289 ngx_str_t src, dst; 302 ngx_str_t src, dst;
290 ngx_table_elt_t *set_cookie; 303 ngx_table_elt_t *set_cookie, *p3p;
291 304
292 /* TODO: mutex for sequencers */ 305 /* TODO: mutex for sequencers */
293 306
294 if (conf->enable == NGX_HTTP_USERID_V1) { 307 if (conf->enable == NGX_HTTP_USERID_V1) {
295 if (conf->service == NGX_CONF_UNSET) { 308 if (conf->service == NGX_CONF_UNSET) {
331 if (sequencer_v2 < 0x03030302) { 344 if (sequencer_v2 < 0x03030302) {
332 sequencer_v2 = 0x03030302; 345 sequencer_v2 = 0x03030302;
333 } 346 }
334 } 347 }
335 348
336 len = conf->name.len + 1 + ngx_base64_encoded_length(16) + 1; 349 len = conf->name.len + 1 + ngx_base64_encoded_length(16) + conf->path.len;
337 350
338 if (conf->expires) { 351 if (conf->expires) {
339 len += sizeof(expires) - 1 + 2; 352 len += sizeof(expires) - 1 + 2;
340 } 353 }
341 354
342 if (conf->domain.len > 1) { 355 if (conf->domain.len > 1) {
343 len += sizeof("; domain=") - 1 + conf->domain.len; 356 len += conf->domain.len;
344 }
345
346 if (conf->path.len) {
347 len += sizeof("; path=") - 1 + conf->path.len;
348 } 357 }
349 358
350 if (!(cookie = ngx_palloc(r->pool, len))) { 359 if (!(cookie = ngx_palloc(r->pool, len))) {
351 return NGX_ERROR; 360 return NGX_ERROR;
352 } 361 }
369 p = ngx_cpymem(p, expires, sizeof("; expires=") - 1); 378 p = ngx_cpymem(p, expires, sizeof("; expires=") - 1);
370 p = ngx_http_cookie_time(p, ngx_time() + conf->expires); 379 p = ngx_http_cookie_time(p, ngx_time() + conf->expires);
371 } 380 }
372 381
373 if (conf->domain.len > 1) { 382 if (conf->domain.len > 1) {
374 p = ngx_cpymem(p, "; domain=", sizeof("; domain=") - 1);
375 p = ngx_cpymem(p, conf->domain.data, conf->domain.len); 383 p = ngx_cpymem(p, conf->domain.data, conf->domain.len);
376 } 384 }
377 385
378 if (conf->path.len) { 386 p = ngx_cpymem(p, conf->path.data, conf->path.len);
379 p = ngx_cpymem(p, "; path=", sizeof("; path=") - 1);
380 p = ngx_cpymem(p, conf->path.data, conf->path.len);
381 }
382
383 *p = '\0';
384
385 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
386 "uid cookie: \"%s\"", cookie);
387 387
388 if (!(set_cookie = ngx_list_push(&r->headers_out.headers))) { 388 if (!(set_cookie = ngx_list_push(&r->headers_out.headers))) {
389 return NGX_ERROR; 389 return NGX_ERROR;
390 } 390 }
391 391
392 set_cookie->key.len = sizeof("Set-Cookie") - 1; 392 set_cookie->key.len = sizeof("Set-Cookie") - 1;
393 set_cookie->key.data = (u_char *) "Set-Cookie"; 393 set_cookie->key.data = (u_char *) "Set-Cookie";
394 set_cookie->value.len = p - cookie; 394 set_cookie->value.len = p - cookie;
395 set_cookie->value.data = cookie; 395 set_cookie->value.data = cookie;
396 396
397 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
398 "uid cookie: \"%V\"", &set_cookie->value);
399
400 if (conf->p3p.len == 1) {
401 return NGX_OK;
402 }
403
404 if (!(p3p = ngx_list_push(&r->headers_out.headers))) {
405 return NGX_ERROR;
406 }
407
408 p3p->key.len = sizeof("P3P") - 1;
409 p3p->key.data = (u_char *) "P3P";
410 p3p->value = conf->p3p;
411
397 return NGX_OK; 412 return NGX_OK;
398 } 413 }
399 414
400 415
401 static u_char *ngx_http_userid_log_uid_got(ngx_http_request_t *r, u_char *buf, 416 static u_char *ngx_http_userid_log_uid_got(ngx_http_request_t *r, u_char *buf,
423 438
424 buf = ngx_cpymem(buf, conf->name.data, conf->name.len); 439 buf = ngx_cpymem(buf, conf->name.data, conf->name.len);
425 440
426 *buf++ = '='; 441 *buf++ = '=';
427 442
428 return buf + ngx_snprintf((char *) buf, 33, "%08X%08X%08X%08X", 443 return ngx_sprintf(buf, "%08XD%08XD%08XD%08XD",
429 ctx->uid_got[0], ctx->uid_got[1], 444 ctx->uid_got[0], ctx->uid_got[1],
430 ctx->uid_got[2], ctx->uid_got[3]); 445 ctx->uid_got[2], ctx->uid_got[3]);
431 } 446 }
432 447
433 448
434 static u_char *ngx_http_userid_log_uid_set(ngx_http_request_t *r, u_char *buf, 449 static u_char *ngx_http_userid_log_uid_set(ngx_http_request_t *r, u_char *buf,
435 uintptr_t data) 450 uintptr_t data)
456 471
457 buf = ngx_cpymem(buf, conf->name.data, conf->name.len); 472 buf = ngx_cpymem(buf, conf->name.data, conf->name.len);
458 473
459 *buf++ = '='; 474 *buf++ = '=';
460 475
461 return buf + ngx_snprintf((char *) buf, 33, "%08X%08X%08X%08X", 476 return ngx_sprintf(buf, "%08XD%08XD%08XD%08XD",
462 ctx->uid_set[0], ctx->uid_set[1], 477 ctx->uid_set[0], ctx->uid_set[1],
463 ctx->uid_set[2], ctx->uid_set[3]); 478 ctx->uid_set[2], ctx->uid_set[3]);
464 } 479 }
465 480
466 481
467 static ngx_int_t ngx_http_userid_init(ngx_cycle_t *cycle) 482 static ngx_int_t ngx_http_userid_init(ngx_cycle_t *cycle)
468 { 483 {
508 conf->name.date = NULL; 523 conf->name.date = NULL;
509 conf->domain.len = 0; 524 conf->domain.len = 0;
510 conf->domain.date = NULL; 525 conf->domain.date = NULL;
511 conf->path.len = 0; 526 conf->path.len = 0;
512 conf->path.date = NULL; 527 conf->path.date = NULL;
528 conf->p3p.len = 0;
529 conf->p3p.date = NULL;
513 530
514 */ 531 */
515 532
516 conf->enable = NGX_CONF_UNSET; 533 conf->enable = NGX_CONF_UNSET;
517 conf->service = NGX_CONF_UNSET; 534 conf->service = NGX_CONF_UNSET;
529 546
530 ngx_conf_merge_value(conf->enable, prev->enable, NGX_HTTP_USERID_OFF); 547 ngx_conf_merge_value(conf->enable, prev->enable, NGX_HTTP_USERID_OFF);
531 548
532 ngx_conf_merge_str_value(conf->name, prev->name, "uid"); 549 ngx_conf_merge_str_value(conf->name, prev->name, "uid");
533 ngx_conf_merge_str_value(conf->domain, prev->domain, "."); 550 ngx_conf_merge_str_value(conf->domain, prev->domain, ".");
534 ngx_conf_merge_str_value(conf->path, prev->path, "/"); 551 ngx_conf_merge_str_value(conf->path, prev->path, "; path=/");
552 ngx_conf_merge_str_value(conf->p3p, prev->p3p, ".");
535 553
536 ngx_conf_merge_value(conf->service, prev->service, NGX_CONF_UNSET); 554 ngx_conf_merge_value(conf->service, prev->service, NGX_CONF_UNSET);
537 ngx_conf_merge_sec_value(conf->expires, prev->expires, 0); 555 ngx_conf_merge_sec_value(conf->expires, prev->expires, 0);
538 556
539 return NGX_CONF_OK; 557 return NGX_CONF_OK;
540 } 558 }
541 559
542 560
543 char *ngx_conf_check_domain(ngx_conf_t *cf, void *post, void *data) 561 char *ngx_http_userid_domain(ngx_conf_t *cf, void *post, void *data)
544 { 562 {
545 ngx_str_t *domain = data; 563 ngx_str_t *domain = data;
564
565 u_char *p, *new;
546 566
547 if (domain->len == 4 && ngx_strcmp(domain->data, "none") == 0) { 567 if (domain->len == 4 && ngx_strcmp(domain->data, "none") == 0) {
548 domain->len = 1; 568 domain->len = 1;
549 domain->data = (u_char *) "."; 569 domain->data = (u_char *) ".";
550 } 570
571 return NGX_CONF_OK;
572 }
573
574 if (!(new = ngx_palloc(cf->pool, sizeof("; domain=") - 1 + domain->len))) {
575 return NGX_CONF_ERROR;
576 }
577
578 p = ngx_cpymem(new, "; domain=", sizeof("; domain=") - 1);
579 p = ngx_cpymem(p, domain->data, domain->len);
580
581 domain->len += sizeof("; domain=") - 1;
582 domain->data = new;
583
584 return NGX_CONF_OK;
585 }
586
587
588 char *ngx_http_userid_path(ngx_conf_t *cf, void *post, void *data)
589 {
590 ngx_str_t *path = data;
591
592 u_char *p, *new;
593
594 if (!(new = ngx_palloc(cf->pool, sizeof("; path=") - 1 + path->len))) {
595 return NGX_CONF_ERROR;
596 }
597
598 p = ngx_cpymem(new, "; path=", sizeof("; path=") - 1);
599 p = ngx_cpymem(p, path->data, path->len);
600
601 path->len += sizeof("; path=") - 1;
602 path->data = new;
551 603
552 return NGX_CONF_OK; 604 return NGX_CONF_OK;
553 } 605 }
554 606
555 607
584 return "value must be less than 68 years"; 636 return "value must be less than 68 years";
585 } 637 }
586 638
587 return NGX_CONF_OK; 639 return NGX_CONF_OK;
588 } 640 }
641
642
643 char *ngx_http_userid_p3p(ngx_conf_t *cf, void *post, void *data)
644 {
645 ngx_str_t *p3p = data;
646
647 if (p3p->len == 4 && ngx_strcmp(p3p->data, "none") == 0) {
648 p3p->len = 1;
649 p3p->data = (u_char *) ".";
650 }
651
652 return NGX_CONF_OK;
653 }