diff options
Diffstat (limited to 'src/http')
| -rw-r--r-- | src/http/modules/ngx_http_proxy_module.c | 62 | ||||
| -rw-r--r-- | src/http/ngx_http_upstream.c | 27 | ||||
| -rw-r--r-- | src/http/ngx_http_upstream.h | 1 |
3 files changed, 89 insertions, 1 deletions
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c index 7774f0f9a..cf7d677ae 100644 --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -81,6 +81,9 @@ typedef struct { ngx_uint_t ssl; ngx_uint_t ssl_protocols; ngx_str_t ssl_ciphers; + ngx_uint_t ssl_verify_depth; + ngx_str_t ssl_trusted_certificate; + ngx_str_t ssl_crl; #endif } ngx_http_proxy_loc_conf_t; @@ -567,6 +570,34 @@ static ngx_command_t ngx_http_proxy_commands[] = { offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_server_name), NULL }, + { ngx_string("proxy_ssl_verify"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_verify), + NULL }, + + { ngx_string("proxy_ssl_verify_depth"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_proxy_loc_conf_t, ssl_verify_depth), + NULL }, + + { ngx_string("proxy_ssl_trusted_certificate"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_proxy_loc_conf_t, ssl_trusted_certificate), + NULL }, + + { ngx_string("proxy_ssl_crl"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_proxy_loc_conf_t, ssl_crl), + NULL }, + #endif ngx_null_command @@ -2418,6 +2449,8 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf) * conf->ssl = 0; * conf->ssl_protocols = 0; * conf->ssl_ciphers = { 0, NULL }; + * conf->ssl_trusted_certificate = { 0, NULL }; + * conf->ssl_crl = { 0, NULL }; */ conf->upstream.store = NGX_CONF_UNSET; @@ -2460,6 +2493,8 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf) #if (NGX_HTTP_SSL) conf->upstream.ssl_session_reuse = NGX_CONF_UNSET; conf->upstream.ssl_server_name = NGX_CONF_UNSET; + conf->upstream.ssl_verify = NGX_CONF_UNSET; + conf->ssl_verify_depth = NGX_CONF_UNSET_UINT; #endif /* "proxy_cyclic_temp_file" is disabled */ @@ -2749,6 +2784,13 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_value(conf->upstream.ssl_server_name, prev->upstream.ssl_server_name, 0); + ngx_conf_merge_value(conf->upstream.ssl_verify, + prev->upstream.ssl_verify, 0); + ngx_conf_merge_uint_value(conf->ssl_verify_depth, + prev->ssl_verify_depth, 1); + ngx_conf_merge_str_value(conf->ssl_trusted_certificate, + prev->ssl_trusted_certificate, ""); + ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, ""); if (conf->ssl && ngx_http_proxy_set_ssl(cf, conf) != NGX_OK) { return NGX_CONF_ERROR; @@ -3818,6 +3860,26 @@ ngx_http_proxy_set_ssl(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *plcf) return NGX_ERROR; } + if (plcf->upstream.ssl_verify) { + if (plcf->ssl_trusted_certificate.len == 0) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no proxy_ssl_trusted_certificate for proxy_ssl_verify"); + return NGX_ERROR; + } + + if (ngx_ssl_trusted_certificate(cf, plcf->upstream.ssl, + &plcf->ssl_trusted_certificate, + plcf->ssl_verify_depth) + != NGX_OK) + { + return NGX_ERROR; + } + + if (ngx_ssl_crl(cf, plcf->upstream.ssl, &plcf->ssl_crl) != NGX_OK) { + return NGX_ERROR; + } + } + return NGX_OK; } diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index d9e381931..8069f5e12 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -1364,7 +1364,7 @@ ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r, c->sendfile = 0; u->output.sendfile = 0; - if (u->conf->ssl_server_name) { + if (u->conf->ssl_server_name || u->conf->ssl_verify) { if (ngx_http_upstream_ssl_name(r, u, c) != NGX_OK) { ngx_http_upstream_finalize_request(r, u, NGX_HTTP_INTERNAL_SERVER_ERROR); @@ -1396,6 +1396,7 @@ ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r, static void ngx_http_upstream_ssl_handshake(ngx_connection_t *c) { + long rc; ngx_http_request_t *r; ngx_http_upstream_t *u; @@ -1404,6 +1405,24 @@ ngx_http_upstream_ssl_handshake(ngx_connection_t *c) if (c->ssl->handshaked) { + if (u->conf->ssl_verify) { + rc = SSL_get_verify_result(c->ssl->connection); + + if (rc != X509_V_OK) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "upstream SSL certificate verify error: (%l:%s)", + rc, X509_verify_cert_error_string(rc)); + goto failed; + } + + if (ngx_ssl_check_host(c, &u->ssl_name) != NGX_OK) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "upstream SSL certificate does not match \"%V\"", + &u->ssl_name); + goto failed; + } + } + if (u->conf->ssl_session_reuse) { u->peer.save_session(&u->peer, u->peer.data); } @@ -1419,6 +1438,8 @@ ngx_http_upstream_ssl_handshake(ngx_connection_t *c) return; } +failed: + c = r->connection; ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR); @@ -1469,6 +1490,10 @@ ngx_http_upstream_ssl_name(ngx_http_request_t *r, ngx_http_upstream_t *u, name.len = p - name.data; } + if (!u->conf->ssl_server_name) { + goto done; + } + #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME /* as per RFC 6066, literal IPv4 and IPv6 addresses are not permitted */ diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h index 037f88d5f..b8998ced8 100644 --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -198,6 +198,7 @@ typedef struct { ngx_http_complex_value_t *ssl_name; ngx_flag_t ssl_server_name; + ngx_flag_t ssl_verify; #endif ngx_str_t module; |
