diff options
author | Roman Arutyunyan <arut@nginx.com> | 2023-12-14 21:58:39 +0400 |
---|---|---|
committer | Roman Arutyunyan <arut@nginx.com> | 2023-12-14 21:58:39 +0400 |
commit | d21675228a0ba8d4331e05c60660228a5d3326de (patch) | |
tree | 5218a1fcffa6998931d6d55e24255208635ddc7f /src/stream/ngx_stream_ssl_module.c | |
parent | 72e5d6ac19a93c9fb64678dd33ea185757a6021a (diff) | |
download | nginx-d21675228a0ba8d4331e05c60660228a5d3326de.tar.gz nginx-d21675228a0ba8d4331e05c60660228a5d3326de.zip |
Stream: virtual servers.
Server name is taken either from ngx_stream_ssl_module or
ngx_stream_ssl_preread_module.
The change adds "default_server" parameter to the "listen" directive,
as well as the following directives: "server_names_hash_max_size",
"server_names_hash_bucket_size", "server_name" and "ssl_reject_handshake".
Diffstat (limited to 'src/stream/ngx_stream_ssl_module.c')
-rw-r--r-- | src/stream/ngx_stream_ssl_module.c | 224 |
1 files changed, 193 insertions, 31 deletions
diff --git a/src/stream/ngx_stream_ssl_module.c b/src/stream/ngx_stream_ssl_module.c index 1ba1825ce..ee5e2f631 100644 --- a/src/stream/ngx_stream_ssl_module.c +++ b/src/stream/ngx_stream_ssl_module.c @@ -219,6 +219,13 @@ static ngx_command_t ngx_stream_ssl_commands[] = { offsetof(ngx_stream_ssl_conf_t, conf_commands), &ngx_stream_ssl_conf_command_post }, + { ngx_string("ssl_reject_handshake"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_STREAM_SRV_CONF_OFFSET, + offsetof(ngx_stream_ssl_conf_t, reject_handshake), + NULL }, + { ngx_string("ssl_alpn"), NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE, ngx_stream_ssl_alpn, @@ -458,7 +465,112 @@ ngx_stream_ssl_handshake_handler(ngx_connection_t *c) static int ngx_stream_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) { + ngx_int_t rc; + ngx_str_t host; + const char *servername; + ngx_connection_t *c; + ngx_stream_session_t *s; + ngx_stream_ssl_conf_t *sscf; + ngx_stream_core_srv_conf_t *cscf; + + c = ngx_ssl_get_connection(ssl_conn); + + if (c->ssl->handshaked) { + *ad = SSL_AD_NO_RENEGOTIATION; + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + + s = c->data; + + 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; + } + + ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, + "SSL server name: \"%s\"", servername); + + host.len = ngx_strlen(servername); + + if (host.len == 0) { + goto done; + } + + host.data = (u_char *) servername; + + rc = ngx_stream_validate_host(&host, c->pool, 1); + + if (rc == NGX_ERROR) { + goto error; + } + + if (rc == NGX_DECLINED) { + goto done; + } + + rc = ngx_stream_find_virtual_server(s, &host, &cscf); + + if (rc == NGX_ERROR) { + goto error; + } + + if (rc == NGX_DECLINED) { + goto done; + } + + 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; + } + + /* + * SSL_set_SSL_CTX() only changes certs as of 1.0.0d + * adjust other things we care about + */ + + SSL_set_verify(ssl_conn, SSL_CTX_get_verify_mode(sscf->ssl.ctx), + SSL_CTX_get_verify_callback(sscf->ssl.ctx)); + + SSL_set_verify_depth(ssl_conn, SSL_CTX_get_verify_depth(sscf->ssl.ctx)); + +#if OPENSSL_VERSION_NUMBER >= 0x009080dfL + /* only in 0.9.8m+ */ + SSL_clear_options(ssl_conn, SSL_get_options(ssl_conn) & + ~SSL_CTX_get_options(sscf->ssl.ctx)); +#endif + + SSL_set_options(ssl_conn, SSL_CTX_get_options(sscf->ssl.ctx)); + +#ifdef SSL_OP_NO_RENEGOTIATION + SSL_set_options(ssl_conn, SSL_OP_NO_RENEGOTIATION); +#endif + } + +done: + + sscf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module); + + if (sscf->reject_handshake) { + c->ssl->handshake_rejected = 1; + *ad = SSL_AD_UNRECOGNIZED_NAME; + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + return SSL_TLSEXT_ERR_OK; + +error: + + *ad = SSL_AD_INTERNAL_ERROR; + return SSL_TLSEXT_ERR_ALERT_FATAL; } #endif @@ -655,7 +767,6 @@ ngx_stream_ssl_create_conf(ngx_conf_t *cf) /* * set by ngx_pcalloc(): * - * scf->listen = 0; * scf->protocols = 0; * scf->certificate_values = NULL; * scf->dhparam = { 0, NULL }; @@ -674,6 +785,7 @@ ngx_stream_ssl_create_conf(ngx_conf_t *cf) scf->passwords = NGX_CONF_UNSET_PTR; scf->conf_commands = NGX_CONF_UNSET_PTR; scf->prefer_server_ciphers = NGX_CONF_UNSET; + scf->reject_handshake = NGX_CONF_UNSET; scf->verify = NGX_CONF_UNSET_UINT; scf->verify_depth = NGX_CONF_UNSET_UINT; scf->builtin_session_cache = NGX_CONF_UNSET; @@ -702,6 +814,8 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_value(conf->prefer_server_ciphers, prev->prefer_server_ciphers, 0); + ngx_conf_merge_value(conf->reject_handshake, prev->reject_handshake, 0); + ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols, (NGX_CONF_BITMASK_SET |NGX_SSL_TLSv1|NGX_SSL_TLSv1_1 @@ -735,35 +849,21 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) conf->ssl.log = cf->log; - if (!conf->listen) { - return NGX_CONF_OK; - } - - if (conf->certificates == NULL) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "no \"ssl_certificate\" is defined for " - "the \"listen ... ssl\" directive in %s:%ui", - conf->file, conf->line); - return NGX_CONF_ERROR; - } + if (conf->certificates) { - if (conf->certificate_keys == NULL) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "no \"ssl_certificate_key\" is defined for " - "the \"listen ... ssl\" directive in %s:%ui", - conf->file, conf->line); - return NGX_CONF_ERROR; - } + if (conf->certificate_keys == NULL + || conf->certificate_keys->nelts < conf->certificates->nelts) + { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no \"ssl_certificate_key\" is defined " + "for certificate \"%V\"", + ((ngx_str_t *) conf->certificates->elts) + + conf->certificates->nelts - 1); + return NGX_CONF_ERROR; + } - if (conf->certificate_keys->nelts < conf->certificates->nelts) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "no \"ssl_certificate_key\" is defined " - "for certificate \"%V\" and " - "the \"listen ... ssl\" directive in %s:%ui", - ((ngx_str_t *) conf->certificates->elts) - + conf->certificates->nelts - 1, - conf->file, conf->line); - return NGX_CONF_ERROR; + } else if (!conf->reject_handshake) { + return NGX_CONF_OK; } if (ngx_ssl_create(&conf->ssl, conf->protocols, NULL) != NGX_OK) { @@ -818,7 +918,7 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) return NGX_CONF_ERROR; #endif - } else { + } else if (conf->certificates) { /* configure certificates */ @@ -917,6 +1017,10 @@ ngx_stream_ssl_compile_certificates(ngx_conf_t *cf, ngx_stream_complex_value_t *cv; ngx_stream_compile_complex_value_t ccv; + if (conf->certificates == NULL) { + return NGX_OK; + } + cert = conf->certificates->elts; key = conf->certificate_keys->elts; nelts = conf->certificates->nelts; @@ -1195,8 +1299,13 @@ ngx_stream_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data) static ngx_int_t ngx_stream_ssl_init(ngx_conf_t *cf) { - ngx_stream_handler_pt *h; - ngx_stream_core_main_conf_t *cmcf; + ngx_uint_t a, p, s; + ngx_stream_handler_pt *h; + ngx_stream_ssl_conf_t *sscf; + ngx_stream_conf_addr_t *addr; + ngx_stream_conf_port_t *port; + ngx_stream_core_srv_conf_t **cscfp, *cscf; + ngx_stream_core_main_conf_t *cmcf; cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module); @@ -1207,5 +1316,58 @@ ngx_stream_ssl_init(ngx_conf_t *cf) *h = ngx_stream_ssl_handler; + if (cmcf->ports == NULL) { + return NGX_OK; + } + + port = cmcf->ports->elts; + for (p = 0; p < cmcf->ports->nelts; p++) { + + addr = port[p].addrs.elts; + for (a = 0; a < port[p].addrs.nelts; a++) { + + if (!addr[a].opt.ssl) { + continue; + } + + cscf = addr[a].default_server; + sscf = cscf->ctx->srv_conf[ngx_stream_ssl_module.ctx_index]; + + if (sscf->certificates) { + continue; + } + + if (!sscf->reject_handshake) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no \"ssl_certificate\" is defined for " + "the \"listen ... ssl\" directive in %s:%ui", + cscf->file_name, cscf->line); + return NGX_ERROR; + } + + /* + * if no certificates are defined in the default server, + * check all non-default server blocks + */ + + cscfp = addr[a].servers.elts; + for (s = 0; s < addr[a].servers.nelts; s++) { + + cscf = cscfp[s]; + sscf = cscf->ctx->srv_conf[ngx_stream_ssl_module.ctx_index]; + + if (sscf->certificates || sscf->reject_handshake) { + continue; + } + + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no \"ssl_certificate\" is defined for " + "the \"listen ... ssl\" directive in %s:%ui", + cscf->file_name, cscf->line); + return NGX_ERROR; + } + } + } + return NGX_OK; } |