comparison src/http/ngx_http_request.c @ 5091:d3e256c67d6d

SSL: do not treat SSL handshake as request. The request object will not be created until SSL handshake is complete. This simplifies adding another connection handler that does not need request object right after handshake (e.g., SPDY). There are also a few more intentional effects: - the "client_header_buffer_size" directive will be taken from the server configuration that was negotiated by SNI; - SSL handshake errors and timeouts are not logged into access log as bad requests; - ngx_ssl_create_connection() is not called until the first byte of ClientHello message was received. This also decreases memory consumption if plain HTTP request is sent to SSL socket.
author Valentin Bartenev <vbart@nginx.com>
date Wed, 27 Feb 2013 17:21:21 +0000
parents 9db95b275755
children c4d3310574e0
comparison
equal deleted inserted replaced
5090:9db95b275755 5091:d3e256c67d6d
314 314
315 rev = c->read; 315 rev = c->read;
316 rev->handler = ngx_http_init_request; 316 rev->handler = ngx_http_init_request;
317 c->write->handler = ngx_http_empty_handler; 317 c->write->handler = ngx_http_empty_handler;
318 318
319 #if (NGX_HTTP_SSL)
320 {
321 ngx_http_ssl_srv_conf_t *sscf;
322
323 sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module);
324
325 if (sscf->enable || hc->addr_conf->ssl) {
326
327 c->log->action = "SSL handshaking";
328
329 if (hc->addr_conf->ssl && sscf->ssl.ctx == NULL) {
330 ngx_log_error(NGX_LOG_ERR, c->log, 0,
331 "no \"ssl_certificate\" is defined "
332 "in server listening on SSL port");
333 ngx_http_close_connection(c);
334 return;
335 }
336
337 hc->ssl = 1;
338
339 rev->handler = ngx_http_ssl_handshake;
340 }
341 }
342 #endif
343
319 if (rev->ready) { 344 if (rev->ready) {
320 /* the deferred accept(), rtsig, aio, iocp */ 345 /* the deferred accept(), rtsig, aio, iocp */
321 346
322 if (ngx_use_accept_mutex) { 347 if (ngx_use_accept_mutex) {
323 ngx_post_event(rev, &ngx_posted_events); 348 ngx_post_event(rev, &ngx_posted_events);
324 return; 349 return;
325 } 350 }
326 351
327 ngx_http_init_request(rev); 352 rev->handler(rev);
328 return; 353 return;
329 } 354 }
330 355
331 ngx_add_timer(rev, c->listening->post_accept_timeout); 356 ngx_add_timer(rev, c->listening->post_accept_timeout);
332 357
393 418
394 r->main_conf = hc->conf_ctx->main_conf; 419 r->main_conf = hc->conf_ctx->main_conf;
395 r->srv_conf = hc->conf_ctx->srv_conf; 420 r->srv_conf = hc->conf_ctx->srv_conf;
396 r->loc_conf = hc->conf_ctx->loc_conf; 421 r->loc_conf = hc->conf_ctx->loc_conf;
397 422
398 rev->handler = ngx_http_process_request_line;
399 r->read_event_handler = ngx_http_block_reading; 423 r->read_event_handler = ngx_http_block_reading;
400
401 #if (NGX_HTTP_SSL)
402
403 {
404 ngx_http_ssl_srv_conf_t *sscf;
405
406 sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
407 if (sscf->enable || hc->addr_conf->ssl) {
408
409 if (c->ssl == NULL) {
410
411 c->log->action = "SSL handshaking";
412
413 if (hc->addr_conf->ssl && sscf->ssl.ctx == NULL) {
414 ngx_log_error(NGX_LOG_ERR, c->log, 0,
415 "no \"ssl_certificate\" is defined "
416 "in server listening on SSL port");
417 ngx_http_close_connection(c);
418 return;
419 }
420
421 if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER)
422 != NGX_OK)
423 {
424 ngx_http_close_connection(c);
425 return;
426 }
427
428 rev->handler = ngx_http_ssl_handshake;
429 }
430
431 r->main_filter_need_in_memory = 1;
432 }
433 }
434
435 #endif
436 424
437 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); 425 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
438 426
439 ngx_http_set_connection_log(r->connection, clcf->error_log); 427 ngx_http_set_connection_log(r->connection, clcf->error_log);
440 428
487 } 475 }
488 476
489 c->single_connection = 1; 477 c->single_connection = 1;
490 c->destroyed = 0; 478 c->destroyed = 0;
491 479
480 #if (NGX_HTTP_SSL)
481 if (c->ssl) {
482 r->main_filter_need_in_memory = 1;
483 }
484 #endif
485
492 r->main = r; 486 r->main = r;
493 r->count = 1; 487 r->count = 1;
494 488
495 tp = ngx_timeofday(); 489 tp = ngx_timeofday();
496 r->start_sec = tp->sec; 490 r->start_sec = tp->sec;
517 (void) ngx_atomic_fetch_add(ngx_stat_reading, 1); 511 (void) ngx_atomic_fetch_add(ngx_stat_reading, 1);
518 r->stat_reading = 1; 512 r->stat_reading = 1;
519 (void) ngx_atomic_fetch_add(ngx_stat_requests, 1); 513 (void) ngx_atomic_fetch_add(ngx_stat_requests, 1);
520 #endif 514 #endif
521 515
522 rev->handler(rev); 516 rev->handler = ngx_http_process_request_line;
517 ngx_http_process_request_line(rev);
523 } 518 }
524 519
525 520
526 #if (NGX_HTTP_SSL) 521 #if (NGX_HTTP_SSL)
527 522
528 static void 523 static void
529 ngx_http_ssl_handshake(ngx_event_t *rev) 524 ngx_http_ssl_handshake(ngx_event_t *rev)
530 { 525 {
531 u_char buf[1]; 526 u_char buf[1];
532 ssize_t n; 527 ssize_t n;
533 ngx_int_t rc; 528 ngx_err_t err;
534 ngx_connection_t *c; 529 ngx_int_t rc;
535 ngx_http_request_t *r; 530 ngx_connection_t *c;
531 ngx_http_connection_t *hc;
532 ngx_http_ssl_srv_conf_t *sscf;
536 533
537 c = rev->data; 534 c = rev->data;
538 r = c->data;
539 535
540 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, 536 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
541 "http check ssl handshake"); 537 "http check ssl handshake");
542 538
543 if (rev->timedout) { 539 if (rev->timedout) {
544 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); 540 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
545 c->timedout = 1; 541 ngx_http_close_connection(c);
546 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
547 return; 542 return;
548 } 543 }
549 544
550 n = recv(c->fd, (char *) buf, 1, MSG_PEEK); 545 n = recv(c->fd, (char *) buf, 1, MSG_PEEK);
551 546
552 if (n == -1 && ngx_socket_errno == NGX_EAGAIN) { 547 err = ngx_socket_errno;
553 548
554 if (!rev->timer_set) { 549 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http recv(): %d", n);
555 ngx_add_timer(rev, c->listening->post_accept_timeout); 550
556 } 551 if (n == -1) {
557 552 if (err == NGX_EAGAIN) {
558 if (ngx_handle_read_event(rev, 0) != NGX_OK) { 553
559 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); 554 if (!rev->timer_set) {
560 } 555 ngx_add_timer(rev, c->listening->post_accept_timeout);
556 }
557
558 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
559 ngx_http_close_connection(c);
560 }
561
562 return;
563 }
564
565 ngx_connection_error(c, err, "recv() failed");
566 ngx_http_close_connection(c);
561 567
562 return; 568 return;
563 } 569 }
564 570
565 if (n == 1) { 571 if (n == 1) {
566 if (buf[0] & 0x80 /* SSLv2 */ || buf[0] == 0x16 /* SSLv3/TLSv1 */) { 572 if (buf[0] & 0x80 /* SSLv2 */ || buf[0] == 0x16 /* SSLv3/TLSv1 */) {
567 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0, 573 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0,
568 "https ssl handshake: 0x%02Xd", buf[0]); 574 "https ssl handshake: 0x%02Xd", buf[0]);
569 575
576 hc = c->data;
577 sscf = ngx_http_get_module_srv_conf(hc->conf_ctx,
578 ngx_http_ssl_module);
579
580 if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER)
581 != NGX_OK)
582 {
583 ngx_http_close_connection(c);
584 return;
585 }
586
570 rc = ngx_ssl_handshake(c); 587 rc = ngx_ssl_handshake(c);
571 588
572 if (rc == NGX_AGAIN) { 589 if (rc == NGX_AGAIN) {
573 590
574 if (!rev->timer_set) { 591 if (!rev->timer_set) {
580 } 597 }
581 598
582 ngx_http_ssl_handshake_handler(c); 599 ngx_http_ssl_handshake_handler(c);
583 600
584 return; 601 return;
585 602 }
586 } else { 603
587 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, 604 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "plain http");
588 "plain http"); 605
589 606 c->log->action = "reading client request line";
590 r->plain_http = 1; 607
591 } 608 rev->handler = ngx_http_init_request;
592 } 609 ngx_http_init_request(rev);
593 610
594 c->log->action = "reading client request line"; 611 return;
595 612 }
596 rev->handler = ngx_http_process_request_line; 613
597 ngx_http_process_request_line(rev); 614 ngx_log_error(NGX_LOG_INFO, c->log, 0, "client closed connection");
615 ngx_http_close_connection(c);
598 } 616 }
599 617
600 618
601 static void 619 static void
602 ngx_http_ssl_handshake_handler(ngx_connection_t *c) 620 ngx_http_ssl_handshake_handler(ngx_connection_t *c)
603 { 621 {
604 ngx_http_request_t *r;
605
606 if (c->ssl->handshaked) { 622 if (c->ssl->handshaked) {
607 623
608 /* 624 /*
609 * The majority of browsers do not send the "close notify" alert. 625 * The majority of browsers do not send the "close notify" alert.
610 * Among them are MSIE, old Mozilla, Netscape 4, Konqueror, 626 * Among them are MSIE, old Mozilla, Netscape 4, Konqueror,
615 631
616 c->ssl->no_wait_shutdown = 1; 632 c->ssl->no_wait_shutdown = 1;
617 633
618 c->log->action = "reading client request line"; 634 c->log->action = "reading client request line";
619 635
620 c->read->handler = ngx_http_process_request_line; 636 c->read->handler = ngx_http_init_request;
621 /* STUB: epoll edge */ c->write->handler = ngx_http_empty_handler; 637 /* STUB: epoll edge */ c->write->handler = ngx_http_empty_handler;
622 638
623 ngx_http_process_request_line(c->read); 639 ngx_http_init_request(c->read);
624 640
625 return; 641 return;
626 } 642 }
627 643
628 r = c->data; 644 if (c->read->timedout) {
629 645 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
630 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST); 646 }
631 647
632 return; 648 ngx_http_close_connection(c);
633 } 649 }
634 650
635 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME 651 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
636 652
637 int 653 int
638 ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) 654 ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
639 { 655 {
640 ngx_str_t host; 656 ngx_str_t host;
641 const char *servername; 657 const char *servername;
642 ngx_connection_t *c; 658 ngx_connection_t *c;
643 ngx_http_request_t *r;
644 ngx_http_connection_t *hc; 659 ngx_http_connection_t *hc;
645 ngx_http_ssl_srv_conf_t *sscf; 660 ngx_http_ssl_srv_conf_t *sscf;
646 ngx_http_core_loc_conf_t *clcf; 661 ngx_http_core_loc_conf_t *clcf;
647 ngx_http_core_srv_conf_t *cscf; 662 ngx_http_core_srv_conf_t *cscf;
648 663
661 676
662 if (host.len == 0) { 677 if (host.len == 0) {
663 return SSL_TLSEXT_ERR_NOACK; 678 return SSL_TLSEXT_ERR_NOACK;
664 } 679 }
665 680
666 r = c->data;
667
668 host.data = (u_char *) servername; 681 host.data = (u_char *) servername;
669 682
670 if (ngx_http_validate_host(&host, r->pool, 1) != NGX_OK) { 683 if (ngx_http_validate_host(&host, c->pool, 1) != NGX_OK) {
671 return SSL_TLSEXT_ERR_NOACK; 684 return SSL_TLSEXT_ERR_NOACK;
672 } 685 }
673 686
674 hc = r->http_connection; 687 hc = c->data;
675 688
676 if (ngx_http_find_virtual_server(c, hc->addr_conf->virtual_names, &host, 689 if (ngx_http_find_virtual_server(c, hc->addr_conf->virtual_names, &host,
677 NULL, &cscf) 690 NULL, &cscf)
678 != NGX_OK) 691 != NGX_OK)
679 { 692 {
680 return SSL_TLSEXT_ERR_NOACK; 693 return SSL_TLSEXT_ERR_NOACK;
681 } 694 }
682 695
683 hc->conf_ctx = cscf->ctx; 696 hc->conf_ctx = cscf->ctx;
684 697
685 r->srv_conf = cscf->ctx->srv_conf; 698 clcf = ngx_http_get_module_loc_conf(hc->conf_ctx, ngx_http_core_module);
686 r->loc_conf = cscf->ctx->loc_conf;
687
688 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
689 699
690 ngx_http_set_connection_log(c, clcf->error_log); 700 ngx_http_set_connection_log(c, clcf->error_log);
691 701
692 sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module); 702 sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module);
693 703
694 if (sscf->ssl.ctx) { 704 if (sscf->ssl.ctx) {
695 SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx); 705 SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx);
696 706
697 /* 707 /*
1629 { 1639 {
1630 ngx_connection_t *c; 1640 ngx_connection_t *c;
1631 1641
1632 c = r->connection; 1642 c = r->connection;
1633 1643
1634 if (r->plain_http) {
1635 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1636 "client sent plain HTTP request to HTTPS port");
1637 ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS);
1638 return;
1639 }
1640
1641 #if (NGX_HTTP_SSL) 1644 #if (NGX_HTTP_SSL)
1642 1645
1643 if (c->ssl) { 1646 if (r->http_connection->ssl) {
1644 long rc; 1647 long rc;
1645 X509 *cert; 1648 X509 *cert;
1646 ngx_http_ssl_srv_conf_t *sscf; 1649 ngx_http_ssl_srv_conf_t *sscf;
1650
1651 if (c->ssl == NULL) {
1652 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1653 "client sent plain HTTP request to HTTPS port");
1654 ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS);
1655 return;
1656 }
1647 1657
1648 sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module); 1658 sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
1649 1659
1650 if (sscf->verify) { 1660 if (sscf->verify) {
1651 rc = SSL_get_verify_result(c->ssl->connection); 1661 rc = SSL_get_verify_result(c->ssl->connection);