# HG changeset patch # User Maxim Dounin # Date 1620256929 -10800 # Node ID 3ab8e1e2f0f7ec6527003047565f4470e1e294b8 # Parent be82e72c9af892d8477e2d7338f5d9f5995c1f25 Upstream: variables support in certificates. diff --git a/src/http/modules/ngx_http_grpc_module.c b/src/http/modules/ngx_http_grpc_module.c --- a/src/http/modules/ngx_http_grpc_module.c +++ b/src/http/modules/ngx_http_grpc_module.c @@ -37,9 +37,6 @@ typedef struct { ngx_uint_t ssl_verify_depth; ngx_str_t ssl_trusted_certificate; ngx_str_t ssl_crl; - ngx_str_t ssl_certificate; - ngx_str_t ssl_certificate_key; - ngx_array_t *ssl_passwords; ngx_array_t *ssl_conf_commands; #endif } ngx_http_grpc_loc_conf_t; @@ -425,16 +422,16 @@ static ngx_command_t ngx_http_grpc_comm { ngx_string("grpc_ssl_certificate"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_http_set_complex_value_zero_slot, NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_grpc_loc_conf_t, ssl_certificate), + offsetof(ngx_http_grpc_loc_conf_t, upstream.ssl_certificate), NULL }, { ngx_string("grpc_ssl_certificate_key"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_http_set_complex_value_zero_slot, NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_grpc_loc_conf_t, ssl_certificate_key), + offsetof(ngx_http_grpc_loc_conf_t, upstream.ssl_certificate_key), NULL }, { ngx_string("grpc_ssl_password_file"), @@ -4342,8 +4339,6 @@ ngx_http_grpc_create_loc_conf(ngx_conf_t * conf->ssl_ciphers = { 0, NULL }; * conf->ssl_trusted_certificate = { 0, NULL }; * conf->ssl_crl = { 0, NULL }; - * conf->ssl_certificate = { 0, NULL }; - * conf->ssl_certificate_key = { 0, NULL }; */ conf->upstream.local = NGX_CONF_UNSET_PTR; @@ -4367,7 +4362,9 @@ ngx_http_grpc_create_loc_conf(ngx_conf_t conf->upstream.ssl_server_name = NGX_CONF_UNSET; conf->upstream.ssl_verify = NGX_CONF_UNSET; conf->ssl_verify_depth = NGX_CONF_UNSET_UINT; - conf->ssl_passwords = NGX_CONF_UNSET_PTR; + conf->upstream.ssl_certificate = NGX_CONF_UNSET_PTR; + conf->upstream.ssl_certificate_key = NGX_CONF_UNSET_PTR; + conf->upstream.ssl_passwords = NGX_CONF_UNSET_PTR; conf->ssl_conf_commands = NGX_CONF_UNSET_PTR; #endif @@ -4471,11 +4468,12 @@ ngx_http_grpc_merge_loc_conf(ngx_conf_t prev->ssl_trusted_certificate, ""); ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, ""); - ngx_conf_merge_str_value(conf->ssl_certificate, - prev->ssl_certificate, ""); - ngx_conf_merge_str_value(conf->ssl_certificate_key, - prev->ssl_certificate_key, ""); - ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL); + ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate, + prev->upstream.ssl_certificate, NULL); + ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate_key, + prev->upstream.ssl_certificate_key, NULL); + ngx_conf_merge_ptr_value(conf->upstream.ssl_passwords, + prev->upstream.ssl_passwords, NULL); ngx_conf_merge_ptr_value(conf->ssl_conf_commands, prev->ssl_conf_commands, NULL); @@ -4831,15 +4829,15 @@ ngx_http_grpc_ssl_password_file(ngx_conf ngx_str_t *value; - if (glcf->ssl_passwords != NGX_CONF_UNSET_PTR) { + if (glcf->upstream.ssl_passwords != NGX_CONF_UNSET_PTR) { return "is duplicate"; } value = cf->args->elts; - glcf->ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]); - - if (glcf->ssl_passwords == NULL) { + glcf->upstream.ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]); + + if (glcf->upstream.ssl_passwords == NULL) { return NGX_CONF_ERROR; } @@ -4885,20 +4883,34 @@ ngx_http_grpc_set_ssl(ngx_conf_t *cf, ng cln->handler = ngx_ssl_cleanup_ctx; cln->data = glcf->upstream.ssl; - if (glcf->ssl_certificate.len) { - - if (glcf->ssl_certificate_key.len == 0) { + if (glcf->upstream.ssl_certificate) { + + if (glcf->upstream.ssl_certificate_key == NULL) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"grpc_ssl_certificate_key\" is defined " - "for certificate \"%V\"", &glcf->ssl_certificate); + "for certificate \"%V\"", + &glcf->upstream.ssl_certificate->value); return NGX_ERROR; } - if (ngx_ssl_certificate(cf, glcf->upstream.ssl, &glcf->ssl_certificate, - &glcf->ssl_certificate_key, glcf->ssl_passwords) - != NGX_OK) + if (glcf->upstream.ssl_certificate->lengths + || glcf->upstream.ssl_certificate_key->lengths) { - return NGX_ERROR; + glcf->upstream.ssl_passwords = + ngx_ssl_preserve_passwords(cf, glcf->upstream.ssl_passwords); + if (glcf->upstream.ssl_passwords == NULL) { + return NGX_ERROR; + } + + } else { + if (ngx_ssl_certificate(cf, glcf->upstream.ssl, + &glcf->upstream.ssl_certificate->value, + &glcf->upstream.ssl_certificate_key->value, + glcf->upstream.ssl_passwords) + != NGX_OK) + { + return NGX_ERROR; + } } } diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -124,9 +124,6 @@ typedef struct { ngx_uint_t ssl_verify_depth; ngx_str_t ssl_trusted_certificate; ngx_str_t ssl_crl; - ngx_str_t ssl_certificate; - ngx_str_t ssl_certificate_key; - ngx_array_t *ssl_passwords; ngx_array_t *ssl_conf_commands; #endif } ngx_http_proxy_loc_conf_t; @@ -753,16 +750,16 @@ static ngx_command_t ngx_http_proxy_com { ngx_string("proxy_ssl_certificate"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_http_set_complex_value_zero_slot, NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_proxy_loc_conf_t, ssl_certificate), + offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_certificate), NULL }, { ngx_string("proxy_ssl_certificate_key"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_http_set_complex_value_zero_slot, NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_proxy_loc_conf_t, ssl_certificate_key), + offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_certificate_key), NULL }, { ngx_string("proxy_ssl_password_file"), @@ -3345,8 +3342,6 @@ ngx_http_proxy_create_loc_conf(ngx_conf_ * conf->ssl_ciphers = { 0, NULL }; * conf->ssl_trusted_certificate = { 0, NULL }; * conf->ssl_crl = { 0, NULL }; - * conf->ssl_certificate = { 0, NULL }; - * conf->ssl_certificate_key = { 0, NULL }; */ conf->upstream.store = NGX_CONF_UNSET; @@ -3401,8 +3396,10 @@ ngx_http_proxy_create_loc_conf(ngx_conf_ conf->upstream.ssl_name = NGX_CONF_UNSET_PTR; conf->upstream.ssl_server_name = NGX_CONF_UNSET; conf->upstream.ssl_verify = NGX_CONF_UNSET; + conf->upstream.ssl_certificate = NGX_CONF_UNSET_PTR; + conf->upstream.ssl_certificate_key = NGX_CONF_UNSET_PTR; + conf->upstream.ssl_passwords = NGX_CONF_UNSET_PTR; conf->ssl_verify_depth = NGX_CONF_UNSET_UINT; - conf->ssl_passwords = NGX_CONF_UNSET_PTR; conf->ssl_conf_commands = NGX_CONF_UNSET_PTR; #endif @@ -3742,11 +3739,12 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t prev->ssl_trusted_certificate, ""); ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, ""); - ngx_conf_merge_str_value(conf->ssl_certificate, - prev->ssl_certificate, ""); - ngx_conf_merge_str_value(conf->ssl_certificate_key, - prev->ssl_certificate_key, ""); - ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL); + ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate, + prev->upstream.ssl_certificate, NULL); + ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate_key, + prev->upstream.ssl_certificate_key, NULL); + ngx_conf_merge_ptr_value(conf->upstream.ssl_passwords, + prev->upstream.ssl_passwords, NULL); ngx_conf_merge_ptr_value(conf->ssl_conf_commands, prev->ssl_conf_commands, NULL); @@ -4857,15 +4855,15 @@ ngx_http_proxy_ssl_password_file(ngx_con ngx_str_t *value; - if (plcf->ssl_passwords != NGX_CONF_UNSET_PTR) { + if (plcf->upstream.ssl_passwords != NGX_CONF_UNSET_PTR) { return "is duplicate"; } value = cf->args->elts; - plcf->ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]); - - if (plcf->ssl_passwords == NULL) { + plcf->upstream.ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]); + + if (plcf->upstream.ssl_passwords == NULL) { return NGX_CONF_ERROR; } @@ -4944,20 +4942,34 @@ ngx_http_proxy_set_ssl(ngx_conf_t *cf, n cln->handler = ngx_ssl_cleanup_ctx; cln->data = plcf->upstream.ssl; - if (plcf->ssl_certificate.len) { - - if (plcf->ssl_certificate_key.len == 0) { + if (plcf->upstream.ssl_certificate) { + + if (plcf->upstream.ssl_certificate_key == NULL) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"proxy_ssl_certificate_key\" is defined " - "for certificate \"%V\"", &plcf->ssl_certificate); + "for certificate \"%V\"", + &plcf->upstream.ssl_certificate->value); return NGX_ERROR; } - if (ngx_ssl_certificate(cf, plcf->upstream.ssl, &plcf->ssl_certificate, - &plcf->ssl_certificate_key, plcf->ssl_passwords) - != NGX_OK) + if (plcf->upstream.ssl_certificate->lengths + || plcf->upstream.ssl_certificate_key->lengths) { - return NGX_ERROR; + plcf->upstream.ssl_passwords = + ngx_ssl_preserve_passwords(cf, plcf->upstream.ssl_passwords); + if (plcf->upstream.ssl_passwords == NULL) { + return NGX_ERROR; + } + + } else { + if (ngx_ssl_certificate(cf, plcf->upstream.ssl, + &plcf->upstream.ssl_certificate->value, + &plcf->upstream.ssl_certificate_key->value, + plcf->upstream.ssl_passwords) + != NGX_OK) + { + return NGX_ERROR; + } } } diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c --- a/src/http/modules/ngx_http_uwsgi_module.c +++ b/src/http/modules/ngx_http_uwsgi_module.c @@ -54,9 +54,6 @@ typedef struct { ngx_uint_t ssl_verify_depth; ngx_str_t ssl_trusted_certificate; ngx_str_t ssl_crl; - ngx_str_t ssl_certificate; - ngx_str_t ssl_certificate_key; - ngx_array_t *ssl_passwords; ngx_array_t *ssl_conf_commands; #endif } ngx_http_uwsgi_loc_conf_t; @@ -548,16 +545,16 @@ static ngx_command_t ngx_http_uwsgi_comm { ngx_string("uwsgi_ssl_certificate"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_http_set_complex_value_zero_slot, NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_uwsgi_loc_conf_t, ssl_certificate), + offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_certificate), NULL }, { ngx_string("uwsgi_ssl_certificate_key"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_http_set_complex_value_zero_slot, NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_uwsgi_loc_conf_t, ssl_certificate_key), + offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_certificate_key), NULL }, { ngx_string("uwsgi_ssl_password_file"), @@ -1513,7 +1510,9 @@ ngx_http_uwsgi_create_loc_conf(ngx_conf_ conf->upstream.ssl_server_name = NGX_CONF_UNSET; conf->upstream.ssl_verify = NGX_CONF_UNSET; conf->ssl_verify_depth = NGX_CONF_UNSET_UINT; - conf->ssl_passwords = NGX_CONF_UNSET_PTR; + conf->upstream.ssl_certificate = NGX_CONF_UNSET_PTR; + conf->upstream.ssl_certificate_key = NGX_CONF_UNSET_PTR; + conf->upstream.ssl_passwords = NGX_CONF_UNSET_PTR; conf->ssl_conf_commands = NGX_CONF_UNSET_PTR; #endif @@ -1837,11 +1836,12 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t prev->ssl_trusted_certificate, ""); ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, ""); - ngx_conf_merge_str_value(conf->ssl_certificate, - prev->ssl_certificate, ""); - ngx_conf_merge_str_value(conf->ssl_certificate_key, - prev->ssl_certificate_key, ""); - ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL); + ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate, + prev->upstream.ssl_certificate, NULL); + ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate_key, + prev->upstream.ssl_certificate_key, NULL); + ngx_conf_merge_ptr_value(conf->upstream.ssl_passwords, + prev->upstream.ssl_passwords, NULL); ngx_conf_merge_ptr_value(conf->ssl_conf_commands, prev->ssl_conf_commands, NULL); @@ -2376,15 +2376,15 @@ ngx_http_uwsgi_ssl_password_file(ngx_con ngx_str_t *value; - if (uwcf->ssl_passwords != NGX_CONF_UNSET_PTR) { + if (uwcf->upstream.ssl_passwords != NGX_CONF_UNSET_PTR) { return "is duplicate"; } value = cf->args->elts; - uwcf->ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]); - - if (uwcf->ssl_passwords == NULL) { + uwcf->upstream.ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]); + + if (uwcf->upstream.ssl_passwords == NULL) { return NGX_CONF_ERROR; } @@ -2430,20 +2430,34 @@ ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, n cln->handler = ngx_ssl_cleanup_ctx; cln->data = uwcf->upstream.ssl; - if (uwcf->ssl_certificate.len) { - - if (uwcf->ssl_certificate_key.len == 0) { + if (uwcf->upstream.ssl_certificate) { + + if (uwcf->upstream.ssl_certificate_key == NULL) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"uwsgi_ssl_certificate_key\" is defined " - "for certificate \"%V\"", &uwcf->ssl_certificate); + "for certificate \"%V\"", + &uwcf->upstream.ssl_certificate->value); return NGX_ERROR; } - if (ngx_ssl_certificate(cf, uwcf->upstream.ssl, &uwcf->ssl_certificate, - &uwcf->ssl_certificate_key, uwcf->ssl_passwords) - != NGX_OK) + if (uwcf->upstream.ssl_certificate->lengths + || uwcf->upstream.ssl_certificate_key->lengths) { - return NGX_ERROR; + uwcf->upstream.ssl_passwords = + ngx_ssl_preserve_passwords(cf, uwcf->upstream.ssl_passwords); + if (uwcf->upstream.ssl_passwords == NULL) { + return NGX_ERROR; + } + + } else { + if (ngx_ssl_certificate(cf, uwcf->upstream.ssl, + &uwcf->upstream.ssl_certificate->value, + &uwcf->upstream.ssl_certificate_key->value, + uwcf->upstream.ssl_passwords) + != NGX_OK) + { + return NGX_ERROR; + } } } diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c --- a/src/http/ngx_http_script.c +++ b/src/http/ngx_http_script.c @@ -276,6 +276,44 @@ ngx_http_set_complex_value_slot(ngx_conf char * +ngx_http_set_complex_value_zero_slot(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + char *p = conf; + + ngx_str_t *value; + ngx_http_complex_value_t **cv; + ngx_http_compile_complex_value_t ccv; + + cv = (ngx_http_complex_value_t **) (p + cmd->offset); + + if (*cv != NGX_CONF_UNSET_PTR) { + return "is duplicate"; + } + + *cv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); + if (*cv == NULL) { + return NGX_CONF_ERROR; + } + + value = cf->args->elts; + + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = *cv; + ccv.zero = 1; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + + +char * ngx_http_set_complex_value_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { diff --git a/src/http/ngx_http_script.h b/src/http/ngx_http_script.h --- a/src/http/ngx_http_script.h +++ b/src/http/ngx_http_script.h @@ -216,6 +216,8 @@ size_t ngx_http_complex_value_size(ngx_h ngx_int_t ngx_http_compile_complex_value(ngx_http_compile_complex_value_t *ccv); char *ngx_http_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +char *ngx_http_set_complex_value_zero_slot(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); char *ngx_http_set_complex_value_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -187,6 +187,8 @@ static void ngx_http_upstream_ssl_handsh static void ngx_http_upstream_ssl_save_session(ngx_connection_t *c); static ngx_int_t ngx_http_upstream_ssl_name(ngx_http_request_t *r, ngx_http_upstream_t *u, ngx_connection_t *c); +static ngx_int_t ngx_http_upstream_ssl_certificate(ngx_http_request_t *r, + ngx_http_upstream_t *u, ngx_connection_t *c); #endif @@ -1692,6 +1694,16 @@ ngx_http_upstream_ssl_init_connection(ng } } + if (u->conf->ssl_certificate && (u->conf->ssl_certificate->lengths + || u->conf->ssl_certificate_key->lengths)) + { + if (ngx_http_upstream_ssl_certificate(r, u, c) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + } + if (u->conf->ssl_session_reuse) { c->ssl->save_session = ngx_http_upstream_ssl_save_session; @@ -1912,6 +1924,45 @@ done: return NGX_OK; } + +static ngx_int_t +ngx_http_upstream_ssl_certificate(ngx_http_request_t *r, + ngx_http_upstream_t *u, ngx_connection_t *c) +{ + ngx_str_t cert, key; + + if (ngx_http_complex_value(r, u->conf->ssl_certificate, &cert) + != NGX_OK) + { + return NGX_ERROR; + } + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http upstream ssl cert: \"%s\"", cert.data); + + if (*cert.data == '\0') { + return NGX_OK; + } + + if (ngx_http_complex_value(r, u->conf->ssl_certificate_key, &key) + != NGX_OK) + { + return NGX_ERROR; + } + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http upstream ssl key: \"%s\"", key.data); + + if (ngx_ssl_connection_certificate(c, r->pool, &cert, &key, + u->conf->ssl_passwords) + != NGX_OK) + { + return NGX_ERROR; + } + + return NGX_OK; +} + #endif diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -234,6 +234,10 @@ typedef struct { ngx_http_complex_value_t *ssl_name; ngx_flag_t ssl_server_name; ngx_flag_t ssl_verify; + + ngx_http_complex_value_t *ssl_certificate; + ngx_http_complex_value_t *ssl_certificate_key; + ngx_array_t *ssl_passwords; #endif ngx_str_t module; diff --git a/src/stream/ngx_stream_proxy_module.c b/src/stream/ngx_stream_proxy_module.c --- a/src/stream/ngx_stream_proxy_module.c +++ b/src/stream/ngx_stream_proxy_module.c @@ -46,8 +46,8 @@ typedef struct { ngx_uint_t ssl_verify_depth; ngx_str_t ssl_trusted_certificate; ngx_str_t ssl_crl; - ngx_str_t ssl_certificate; - ngx_str_t ssl_certificate_key; + ngx_stream_complex_value_t *ssl_certificate; + ngx_stream_complex_value_t *ssl_certificate_key; ngx_array_t *ssl_passwords; ngx_array_t *ssl_conf_commands; @@ -101,6 +101,7 @@ static void ngx_stream_proxy_ssl_init_co static void ngx_stream_proxy_ssl_handshake(ngx_connection_t *pc); static void ngx_stream_proxy_ssl_save_session(ngx_connection_t *c); static ngx_int_t ngx_stream_proxy_ssl_name(ngx_stream_session_t *s); +static ngx_int_t ngx_stream_proxy_ssl_certificate(ngx_stream_session_t *s); static ngx_int_t ngx_stream_proxy_set_ssl(ngx_conf_t *cf, ngx_stream_proxy_srv_conf_t *pscf); @@ -318,14 +319,14 @@ static ngx_command_t ngx_stream_proxy_c { ngx_string("proxy_ssl_certificate"), NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_stream_set_complex_value_zero_slot, NGX_STREAM_SRV_CONF_OFFSET, offsetof(ngx_stream_proxy_srv_conf_t, ssl_certificate), NULL }, { ngx_string("proxy_ssl_certificate_key"), NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_stream_set_complex_value_zero_slot, NGX_STREAM_SRV_CONF_OFFSET, offsetof(ngx_stream_proxy_srv_conf_t, ssl_certificate_key), NULL }, @@ -1060,6 +1061,15 @@ ngx_stream_proxy_ssl_init_connection(ngx } } + if (pscf->ssl_certificate && (pscf->ssl_certificate->lengths + || pscf->ssl_certificate_key->lengths)) + { + if (ngx_stream_proxy_ssl_certificate(s) != NGX_OK) { + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); + return; + } + } + if (pscf->ssl_session_reuse) { pc->ssl->save_session = ngx_stream_proxy_ssl_save_session; @@ -1247,6 +1257,50 @@ done: return NGX_OK; } + +static ngx_int_t +ngx_stream_proxy_ssl_certificate(ngx_stream_session_t *s) +{ + ngx_str_t cert, key; + ngx_connection_t *c; + ngx_stream_proxy_srv_conf_t *pscf; + + c = s->upstream->peer.connection; + + pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module); + + if (ngx_stream_complex_value(s, pscf->ssl_certificate, &cert) + != NGX_OK) + { + return NGX_ERROR; + } + + ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, + "stream upstream ssl cert: \"%s\"", cert.data); + + if (*cert.data == '\0') { + return NGX_OK; + } + + if (ngx_stream_complex_value(s, pscf->ssl_certificate_key, &key) + != NGX_OK) + { + return NGX_ERROR; + } + + ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, + "stream upstream ssl key: \"%s\"", key.data); + + if (ngx_ssl_connection_certificate(c, c->pool, &cert, &key, + pscf->ssl_passwords) + != NGX_OK) + { + return NGX_ERROR; + } + + return NGX_OK; +} + #endif @@ -1979,8 +2033,6 @@ ngx_stream_proxy_create_srv_conf(ngx_con * conf->ssl_ciphers = { 0, NULL }; * conf->ssl_trusted_certificate = { 0, NULL }; * conf->ssl_crl = { 0, NULL }; - * conf->ssl_certificate = { 0, NULL }; - * conf->ssl_certificate_key = { 0, NULL }; * * conf->ssl = NULL; * conf->upstream = NULL; @@ -2008,6 +2060,8 @@ ngx_stream_proxy_create_srv_conf(ngx_con conf->ssl_server_name = NGX_CONF_UNSET; conf->ssl_verify = NGX_CONF_UNSET; conf->ssl_verify_depth = NGX_CONF_UNSET_UINT; + conf->ssl_certificate = NGX_CONF_UNSET_PTR; + conf->ssl_certificate_key = NGX_CONF_UNSET_PTR; conf->ssl_passwords = NGX_CONF_UNSET_PTR; conf->ssl_conf_commands = NGX_CONF_UNSET_PTR; #endif @@ -2083,11 +2137,11 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, ""); - ngx_conf_merge_str_value(conf->ssl_certificate, - prev->ssl_certificate, ""); - - ngx_conf_merge_str_value(conf->ssl_certificate_key, - prev->ssl_certificate_key, ""); + ngx_conf_merge_ptr_value(conf->ssl_certificate, + prev->ssl_certificate, NULL); + + ngx_conf_merge_ptr_value(conf->ssl_certificate_key, + prev->ssl_certificate_key, NULL); ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL); @@ -2131,20 +2185,34 @@ ngx_stream_proxy_set_ssl(ngx_conf_t *cf, cln->handler = ngx_ssl_cleanup_ctx; cln->data = pscf->ssl; - if (pscf->ssl_certificate.len) { - - if (pscf->ssl_certificate_key.len == 0) { + if (pscf->ssl_certificate) { + + if (pscf->ssl_certificate_key == NULL) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"proxy_ssl_certificate_key\" is defined " - "for certificate \"%V\"", &pscf->ssl_certificate); + "for certificate \"%V\"", + &pscf->ssl_certificate->value); return NGX_ERROR; } - if (ngx_ssl_certificate(cf, pscf->ssl, &pscf->ssl_certificate, - &pscf->ssl_certificate_key, pscf->ssl_passwords) - != NGX_OK) + if (pscf->ssl_certificate->lengths + || pscf->ssl_certificate_key->lengths) { - return NGX_ERROR; + pscf->ssl_passwords = + ngx_ssl_preserve_passwords(cf, pscf->ssl_passwords); + if (pscf->ssl_passwords == NULL) { + return NGX_ERROR; + } + + } else { + if (ngx_ssl_certificate(cf, pscf->ssl, + &pscf->ssl_certificate->value, + &pscf->ssl_certificate_key->value, + pscf->ssl_passwords) + != NGX_OK) + { + return NGX_ERROR; + } } } diff --git a/src/stream/ngx_stream_script.c b/src/stream/ngx_stream_script.c --- a/src/stream/ngx_stream_script.c +++ b/src/stream/ngx_stream_script.c @@ -278,6 +278,44 @@ ngx_stream_set_complex_value_slot(ngx_co char * +ngx_stream_set_complex_value_zero_slot(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + char *p = conf; + + ngx_str_t *value; + ngx_stream_complex_value_t **cv; + ngx_stream_compile_complex_value_t ccv; + + cv = (ngx_stream_complex_value_t **) (p + cmd->offset); + + if (*cv != NGX_CONF_UNSET_PTR) { + return "is duplicate"; + } + + *cv = ngx_palloc(cf->pool, sizeof(ngx_stream_complex_value_t)); + if (*cv == NULL) { + return NGX_CONF_ERROR; + } + + value = cf->args->elts; + + ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = *cv; + ccv.zero = 1; + + if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + + +char * ngx_stream_set_complex_value_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { diff --git a/src/stream/ngx_stream_script.h b/src/stream/ngx_stream_script.h --- a/src/stream/ngx_stream_script.h +++ b/src/stream/ngx_stream_script.h @@ -112,6 +112,8 @@ ngx_int_t ngx_stream_compile_complex_val ngx_stream_compile_complex_value_t *ccv); char *ngx_stream_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +char *ngx_stream_set_complex_value_zero_slot(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); char *ngx_stream_set_complex_value_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);