mirror of
https://github.com/nginx/nginx.git
synced 2025-02-25 18:55:26 -06:00
SNI: added restriction for TLSv1.3 cross-SNI session resumption.
In OpenSSL, session resumption always happens in the default SSL context, prior to invoking the SNI callback. Further, unlike in TLSv1.2 and older protocols, SSL_get_servername() returns values received in the resumption handshake, which may be different from the value in the initial handshake. Notably, this makes the restriction added inb720f650b
insufficient for sessions resumed with different SNI server name. Considering the example fromb720f650b
, previously, a client was able to request example.org by presenting a certificate for example.org, then to resume and request example.com. The fix is to reject handshakes resumed with a different server name, if verification of client certificates is enabled in a corresponding server configuration.
This commit is contained in:
parent
22a2a225ba
commit
46b9f5d389
@ -932,6 +932,31 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
|
||||
goto done;
|
||||
}
|
||||
|
||||
sscf = ngx_http_get_module_srv_conf(cscf->ctx, ngx_http_ssl_module);
|
||||
|
||||
#if (defined TLS1_3_VERSION \
|
||||
&& !defined LIBRESSL_VERSION_NUMBER && !defined OPENSSL_IS_BORINGSSL)
|
||||
|
||||
/*
|
||||
* SSL_SESSION_get0_hostname() is only available in OpenSSL 1.1.1+,
|
||||
* but servername being negotiated in every TLSv1.3 handshake
|
||||
* is only returned in OpenSSL 1.1.1+ as well
|
||||
*/
|
||||
|
||||
if (sscf->verify) {
|
||||
const char *hostname;
|
||||
|
||||
hostname = SSL_SESSION_get0_hostname(SSL_get0_session(ssl_conn));
|
||||
|
||||
if (hostname != NULL && ngx_strcmp(hostname, servername) != 0) {
|
||||
c->ssl->handshake_rejected = 1;
|
||||
*ad = SSL_AD_ACCESS_DENIED;
|
||||
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
hc->ssl_servername = ngx_palloc(c->pool, sizeof(ngx_str_t));
|
||||
if (hc->ssl_servername == NULL) {
|
||||
goto error;
|
||||
@ -945,8 +970,6 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
|
||||
|
||||
ngx_set_connection_log(c, clcf->error_log);
|
||||
|
||||
sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module);
|
||||
|
||||
c->ssl->buffer_size = sscf->buffer_size;
|
||||
|
||||
if (sscf->ssl.ctx) {
|
||||
|
@ -589,12 +589,35 @@ ngx_stream_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
|
||||
goto done;
|
||||
}
|
||||
|
||||
sscf = ngx_stream_get_module_srv_conf(cscf->ctx, ngx_stream_ssl_module);
|
||||
|
||||
#if (defined TLS1_3_VERSION \
|
||||
&& !defined LIBRESSL_VERSION_NUMBER && !defined OPENSSL_IS_BORINGSSL)
|
||||
|
||||
/*
|
||||
* SSL_SESSION_get0_hostname() is only available in OpenSSL 1.1.1+,
|
||||
* but servername being negotiated in every TLSv1.3 handshake
|
||||
* is only returned in OpenSSL 1.1.1+ as well
|
||||
*/
|
||||
|
||||
if (sscf->verify) {
|
||||
const char *hostname;
|
||||
|
||||
hostname = SSL_SESSION_get0_hostname(SSL_get0_session(ssl_conn));
|
||||
|
||||
if (hostname != NULL && ngx_strcmp(hostname, servername) != 0) {
|
||||
c->ssl->handshake_rejected = 1;
|
||||
*ad = SSL_AD_ACCESS_DENIED;
|
||||
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
s->srv_conf = cscf->ctx->srv_conf;
|
||||
|
||||
ngx_set_connection_log(c, cscf->error_log);
|
||||
|
||||
sscf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module);
|
||||
|
||||
if (sscf->ssl.ctx) {
|
||||
if (SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx) == NULL) {
|
||||
goto error;
|
||||
|
Loading…
Reference in New Issue
Block a user