Mercurial > hg > nginx
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) |