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