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)