comparison src/event/ngx_event_openssl.c @ 5834:ca63fc5ed9b1

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 275e35d54626
children ec81934727a1
comparison
equal deleted inserted replaced
5833:e3016ee8dba3 5834:ca63fc5ed9b1
31 static void ngx_ssl_shutdown_handler(ngx_event_t *ev); 31 static void ngx_ssl_shutdown_handler(ngx_event_t *ev);
32 static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, 32 static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr,
33 ngx_err_t err, char *text); 33 ngx_err_t err, char *text);
34 static void ngx_ssl_clear_error(ngx_log_t *log); 34 static void ngx_ssl_clear_error(ngx_log_t *log);
35 35
36 static ngx_int_t ngx_ssl_session_id_context(ngx_ssl_t *ssl,
37 ngx_str_t *sess_ctx);
36 ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data); 38 ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data);
37 static int ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, 39 static int ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn,
38 ngx_ssl_session_t *sess); 40 ngx_ssl_session_t *sess);
39 static ngx_ssl_session_t *ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn, 41 static ngx_ssl_session_t *ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn,
40 u_char *id, int len, int *copy); 42 u_char *id, int len, int *copy);
1971 { 1973 {
1972 long cache_mode; 1974 long cache_mode;
1973 1975
1974 SSL_CTX_set_timeout(ssl->ctx, (long) timeout); 1976 SSL_CTX_set_timeout(ssl->ctx, (long) timeout);
1975 1977
1978 if (ngx_ssl_session_id_context(ssl, sess_ctx) != NGX_OK) {
1979 return NGX_ERROR;
1980 }
1981
1976 if (builtin_session_cache == NGX_SSL_NO_SCACHE) { 1982 if (builtin_session_cache == NGX_SSL_NO_SCACHE) {
1977 SSL_CTX_set_session_cache_mode(ssl->ctx, SSL_SESS_CACHE_OFF); 1983 SSL_CTX_set_session_cache_mode(ssl->ctx, SSL_SESS_CACHE_OFF);
1978 return NGX_OK; 1984 return NGX_OK;
1979 } 1985 }
1980
1981 SSL_CTX_set_session_id_context(ssl->ctx, sess_ctx->data, sess_ctx->len);
1982 1986
1983 if (builtin_session_cache == NGX_SSL_NONE_SCACHE) { 1987 if (builtin_session_cache == NGX_SSL_NONE_SCACHE) {
1984 1988
1985 /* 1989 /*
1986 * If the server explicitly says that it does not support 1990 * If the server explicitly says that it does not support
2031 return NGX_ERROR; 2035 return NGX_ERROR;
2032 } 2036 }
2033 } 2037 }
2034 2038
2035 return NGX_OK; 2039 return NGX_OK;
2040 }
2041
2042
2043 static ngx_int_t
2044 ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t *sess_ctx)
2045 {
2046 int n, i;
2047 X509 *cert;
2048 X509_NAME *name;
2049 EVP_MD_CTX md;
2050 unsigned int len;
2051 STACK_OF(X509_NAME) *list;
2052 u_char buf[EVP_MAX_MD_SIZE];
2053
2054 /*
2055 * Session ID context is set based on the string provided,
2056 * the server certificate, and the client CA list.
2057 */
2058
2059 EVP_MD_CTX_init(&md);
2060
2061 if (EVP_DigestInit_ex(&md, EVP_sha1(), NULL) == 0) {
2062 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
2063 "EVP_DigestInit_ex() failed");
2064 goto failed;
2065 }
2066
2067 if (EVP_DigestUpdate(&md, sess_ctx->data, sess_ctx->len) == 0) {
2068 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
2069 "EVP_DigestUpdate() failed");
2070 goto failed;
2071 }
2072
2073 cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
2074
2075 if (X509_digest(cert, EVP_sha1(), buf, &len) == 0) {
2076 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
2077 "X509_digest() failed");
2078 goto failed;
2079 }
2080
2081 if (EVP_DigestUpdate(&md, buf, len) == 0) {
2082 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
2083 "EVP_DigestUpdate() failed");
2084 goto failed;
2085 }
2086
2087 list = SSL_CTX_get_client_CA_list(ssl->ctx);
2088
2089 if (list != NULL) {
2090 n = sk_X509_NAME_num(list);
2091
2092 for (i = 0; i < n; i++) {
2093 name = sk_X509_NAME_value(list, i);
2094
2095 if (X509_NAME_digest(name, EVP_sha1(), buf, &len) == 0) {
2096 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
2097 "X509_NAME_digest() failed");
2098 goto failed;
2099 }
2100
2101 if (EVP_DigestUpdate(&md, buf, len) == 0) {
2102 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
2103 "EVP_DigestUpdate() failed");
2104 goto failed;
2105 }
2106 }
2107 }
2108
2109 if (EVP_DigestFinal_ex(&md, buf, &len) == 0) {
2110 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
2111 "EVP_DigestUpdate() failed");
2112 goto failed;
2113 }
2114
2115 EVP_MD_CTX_cleanup(&md);
2116
2117 if (SSL_CTX_set_session_id_context(ssl->ctx, buf, len) == 0) {
2118 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
2119 "SSL_CTX_set_session_id_context() failed");
2120 return NGX_ERROR;
2121 }
2122
2123 return NGX_OK;
2124
2125 failed:
2126
2127 EVP_MD_CTX_cleanup(&md);
2128
2129 return NGX_ERROR;
2036 } 2130 }
2037 2131
2038 2132
2039 ngx_int_t 2133 ngx_int_t
2040 ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data) 2134 ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data)