diff options
author | Maxim Dounin <mdounin@mdounin.ru> | 2019-02-25 16:42:54 +0300 |
---|---|---|
committer | Maxim Dounin <mdounin@mdounin.ru> | 2019-02-25 16:42:54 +0300 |
commit | ecfab06cb20959219c9aadc2ef59507488e4fa99 (patch) | |
tree | 1a8a5da9c30639700d006f56851f69f77cd1fff2 | |
parent | fbcb0c8a33c7168aad3b1474d4cd8cde3486e155 (diff) |
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.
-rw-r--r-- | src/event/ngx_event_openssl.c | 30 | ||||
-rw-r--r-- | src/event/ngx_event_openssl.h | 3 | ||||
-rw-r--r-- | src/http/modules/ngx_http_ssl_module.c | 2 | ||||
-rw-r--r-- | src/mail/ngx_mail_ssl_module.c | 2 | ||||
-rw-r--r-- | src/stream/ngx_stream_ssl_module.c | 2 |
5 files changed, 31 insertions, 8 deletions
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c index c6eb65c64..e18778e2a 100644 --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -54,7 +54,7 @@ static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, static void ngx_ssl_clear_error(ngx_log_t *log); static ngx_int_t ngx_ssl_session_id_context(ngx_ssl_t *ssl, - ngx_str_t *sess_ctx); + ngx_str_t *sess_ctx, ngx_array_t *certificates); static int ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess); static ngx_ssl_session_t *ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn, @@ -3013,13 +3013,14 @@ ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...) ngx_int_t ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, - ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout) + ngx_array_t *certificates, ssize_t builtin_session_cache, + ngx_shm_zone_t *shm_zone, time_t timeout) { long cache_mode; SSL_CTX_set_timeout(ssl->ctx, (long) timeout); - if (ngx_ssl_session_id_context(ssl, sess_ctx) != NGX_OK) { + if (ngx_ssl_session_id_context(ssl, sess_ctx, certificates) != NGX_OK) { return NGX_ERROR; } @@ -3085,11 +3086,14 @@ ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, static ngx_int_t -ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t *sess_ctx) +ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, + ngx_array_t *certificates) { int n, i; X509 *cert; X509_NAME *name; + ngx_str_t *certs; + ngx_uint_t k; EVP_MD_CTX *md; unsigned int len; STACK_OF(X509_NAME) *list; @@ -3134,6 +3138,24 @@ ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t *sess_ctx) } } + if (SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index) == NULL) { + + /* + * If certificates are loaded dynamically, we use certificate + * names as specified in the configuration (with variables). + */ + + certs = certificates->elts; + for (k = 0; k < certificates->nelts; k++) { + + if (EVP_DigestUpdate(md, certs[k].data, certs[k].len) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "EVP_DigestUpdate() failed"); + goto failed; + } + } + } + list = SSL_CTX_get_client_CA_list(ssl->ctx); if (list != NULL) { diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h index 21ed19e2d..61da0c5db 100644 --- a/src/event/ngx_event_openssl.h +++ b/src/event/ngx_event_openssl.h @@ -192,7 +192,8 @@ ngx_int_t ngx_ssl_early_data(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_int_t ngx_ssl_client_session_cache(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_uint_t enable); ngx_int_t ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, - ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout); + ngx_array_t *certificates, ssize_t builtin_session_cache, + ngx_shm_zone_t *shm_zone, time_t timeout); ngx_int_t ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths); ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data); diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index 3134f0ec8..3bf122acb 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -817,7 +817,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) } if (ngx_ssl_session_cache(&conf->ssl, &ngx_http_ssl_sess_id_ctx, - conf->builtin_session_cache, + conf->certificates, conf->builtin_session_cache, conf->shm_zone, conf->session_timeout) != NGX_OK) { diff --git a/src/mail/ngx_mail_ssl_module.c b/src/mail/ngx_mail_ssl_module.c index 45095979e..10e982ee8 100644 --- a/src/mail/ngx_mail_ssl_module.c +++ b/src/mail/ngx_mail_ssl_module.c @@ -435,7 +435,7 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) } if (ngx_ssl_session_cache(&conf->ssl, &ngx_mail_ssl_sess_id_ctx, - conf->builtin_session_cache, + conf->certificates, conf->builtin_session_cache, conf->shm_zone, conf->session_timeout) != NGX_OK) { diff --git a/src/stream/ngx_stream_ssl_module.c b/src/stream/ngx_stream_ssl_module.c index 7e91d5bfe..9ab2c82be 100644 --- a/src/stream/ngx_stream_ssl_module.c +++ b/src/stream/ngx_stream_ssl_module.c @@ -766,7 +766,7 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) } if (ngx_ssl_session_cache(&conf->ssl, &ngx_stream_ssl_sess_id_ctx, - conf->builtin_session_cache, + conf->certificates, conf->builtin_session_cache, conf->shm_zone, conf->session_timeout) != NGX_OK) { |