Mercurial > hg > nginx
comparison src/event/ngx_event_openssl.c @ 7653:8409f9df6219
SSL: client certificate validation with OCSP (ticket #1534).
OCSP validation for client certificates is enabled by the "ssl_ocsp" directive.
OCSP responder can be optionally specified by "ssl_ocsp_responder".
When session is reused, peer chain is not available for validation.
If the verified chain contains certificates from the peer chain not available
at the server, validation will fail.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Fri, 22 May 2020 17:30:12 +0300 |
parents | f1720934c45b |
children | 699f6e55bbb4 7995cd199b52 |
comparison
equal
deleted
inserted
replaced
7652:7cffd81015e7 | 7653:8409f9df6219 |
---|---|
128 | 128 |
129 int ngx_ssl_connection_index; | 129 int ngx_ssl_connection_index; |
130 int ngx_ssl_server_conf_index; | 130 int ngx_ssl_server_conf_index; |
131 int ngx_ssl_session_cache_index; | 131 int ngx_ssl_session_cache_index; |
132 int ngx_ssl_session_ticket_keys_index; | 132 int ngx_ssl_session_ticket_keys_index; |
133 int ngx_ssl_ocsp_index; | |
133 int ngx_ssl_certificate_index; | 134 int ngx_ssl_certificate_index; |
134 int ngx_ssl_next_certificate_index; | 135 int ngx_ssl_next_certificate_index; |
135 int ngx_ssl_certificate_name_index; | 136 int ngx_ssl_certificate_name_index; |
136 int ngx_ssl_stapling_index; | 137 int ngx_ssl_stapling_index; |
137 | 138 |
206 } | 207 } |
207 | 208 |
208 ngx_ssl_session_ticket_keys_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, | 209 ngx_ssl_session_ticket_keys_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, |
209 NULL, NULL); | 210 NULL, NULL); |
210 if (ngx_ssl_session_ticket_keys_index == -1) { | 211 if (ngx_ssl_session_ticket_keys_index == -1) { |
212 ngx_ssl_error(NGX_LOG_ALERT, log, 0, | |
213 "SSL_CTX_get_ex_new_index() failed"); | |
214 return NGX_ERROR; | |
215 } | |
216 | |
217 ngx_ssl_ocsp_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL); | |
218 if (ngx_ssl_ocsp_index == -1) { | |
211 ngx_ssl_error(NGX_LOG_ALERT, log, 0, | 219 ngx_ssl_error(NGX_LOG_ALERT, log, 0, |
212 "SSL_CTX_get_ex_new_index() failed"); | 220 "SSL_CTX_get_ex_new_index() failed"); |
213 return NGX_ERROR; | 221 return NGX_ERROR; |
214 } | 222 } |
215 | 223 |
1592 ngx_int_t | 1600 ngx_int_t |
1593 ngx_ssl_handshake(ngx_connection_t *c) | 1601 ngx_ssl_handshake(ngx_connection_t *c) |
1594 { | 1602 { |
1595 int n, sslerr; | 1603 int n, sslerr; |
1596 ngx_err_t err; | 1604 ngx_err_t err; |
1605 ngx_int_t rc; | |
1597 | 1606 |
1598 #ifdef SSL_READ_EARLY_DATA_SUCCESS | 1607 #ifdef SSL_READ_EARLY_DATA_SUCCESS |
1599 if (c->ssl->try_early_data) { | 1608 if (c->ssl->try_early_data) { |
1600 return ngx_ssl_try_early_data(c); | 1609 return ngx_ssl_try_early_data(c); |
1601 } | 1610 } |
1602 #endif | 1611 #endif |
1603 | 1612 |
1613 if (c->ssl->in_ocsp) { | |
1614 return ngx_ssl_ocsp_validate(c); | |
1615 } | |
1616 | |
1604 ngx_ssl_clear_error(c->log); | 1617 ngx_ssl_clear_error(c->log); |
1605 | 1618 |
1606 n = SSL_do_handshake(c->ssl->connection); | 1619 n = SSL_do_handshake(c->ssl->connection); |
1607 | 1620 |
1608 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n); | 1621 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n); |
1618 } | 1631 } |
1619 | 1632 |
1620 #if (NGX_DEBUG) | 1633 #if (NGX_DEBUG) |
1621 ngx_ssl_handshake_log(c); | 1634 ngx_ssl_handshake_log(c); |
1622 #endif | 1635 #endif |
1623 | |
1624 c->ssl->handshaked = 1; | |
1625 | 1636 |
1626 c->recv = ngx_ssl_recv; | 1637 c->recv = ngx_ssl_recv; |
1627 c->send = ngx_ssl_write; | 1638 c->send = ngx_ssl_write; |
1628 c->recv_chain = ngx_ssl_recv_chain; | 1639 c->recv_chain = ngx_ssl_recv_chain; |
1629 c->send_chain = ngx_ssl_send_chain; | 1640 c->send_chain = ngx_ssl_send_chain; |
1639 | 1650 |
1640 #endif | 1651 #endif |
1641 #endif | 1652 #endif |
1642 #endif | 1653 #endif |
1643 | 1654 |
1655 rc = ngx_ssl_ocsp_validate(c); | |
1656 | |
1657 if (rc == NGX_ERROR) { | |
1658 return NGX_ERROR; | |
1659 } | |
1660 | |
1661 if (rc == NGX_AGAIN) { | |
1662 c->read->handler = ngx_ssl_handshake_handler; | |
1663 c->write->handler = ngx_ssl_handshake_handler; | |
1664 return NGX_AGAIN; | |
1665 } | |
1666 | |
1667 c->ssl->handshaked = 1; | |
1668 | |
1644 return NGX_OK; | 1669 return NGX_OK; |
1645 } | 1670 } |
1646 | 1671 |
1647 sslerr = SSL_get_error(c->ssl->connection, n); | 1672 sslerr = SSL_get_error(c->ssl->connection, n); |
1648 | 1673 |
1708 { | 1733 { |
1709 int n, sslerr; | 1734 int n, sslerr; |
1710 u_char buf; | 1735 u_char buf; |
1711 size_t readbytes; | 1736 size_t readbytes; |
1712 ngx_err_t err; | 1737 ngx_err_t err; |
1738 ngx_int_t rc; | |
1713 | 1739 |
1714 ngx_ssl_clear_error(c->log); | 1740 ngx_ssl_clear_error(c->log); |
1715 | 1741 |
1716 readbytes = 0; | 1742 readbytes = 0; |
1717 | 1743 |
1742 c->ssl->try_early_data = 0; | 1768 c->ssl->try_early_data = 0; |
1743 | 1769 |
1744 c->ssl->early_buf = buf; | 1770 c->ssl->early_buf = buf; |
1745 c->ssl->early_preread = 1; | 1771 c->ssl->early_preread = 1; |
1746 | 1772 |
1747 c->ssl->handshaked = 1; | |
1748 c->ssl->in_early = 1; | 1773 c->ssl->in_early = 1; |
1749 | 1774 |
1750 c->recv = ngx_ssl_recv; | 1775 c->recv = ngx_ssl_recv; |
1751 c->send = ngx_ssl_write; | 1776 c->send = ngx_ssl_write; |
1752 c->recv_chain = ngx_ssl_recv_chain; | 1777 c->recv_chain = ngx_ssl_recv_chain; |
1753 c->send_chain = ngx_ssl_send_chain; | 1778 c->send_chain = ngx_ssl_send_chain; |
1779 | |
1780 rc = ngx_ssl_ocsp_validate(c); | |
1781 | |
1782 if (rc == NGX_ERROR) { | |
1783 return NGX_ERROR; | |
1784 } | |
1785 | |
1786 if (rc == NGX_AGAIN) { | |
1787 c->read->handler = ngx_ssl_handshake_handler; | |
1788 c->write->handler = ngx_ssl_handshake_handler; | |
1789 return NGX_AGAIN; | |
1790 } | |
1791 | |
1792 c->ssl->handshaked = 1; | |
1754 | 1793 |
1755 return NGX_OK; | 1794 return NGX_OK; |
1756 } | 1795 } |
1757 | 1796 |
1758 /* SSL_READ_EARLY_DATA_ERROR */ | 1797 /* SSL_READ_EARLY_DATA_ERROR */ |
2732 ngx_int_t | 2771 ngx_int_t |
2733 ngx_ssl_shutdown(ngx_connection_t *c) | 2772 ngx_ssl_shutdown(ngx_connection_t *c) |
2734 { | 2773 { |
2735 int n, sslerr, mode; | 2774 int n, sslerr, mode; |
2736 ngx_err_t err; | 2775 ngx_err_t err; |
2776 | |
2777 ngx_ssl_ocsp_cleanup(c); | |
2737 | 2778 |
2738 if (SSL_in_init(c->ssl->connection)) { | 2779 if (SSL_in_init(c->ssl->connection)) { |
2739 /* | 2780 /* |
2740 * OpenSSL 1.0.2f complains if SSL_shutdown() is called during | 2781 * OpenSSL 1.0.2f complains if SSL_shutdown() is called during |
2741 * an SSL handshake, while previous versions always return 0. | 2782 * an SSL handshake, while previous versions always return 0. |
4892 X509_free(cert); | 4933 X509_free(cert); |
4893 | 4934 |
4894 rc = SSL_get_verify_result(c->ssl->connection); | 4935 rc = SSL_get_verify_result(c->ssl->connection); |
4895 | 4936 |
4896 if (rc == X509_V_OK) { | 4937 if (rc == X509_V_OK) { |
4897 ngx_str_set(s, "SUCCESS"); | 4938 if (ngx_ssl_ocsp_get_status(c, &str) == NGX_OK) { |
4898 return NGX_OK; | 4939 ngx_str_set(s, "SUCCESS"); |
4899 } | 4940 return NGX_OK; |
4900 | 4941 } |
4901 str = X509_verify_cert_error_string(rc); | 4942 |
4943 } else { | |
4944 str = X509_verify_cert_error_string(rc); | |
4945 } | |
4902 | 4946 |
4903 s->data = ngx_pnalloc(pool, sizeof("FAILED:") - 1 + ngx_strlen(str)); | 4947 s->data = ngx_pnalloc(pool, sizeof("FAILED:") - 1 + ngx_strlen(str)); |
4904 if (s->data == NULL) { | 4948 if (s->data == NULL) { |
4905 return NGX_ERROR; | 4949 return NGX_ERROR; |
4906 } | 4950 } |