comparison src/event/ngx_event_openssl_stapling.c @ 7650:abb6cc8f1dd8

OCSP stapling: moved response verification to a separate function.
author Roman Arutyunyan <arut@nginx.com>
date Wed, 06 May 2020 21:44:14 +0300
parents b99cbafd51da
children 6ca8e15caf1f
comparison
equal deleted inserted replaced
7649:3c8082c3f98a 7650:abb6cc8f1dd8
42 42
43 43
44 typedef struct ngx_ssl_ocsp_ctx_s ngx_ssl_ocsp_ctx_t; 44 typedef struct ngx_ssl_ocsp_ctx_s ngx_ssl_ocsp_ctx_t;
45 45
46 struct ngx_ssl_ocsp_ctx_s { 46 struct ngx_ssl_ocsp_ctx_s {
47 SSL_CTX *ssl_ctx;
48
47 X509 *cert; 49 X509 *cert;
48 X509 *issuer; 50 X509 *issuer;
51
52 int status;
53 time_t valid;
49 54
50 u_char *name; 55 u_char *name;
51 56
52 ngx_uint_t naddrs; 57 ngx_uint_t naddrs;
53 58
72 77
73 ngx_uint_t state; 78 ngx_uint_t state;
74 79
75 ngx_uint_t code; 80 ngx_uint_t code;
76 ngx_uint_t count; 81 ngx_uint_t count;
77 82 ngx_uint_t flags;
78 ngx_uint_t done; 83 ngx_uint_t done;
79 84
80 u_char *header_name_start; 85 u_char *header_name_start;
81 u_char *header_name_end; 86 u_char *header_name_end;
82 u_char *header_start; 87 u_char *header_start;
118 static ngx_int_t ngx_ssl_ocsp_process_status_line(ngx_ssl_ocsp_ctx_t *ctx); 123 static ngx_int_t ngx_ssl_ocsp_process_status_line(ngx_ssl_ocsp_ctx_t *ctx);
119 static ngx_int_t ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t *ctx); 124 static ngx_int_t ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t *ctx);
120 static ngx_int_t ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx); 125 static ngx_int_t ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx);
121 static ngx_int_t ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx); 126 static ngx_int_t ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx);
122 static ngx_int_t ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx); 127 static ngx_int_t ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx);
128 static ngx_int_t ngx_ssl_ocsp_verify(ngx_ssl_ocsp_ctx_t *ctx);
123 129
124 static u_char *ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len); 130 static u_char *ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len);
125 131
126 132
127 ngx_int_t 133 ngx_int_t
562 ctx = ngx_ssl_ocsp_start(); 568 ctx = ngx_ssl_ocsp_start();
563 if (ctx == NULL) { 569 if (ctx == NULL) {
564 return; 570 return;
565 } 571 }
566 572
573 ctx->ssl_ctx = staple->ssl_ctx;
567 ctx->cert = staple->cert; 574 ctx->cert = staple->cert;
568 ctx->issuer = staple->issuer; 575 ctx->issuer = staple->issuer;
569 ctx->name = staple->name; 576 ctx->name = staple->name;
577 ctx->flags = (staple->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY);
570 578
571 ctx->addrs = staple->addrs; 579 ctx->addrs = staple->addrs;
572 ctx->host = staple->host; 580 ctx->host = staple->host;
573 ctx->uri = staple->uri; 581 ctx->uri = staple->uri;
574 ctx->port = staple->port; 582 ctx->port = staple->port;
587 595
588 596
589 static void 597 static void
590 ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx) 598 ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
591 { 599 {
592 int n; 600 time_t now;
593 size_t len; 601 ngx_str_t response;
594 time_t now, valid; 602 ngx_ssl_stapling_t *staple;
595 ngx_str_t response;
596 X509_STORE *store;
597 const u_char *p;
598 STACK_OF(X509) *chain;
599 OCSP_CERTID *id;
600 OCSP_RESPONSE *ocsp;
601 OCSP_BASICRESP *basic;
602 ngx_ssl_stapling_t *staple;
603 ASN1_GENERALIZEDTIME *thisupdate, *nextupdate;
604 603
605 staple = ctx->data; 604 staple = ctx->data;
606 now = ngx_time(); 605 now = ngx_time();
607 ocsp = NULL; 606
608 basic = NULL; 607 if (ngx_ssl_ocsp_verify(ctx) != NGX_OK) {
609 id = NULL;
610
611 if (ctx->code != 200) {
612 goto error; 608 goto error;
613 } 609 }
614 610
615 /* check the response */ 611 if (ctx->status != V_OCSP_CERTSTATUS_GOOD) {
616
617 len = ctx->response->last - ctx->response->pos;
618 p = ctx->response->pos;
619
620 ocsp = d2i_OCSP_RESPONSE(NULL, &p, len);
621 if (ocsp == NULL) {
622 ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
623 "d2i_OCSP_RESPONSE() failed");
624 goto error;
625 }
626
627 n = OCSP_response_status(ocsp);
628
629 if (n != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
630 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
631 "OCSP response not successful (%d: %s)",
632 n, OCSP_response_status_str(n));
633 goto error;
634 }
635
636 basic = OCSP_response_get1_basic(ocsp);
637 if (basic == NULL) {
638 ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
639 "OCSP_response_get1_basic() failed");
640 goto error;
641 }
642
643 store = SSL_CTX_get_cert_store(staple->ssl_ctx);
644 if (store == NULL) {
645 ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
646 "SSL_CTX_get_cert_store() failed");
647 goto error;
648 }
649
650 #ifdef SSL_CTRL_SELECT_CURRENT_CERT
651 /* OpenSSL 1.0.2+ */
652 SSL_CTX_select_current_cert(staple->ssl_ctx, ctx->cert);
653 #endif
654
655 #ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
656 /* OpenSSL 1.0.1+ */
657 SSL_CTX_get_extra_chain_certs(staple->ssl_ctx, &chain);
658 #else
659 chain = staple->ssl_ctx->extra_certs;
660 #endif
661
662 if (OCSP_basic_verify(basic, chain, store,
663 staple->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY)
664 != 1)
665 {
666 ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
667 "OCSP_basic_verify() failed");
668 goto error;
669 }
670
671 id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
672 if (id == NULL) {
673 ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
674 "OCSP_cert_to_id() failed");
675 goto error;
676 }
677
678 if (OCSP_resp_find_status(basic, id, &n, NULL, NULL,
679 &thisupdate, &nextupdate)
680 != 1)
681 {
682 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
683 "certificate status not found in the OCSP response");
684 goto error;
685 }
686
687 if (n != V_OCSP_CERTSTATUS_GOOD) {
688 ngx_log_error(NGX_LOG_ERR, ctx->log, 0, 612 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
689 "certificate status \"%s\" in the OCSP response", 613 "certificate status \"%s\" in the OCSP response",
690 OCSP_cert_status_str(n)); 614 OCSP_cert_status_str(ctx->status));
691 goto error; 615 goto error;
692 } 616 }
693 617
694 if (OCSP_check_validity(thisupdate, nextupdate, 300, -1) != 1) {
695 ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
696 "OCSP_check_validity() failed");
697 goto error;
698 }
699
700 if (nextupdate) {
701 valid = ngx_ssl_stapling_time(nextupdate);
702 if (valid == (time_t) NGX_ERROR) {
703 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
704 "invalid nextUpdate time in certificate status");
705 goto error;
706 }
707
708 } else {
709 valid = NGX_MAX_TIME_T_VALUE;
710 }
711
712 OCSP_CERTID_free(id);
713 OCSP_BASICRESP_free(basic);
714 OCSP_RESPONSE_free(ocsp);
715
716 id = NULL;
717 basic = NULL;
718 ocsp = NULL;
719
720 /* copy the response to memory not in ctx->pool */ 618 /* copy the response to memory not in ctx->pool */
721 619
722 response.len = len; 620 response.len = ctx->response->last - ctx->response->pos;
723 response.data = ngx_alloc(response.len, ctx->log); 621 response.data = ngx_alloc(response.len, ctx->log);
724 622
725 if (response.data == NULL) { 623 if (response.data == NULL) {
726 goto error; 624 goto error;
727 } 625 }
728 626
729 ngx_memcpy(response.data, ctx->response->pos, response.len); 627 ngx_memcpy(response.data, ctx->response->pos, response.len);
730 628
731 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
732 "ssl ocsp response, %s, %uz",
733 OCSP_cert_status_str(n), response.len);
734
735 if (staple->staple.data) { 629 if (staple->staple.data) {
736 ngx_free(staple->staple.data); 630 ngx_free(staple->staple.data);
737 } 631 }
738 632
739 staple->staple = response; 633 staple->staple = response;
740 staple->valid = valid; 634 staple->valid = ctx->valid;
741 635
742 /* 636 /*
743 * refresh before the response expires, 637 * refresh before the response expires,
744 * but not earlier than in 5 minutes, and at least in an hour 638 * but not earlier than in 5 minutes, and at least in an hour
745 */ 639 */
746 640
747 staple->loading = 0; 641 staple->loading = 0;
748 staple->refresh = ngx_max(ngx_min(valid - 300, now + 3600), now + 300); 642 staple->refresh = ngx_max(ngx_min(ctx->valid - 300, now + 3600), now + 300);
749 643
750 ngx_ssl_ocsp_done(ctx); 644 ngx_ssl_ocsp_done(ctx);
751 return; 645 return;
752 646
753 error: 647 error:
754 648
755 staple->loading = 0; 649 staple->loading = 0;
756 staple->refresh = now + 300; 650 staple->refresh = now + 300;
757
758 if (id) {
759 OCSP_CERTID_free(id);
760 }
761
762 if (basic) {
763 OCSP_BASICRESP_free(basic);
764 }
765
766 if (ocsp) {
767 OCSP_RESPONSE_free(ocsp);
768 }
769 651
770 ngx_ssl_ocsp_done(ctx); 652 ngx_ssl_ocsp_done(ctx);
771 } 653 }
772 654
773 655
1829 1711
1830 return NGX_AGAIN; 1712 return NGX_AGAIN;
1831 } 1713 }
1832 1714
1833 1715
1716 static ngx_int_t
1717 ngx_ssl_ocsp_verify(ngx_ssl_ocsp_ctx_t *ctx)
1718 {
1719 int n;
1720 size_t len;
1721 X509_STORE *store;
1722 const u_char *p;
1723 STACK_OF(X509) *chain;
1724 OCSP_CERTID *id;
1725 OCSP_RESPONSE *ocsp;
1726 OCSP_BASICRESP *basic;
1727 ASN1_GENERALIZEDTIME *thisupdate, *nextupdate;
1728
1729 ocsp = NULL;
1730 basic = NULL;
1731 id = NULL;
1732
1733 if (ctx->code != 200) {
1734 goto error;
1735 }
1736
1737 /* check the response */
1738
1739 len = ctx->response->last - ctx->response->pos;
1740 p = ctx->response->pos;
1741
1742 ocsp = d2i_OCSP_RESPONSE(NULL, &p, len);
1743 if (ocsp == NULL) {
1744 ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
1745 "d2i_OCSP_RESPONSE() failed");
1746 goto error;
1747 }
1748
1749 n = OCSP_response_status(ocsp);
1750
1751 if (n != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
1752 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1753 "OCSP response not successful (%d: %s)",
1754 n, OCSP_response_status_str(n));
1755 goto error;
1756 }
1757
1758 basic = OCSP_response_get1_basic(ocsp);
1759 if (basic == NULL) {
1760 ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
1761 "OCSP_response_get1_basic() failed");
1762 goto error;
1763 }
1764
1765 store = SSL_CTX_get_cert_store(ctx->ssl_ctx);
1766 if (store == NULL) {
1767 ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1768 "SSL_CTX_get_cert_store() failed");
1769 goto error;
1770 }
1771
1772 #ifdef SSL_CTRL_SELECT_CURRENT_CERT
1773 /* OpenSSL 1.0.2+ */
1774 SSL_CTX_select_current_cert(ctx->ssl_ctx, ctx->cert);
1775 #endif
1776
1777 #ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
1778 /* OpenSSL 1.0.1+ */
1779 SSL_CTX_get_extra_chain_certs(ctx->ssl_ctx, &chain);
1780 #else
1781 chain = ctx->ssl_ctx->extra_certs;
1782 #endif
1783
1784 if (OCSP_basic_verify(basic, chain, store, ctx->flags) != 1) {
1785 ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
1786 "OCSP_basic_verify() failed");
1787 goto error;
1788 }
1789
1790 id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
1791 if (id == NULL) {
1792 ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1793 "OCSP_cert_to_id() failed");
1794 goto error;
1795 }
1796
1797 if (OCSP_resp_find_status(basic, id, &ctx->status, NULL, NULL,
1798 &thisupdate, &nextupdate)
1799 != 1)
1800 {
1801 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1802 "certificate status not found in the OCSP response");
1803 goto error;
1804 }
1805
1806 if (OCSP_check_validity(thisupdate, nextupdate, 300, -1) != 1) {
1807 ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
1808 "OCSP_check_validity() failed");
1809 goto error;
1810 }
1811
1812 if (nextupdate) {
1813 ctx->valid = ngx_ssl_stapling_time(nextupdate);
1814 if (ctx->valid == (time_t) NGX_ERROR) {
1815 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1816 "invalid nextUpdate time in certificate status");
1817 goto error;
1818 }
1819
1820 } else {
1821 ctx->valid = NGX_MAX_TIME_T_VALUE;
1822 }
1823
1824 OCSP_CERTID_free(id);
1825 OCSP_BASICRESP_free(basic);
1826 OCSP_RESPONSE_free(ocsp);
1827
1828 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1829 "ssl ocsp response, %s, %uz",
1830 OCSP_cert_status_str(ctx->status), len);
1831
1832 return NGX_OK;
1833
1834 error:
1835
1836 if (id) {
1837 OCSP_CERTID_free(id);
1838 }
1839
1840 if (basic) {
1841 OCSP_BASICRESP_free(basic);
1842 }
1843
1844 if (ocsp) {
1845 OCSP_RESPONSE_free(ocsp);
1846 }
1847
1848 return NGX_ERROR;
1849 }
1850
1851
1834 static u_char * 1852 static u_char *
1835 ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len) 1853 ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len)
1836 { 1854 {
1837 u_char *p; 1855 u_char *p;
1838 ngx_ssl_ocsp_ctx_t *ctx; 1856 ngx_ssl_ocsp_ctx_t *ctx;