Mercurial > hg > nginx
comparison src/event/ngx_event_openssl.c @ 5841:1ee1db30c9b9 stable-1.6
SSL: session id context now includes certificate hash.
This prevents inappropriate session reuse in unrelated server{}
blocks, while preserving ability to restore sessions on other servers
when using TLS Session Tickets.
Additionally, session context is now set even if there is no session cache
configured. This is needed as it's also used for TLS Session Tickets.
Thanks to Antoine Delignat-Lavaud and Piotr Sikora.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 15 Sep 2014 17:59:47 +0400 |
parents | 4c6ceca4f5f7 |
children | 1d6eb39d05c9 |
comparison
equal
deleted
inserted
replaced
5840:60d2cb03faee | 5841:1ee1db30c9b9 |
---|---|
25 static void ngx_ssl_shutdown_handler(ngx_event_t *ev); | 25 static void ngx_ssl_shutdown_handler(ngx_event_t *ev); |
26 static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, | 26 static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, |
27 ngx_err_t err, char *text); | 27 ngx_err_t err, char *text); |
28 static void ngx_ssl_clear_error(ngx_log_t *log); | 28 static void ngx_ssl_clear_error(ngx_log_t *log); |
29 | 29 |
30 static ngx_int_t ngx_ssl_session_id_context(ngx_ssl_t *ssl, | |
31 ngx_str_t *sess_ctx); | |
30 ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data); | 32 ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data); |
31 static int ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, | 33 static int ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, |
32 ngx_ssl_session_t *sess); | 34 ngx_ssl_session_t *sess); |
33 static ngx_ssl_session_t *ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn, | 35 static ngx_ssl_session_t *ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn, |
34 u_char *id, int len, int *copy); | 36 u_char *id, int len, int *copy); |
1727 { | 1729 { |
1728 long cache_mode; | 1730 long cache_mode; |
1729 | 1731 |
1730 SSL_CTX_set_timeout(ssl->ctx, (long) timeout); | 1732 SSL_CTX_set_timeout(ssl->ctx, (long) timeout); |
1731 | 1733 |
1734 if (ngx_ssl_session_id_context(ssl, sess_ctx) != NGX_OK) { | |
1735 return NGX_ERROR; | |
1736 } | |
1737 | |
1732 if (builtin_session_cache == NGX_SSL_NO_SCACHE) { | 1738 if (builtin_session_cache == NGX_SSL_NO_SCACHE) { |
1733 SSL_CTX_set_session_cache_mode(ssl->ctx, SSL_SESS_CACHE_OFF); | 1739 SSL_CTX_set_session_cache_mode(ssl->ctx, SSL_SESS_CACHE_OFF); |
1734 return NGX_OK; | 1740 return NGX_OK; |
1735 } | 1741 } |
1736 | |
1737 SSL_CTX_set_session_id_context(ssl->ctx, sess_ctx->data, sess_ctx->len); | |
1738 | 1742 |
1739 if (builtin_session_cache == NGX_SSL_NONE_SCACHE) { | 1743 if (builtin_session_cache == NGX_SSL_NONE_SCACHE) { |
1740 | 1744 |
1741 /* | 1745 /* |
1742 * If the server explicitly says that it does not support | 1746 * If the server explicitly says that it does not support |
1787 return NGX_ERROR; | 1791 return NGX_ERROR; |
1788 } | 1792 } |
1789 } | 1793 } |
1790 | 1794 |
1791 return NGX_OK; | 1795 return NGX_OK; |
1796 } | |
1797 | |
1798 | |
1799 static ngx_int_t | |
1800 ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t *sess_ctx) | |
1801 { | |
1802 int n, i; | |
1803 X509 *cert; | |
1804 X509_NAME *name; | |
1805 EVP_MD_CTX md; | |
1806 unsigned int len; | |
1807 STACK_OF(X509_NAME) *list; | |
1808 u_char buf[EVP_MAX_MD_SIZE]; | |
1809 | |
1810 /* | |
1811 * Session ID context is set based on the string provided, | |
1812 * the server certificate, and the client CA list. | |
1813 */ | |
1814 | |
1815 EVP_MD_CTX_init(&md); | |
1816 | |
1817 if (EVP_DigestInit_ex(&md, EVP_sha1(), NULL) == 0) { | |
1818 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, | |
1819 "EVP_DigestInit_ex() failed"); | |
1820 goto failed; | |
1821 } | |
1822 | |
1823 if (EVP_DigestUpdate(&md, sess_ctx->data, sess_ctx->len) == 0) { | |
1824 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, | |
1825 "EVP_DigestUpdate() failed"); | |
1826 goto failed; | |
1827 } | |
1828 | |
1829 cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); | |
1830 | |
1831 if (X509_digest(cert, EVP_sha1(), buf, &len) == 0) { | |
1832 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, | |
1833 "X509_digest() failed"); | |
1834 goto failed; | |
1835 } | |
1836 | |
1837 if (EVP_DigestUpdate(&md, buf, len) == 0) { | |
1838 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, | |
1839 "EVP_DigestUpdate() failed"); | |
1840 goto failed; | |
1841 } | |
1842 | |
1843 list = SSL_CTX_get_client_CA_list(ssl->ctx); | |
1844 | |
1845 if (list != NULL) { | |
1846 n = sk_X509_NAME_num(list); | |
1847 | |
1848 for (i = 0; i < n; i++) { | |
1849 name = sk_X509_NAME_value(list, i); | |
1850 | |
1851 if (X509_NAME_digest(name, EVP_sha1(), buf, &len) == 0) { | |
1852 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, | |
1853 "X509_NAME_digest() failed"); | |
1854 goto failed; | |
1855 } | |
1856 | |
1857 if (EVP_DigestUpdate(&md, buf, len) == 0) { | |
1858 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, | |
1859 "EVP_DigestUpdate() failed"); | |
1860 goto failed; | |
1861 } | |
1862 } | |
1863 } | |
1864 | |
1865 if (EVP_DigestFinal_ex(&md, buf, &len) == 0) { | |
1866 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, | |
1867 "EVP_DigestUpdate() failed"); | |
1868 goto failed; | |
1869 } | |
1870 | |
1871 EVP_MD_CTX_cleanup(&md); | |
1872 | |
1873 if (SSL_CTX_set_session_id_context(ssl->ctx, buf, len) == 0) { | |
1874 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, | |
1875 "SSL_CTX_set_session_id_context() failed"); | |
1876 return NGX_ERROR; | |
1877 } | |
1878 | |
1879 return NGX_OK; | |
1880 | |
1881 failed: | |
1882 | |
1883 EVP_MD_CTX_cleanup(&md); | |
1884 | |
1885 return NGX_ERROR; | |
1792 } | 1886 } |
1793 | 1887 |
1794 | 1888 |
1795 ngx_int_t | 1889 ngx_int_t |
1796 ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data) | 1890 ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data) |