summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/event/ngx_event_openssl.c85
-rw-r--r--src/event/ngx_event_openssl.h15
-rw-r--r--src/http/modules/ngx_http_ssl_module.c6
-rw-r--r--src/http/ngx_http_request.c62
-rw-r--r--src/stream/ngx_stream_ssl_module.c68
5 files changed, 165 insertions, 71 deletions
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
index e36f30c74..d9abcd082 100644
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -128,6 +128,7 @@ int ngx_ssl_ticket_keys_index;
int ngx_ssl_ocsp_index;
int ngx_ssl_index;
int ngx_ssl_certificate_name_index;
+int ngx_ssl_client_hello_arg_index;
u_char ngx_ssl_session_buffer[NGX_SSL_MAX_SESSION_SIZE];
@@ -270,6 +271,14 @@ ngx_ssl_init(ngx_log_t *log)
return NGX_ERROR;
}
+ ngx_ssl_client_hello_arg_index = SSL_CTX_get_ex_new_index(0, NULL, NULL,
+ NULL, NULL);
+ if (ngx_ssl_client_hello_arg_index == -1) {
+ ngx_ssl_error(NGX_LOG_ALERT, log, 0,
+ "SSL_CTX_get_ex_new_index() failed");
+ return NGX_ERROR;
+ }
+
return NGX_OK;
}
@@ -1645,6 +1654,82 @@ ngx_ssl_new_client_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess)
}
+void
+ngx_ssl_set_client_hello_callback(SSL_CTX *ssl_ctx,
+ ngx_ssl_client_hello_arg *cb)
+{
+#ifdef SSL_CLIENT_HELLO_SUCCESS
+
+ SSL_CTX_set_client_hello_cb(ssl_ctx, ngx_ssl_client_hello_callback, NULL);
+ SSL_CTX_set_ex_data(ssl_ctx, ngx_ssl_client_hello_arg_index, cb);
+
+#endif
+}
+
+
+#ifdef SSL_CLIENT_HELLO_SUCCESS
+
+int
+ngx_ssl_client_hello_callback(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
+{
+ u_char *p;
+ size_t len;
+ ngx_int_t rc;
+ ngx_str_t host;
+ ngx_connection_t *c;
+ ngx_ssl_client_hello_arg *cb;
+
+ c = ngx_ssl_get_connection(ssl_conn);
+ cb = SSL_CTX_get_ex_data(c->ssl->session_ctx,
+ ngx_ssl_client_hello_arg_index);
+
+ if (SSL_client_hello_get0_ext(ssl_conn, TLSEXT_TYPE_server_name,
+ (const unsigned char **) &p, &len)
+ == 0)
+ {
+ ngx_str_null(&host);
+ goto done;
+ }
+
+ /*
+ * RFC 6066 mandates non-zero HostName length, we follow OpenSSL.
+ * No more than one ServerName is expected.
+ */
+
+ if (len < 5
+ || (size_t) (p[0] << 8) + p[1] + 2 != len
+ || p[2] != TLSEXT_NAMETYPE_host_name
+ || (size_t) (p[3] << 8) + p[4] + 2 + 3 != len)
+ {
+ *ad = SSL_AD_DECODE_ERROR;
+ return SSL_CLIENT_HELLO_ERROR;
+ }
+
+ len -= 5;
+ p += 5;
+
+ if (len > TLSEXT_MAXLEN_host_name || ngx_strlchr(p, p + len, '\0')) {
+ *ad = SSL_AD_UNRECOGNIZED_NAME;
+ return SSL_CLIENT_HELLO_ERROR;
+ }
+
+ host.len = len;
+ host.data = p;
+
+done:
+
+ rc = cb->servername(ssl_conn, ad, &host);
+
+ if (rc == SSL_TLSEXT_ERR_ALERT_FATAL) {
+ return SSL_CLIENT_HELLO_ERROR;
+ }
+
+ return SSL_CLIENT_HELLO_SUCCESS;
+}
+
+#endif
+
+
ngx_int_t
ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags)
{
diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h
index e7ccd51e8..544703f61 100644
--- a/src/event/ngx_event_openssl.h
+++ b/src/event/ngx_event_openssl.h
@@ -151,6 +151,7 @@ struct ngx_ssl_connection_s {
unsigned in_ocsp:1;
unsigned early_preread:1;
unsigned write_blocked:1;
+ unsigned sni_accepted:1;
};
@@ -197,6 +198,13 @@ typedef struct {
} ngx_ssl_session_cache_t;
+typedef int (*ngx_ssl_servername_pt)(ngx_ssl_conn_t *, int *, void *);
+
+typedef struct {
+ ngx_ssl_servername_pt servername;
+} ngx_ssl_client_hello_arg;
+
+
#define NGX_SSL_SSLv2 0x0002
#define NGX_SSL_SSLv3 0x0004
#define NGX_SSL_TLSv1 0x0008
@@ -286,6 +294,12 @@ 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);
+void ngx_ssl_set_client_hello_callback(SSL_CTX *ssl_ctx,
+ ngx_ssl_client_hello_arg *cb);
+#ifdef SSL_CLIENT_HELLO_SUCCESS
+int ngx_ssl_client_hello_callback(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg);
+#endif
+
ngx_int_t ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c,
ngx_uint_t flags);
@@ -382,6 +396,7 @@ extern int ngx_ssl_ticket_keys_index;
extern int ngx_ssl_ocsp_index;
extern int ngx_ssl_index;
extern int ngx_ssl_certificate_name_index;
+extern int ngx_ssl_client_hello_arg_index;
extern u_char ngx_ssl_session_buffer[NGX_SSL_MAX_SESSION_SIZE];
diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c
index fbf4ab871..3778758e2 100644
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -749,6 +749,10 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
cln->data = &conf->ssl;
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+ {
+ static ngx_ssl_client_hello_arg cb = { ngx_http_ssl_servername };
+
+ ngx_ssl_set_client_hello_callback(conf->ssl.ctx, &cb);
if (SSL_CTX_set_tlsext_servername_callback(conf->ssl.ctx,
ngx_http_ssl_servername)
@@ -759,7 +763,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
"dynamically to an OpenSSL library which has no tlsext support, "
"therefore SNI is not available");
}
-
+ }
#endif
#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 95cb1a133..6f6e975b7 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -891,27 +891,41 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
return SSL_TLSEXT_ERR_ALERT_FATAL;
}
+ if (c->ssl->sni_accepted) {
+ return SSL_TLSEXT_ERR_OK;
+ }
+
hc = c->data;
- servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name);
+ if (arg != NULL) {
+ host = *(ngx_str_t *) arg;
- if (servername == NULL) {
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "SSL server name: null");
- goto done;
+ if (host.data == NULL) {
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
+ "SSL server name: null");
+ goto done;
+ }
+
+ } else {
+ servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name);
+
+ if (servername == NULL) {
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
+ "SSL server name: null");
+ goto done;
+ }
+
+ host.len = ngx_strlen(servername);
+ host.data = (u_char *) servername;
}
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "SSL server name: \"%s\"", servername);
-
- host.len = ngx_strlen(servername);
+ "SSL server name: \"%V\"", &host);
if (host.len == 0) {
goto done;
}
- host.data = (u_char *) servername;
-
rc = ngx_http_validate_host(&host, c->pool, 1);
if (rc == NGX_ERROR) {
@@ -933,31 +947,6 @@ 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;
@@ -971,6 +960,8 @@ 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(cscf->ctx, ngx_http_ssl_module);
+
c->ssl->buffer_size = sscf->buffer_size;
if (sscf->ssl.ctx) {
@@ -1019,6 +1010,7 @@ done:
return SSL_TLSEXT_ERR_ALERT_FATAL;
}
+ c->ssl->sni_accepted = 1;
return SSL_TLSEXT_ERR_OK;
error:
diff --git a/src/stream/ngx_stream_ssl_module.c b/src/stream/ngx_stream_ssl_module.c
index 7ce1175f1..7bf6304e4 100644
--- a/src/stream/ngx_stream_ssl_module.c
+++ b/src/stream/ngx_stream_ssl_module.c
@@ -555,27 +555,41 @@ ngx_stream_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
return SSL_TLSEXT_ERR_ALERT_FATAL;
}
+ if (c->ssl->sni_accepted) {
+ return SSL_TLSEXT_ERR_OK;
+ }
+
s = c->data;
- servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name);
+ if (arg) {
+ host = *(ngx_str_t *) arg;
- if (servername == NULL) {
- ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0,
- "SSL server name: null");
- goto done;
+ if (host.data == NULL) {
+ ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0,
+ "SSL server name: null");
+ goto done;
+ }
+
+ } else {
+ servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name);
+
+ if (servername == NULL) {
+ ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0,
+ "SSL server name: null");
+ goto done;
+ }
+
+ host.len = ngx_strlen(servername);
+ host.data = (u_char *) servername;
}
ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0,
- "SSL server name: \"%s\"", servername);
-
- host.len = ngx_strlen(servername);
+ "SSL server name: \"%V\"", &host);
if (host.len == 0) {
goto done;
}
- host.data = (u_char *) servername;
-
rc = ngx_stream_validate_host(&host, c->pool, 1);
if (rc == NGX_ERROR) {
@@ -596,35 +610,12 @@ 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(cscf->ctx, ngx_stream_ssl_module);
+
if (sscf->ssl.ctx) {
if (SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx) == NULL) {
goto error;
@@ -663,6 +654,7 @@ done:
return SSL_TLSEXT_ERR_ALERT_FATAL;
}
+ c->ssl->sni_accepted = 1;
return SSL_TLSEXT_ERR_OK;
error:
@@ -1002,8 +994,14 @@ ngx_stream_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
cln->data = &conf->ssl;
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+ {
+ static ngx_ssl_client_hello_arg cb = { ngx_stream_ssl_servername };
+
+ ngx_ssl_set_client_hello_callback(conf->ssl.ctx, &cb);
+
SSL_CTX_set_tlsext_servername_callback(conf->ssl.ctx,
ngx_stream_ssl_servername);
+ }
#endif
#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation