Mercurial > hg > nginx
comparison src/event/ngx_event_openssl.c @ 7465:6708bec13757
SSL: adjusted session id context with dynamic certificates.
Dynamic certificates re-introduce problem with incorrect session
reuse (AKA "virtual host confusion", CVE-2014-3616), since there are
no server certificates to generate session id context from.
To prevent this, session id context is now generated from ssl_certificate
directives as specified in the configuration. This approach prevents
incorrect session reuse in most cases, while still allowing sharing
sessions across multiple machines with ssl_session_ticket_key set as
long as configurations are identical.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 25 Feb 2019 16:42:54 +0300 |
parents | 180df83473a4 |
children | d430babbe643 |
comparison
equal
deleted
inserted
replaced
7464:e970de27966a | 7465:6708bec13757 |
---|---|
52 static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, | 52 static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, |
53 ngx_err_t err, char *text); | 53 ngx_err_t err, char *text); |
54 static void ngx_ssl_clear_error(ngx_log_t *log); | 54 static void ngx_ssl_clear_error(ngx_log_t *log); |
55 | 55 |
56 static ngx_int_t ngx_ssl_session_id_context(ngx_ssl_t *ssl, | 56 static ngx_int_t ngx_ssl_session_id_context(ngx_ssl_t *ssl, |
57 ngx_str_t *sess_ctx); | 57 ngx_str_t *sess_ctx, ngx_array_t *certificates); |
58 static int ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, | 58 static int ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, |
59 ngx_ssl_session_t *sess); | 59 ngx_ssl_session_t *sess); |
60 static ngx_ssl_session_t *ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn, | 60 static ngx_ssl_session_t *ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn, |
61 #if OPENSSL_VERSION_NUMBER >= 0x10100003L | 61 #if OPENSSL_VERSION_NUMBER >= 0x10100003L |
62 const | 62 const |
3011 } | 3011 } |
3012 | 3012 |
3013 | 3013 |
3014 ngx_int_t | 3014 ngx_int_t |
3015 ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, | 3015 ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, |
3016 ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout) | 3016 ngx_array_t *certificates, ssize_t builtin_session_cache, |
3017 ngx_shm_zone_t *shm_zone, time_t timeout) | |
3017 { | 3018 { |
3018 long cache_mode; | 3019 long cache_mode; |
3019 | 3020 |
3020 SSL_CTX_set_timeout(ssl->ctx, (long) timeout); | 3021 SSL_CTX_set_timeout(ssl->ctx, (long) timeout); |
3021 | 3022 |
3022 if (ngx_ssl_session_id_context(ssl, sess_ctx) != NGX_OK) { | 3023 if (ngx_ssl_session_id_context(ssl, sess_ctx, certificates) != NGX_OK) { |
3023 return NGX_ERROR; | 3024 return NGX_ERROR; |
3024 } | 3025 } |
3025 | 3026 |
3026 if (builtin_session_cache == NGX_SSL_NO_SCACHE) { | 3027 if (builtin_session_cache == NGX_SSL_NO_SCACHE) { |
3027 SSL_CTX_set_session_cache_mode(ssl->ctx, SSL_SESS_CACHE_OFF); | 3028 SSL_CTX_set_session_cache_mode(ssl->ctx, SSL_SESS_CACHE_OFF); |
3083 return NGX_OK; | 3084 return NGX_OK; |
3084 } | 3085 } |
3085 | 3086 |
3086 | 3087 |
3087 static ngx_int_t | 3088 static ngx_int_t |
3088 ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t *sess_ctx) | 3089 ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, |
3090 ngx_array_t *certificates) | |
3089 { | 3091 { |
3090 int n, i; | 3092 int n, i; |
3091 X509 *cert; | 3093 X509 *cert; |
3092 X509_NAME *name; | 3094 X509_NAME *name; |
3095 ngx_str_t *certs; | |
3096 ngx_uint_t k; | |
3093 EVP_MD_CTX *md; | 3097 EVP_MD_CTX *md; |
3094 unsigned int len; | 3098 unsigned int len; |
3095 STACK_OF(X509_NAME) *list; | 3099 STACK_OF(X509_NAME) *list; |
3096 u_char buf[EVP_MAX_MD_SIZE]; | 3100 u_char buf[EVP_MAX_MD_SIZE]; |
3097 | 3101 |
3129 | 3133 |
3130 if (EVP_DigestUpdate(md, buf, len) == 0) { | 3134 if (EVP_DigestUpdate(md, buf, len) == 0) { |
3131 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, | 3135 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, |
3132 "EVP_DigestUpdate() failed"); | 3136 "EVP_DigestUpdate() failed"); |
3133 goto failed; | 3137 goto failed; |
3138 } | |
3139 } | |
3140 | |
3141 if (SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index) == NULL) { | |
3142 | |
3143 /* | |
3144 * If certificates are loaded dynamically, we use certificate | |
3145 * names as specified in the configuration (with variables). | |
3146 */ | |
3147 | |
3148 certs = certificates->elts; | |
3149 for (k = 0; k < certificates->nelts; k++) { | |
3150 | |
3151 if (EVP_DigestUpdate(md, certs[k].data, certs[k].len) == 0) { | |
3152 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, | |
3153 "EVP_DigestUpdate() failed"); | |
3154 goto failed; | |
3155 } | |
3134 } | 3156 } |
3135 } | 3157 } |
3136 | 3158 |
3137 list = SSL_CTX_get_client_CA_list(ssl->ctx); | 3159 list = SSL_CTX_get_client_CA_list(ssl->ctx); |
3138 | 3160 |