mirror of
https://github.com/nginx/nginx.git
synced 2025-06-07 17:52:38 +08:00
SSL: variables support in ssl_certificate and ssl_certificate_key.
To evaluate variables, a request is created in the certificate callback, and then freed. To do this without side effects on the stub_status counters and connection state, an additional function was introduced, ngx_http_alloc_request(). Only works with OpenSSL 1.0.2+, since there is no SSL_CTX_set_cert_cb() in older versions.
This commit is contained in:
parent
9ff7ba3d00
commit
6e5a731edb
@ -41,6 +41,9 @@ static void *ngx_http_ssl_create_srv_conf(ngx_conf_t *cf);
|
|||||||
static char *ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf,
|
static char *ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf,
|
||||||
void *parent, void *child);
|
void *parent, void *child);
|
||||||
|
|
||||||
|
static ngx_int_t ngx_http_ssl_compile_certificates(ngx_conf_t *cf,
|
||||||
|
ngx_http_ssl_srv_conf_t *conf);
|
||||||
|
|
||||||
static char *ngx_http_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd,
|
static char *ngx_http_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||||
void *conf);
|
void *conf);
|
||||||
static char *ngx_http_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
|
static char *ngx_http_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||||
@ -550,6 +553,7 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
|
|||||||
* set by ngx_pcalloc():
|
* set by ngx_pcalloc():
|
||||||
*
|
*
|
||||||
* sscf->protocols = 0;
|
* sscf->protocols = 0;
|
||||||
|
* sscf->certificate_values = NULL;
|
||||||
* sscf->dhparam = { 0, NULL };
|
* sscf->dhparam = { 0, NULL };
|
||||||
* sscf->ecdh_curve = { 0, NULL };
|
* sscf->ecdh_curve = { 0, NULL };
|
||||||
* sscf->client_certificate = { 0, NULL };
|
* sscf->client_certificate = { 0, NULL };
|
||||||
@ -727,12 +731,37 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
cln->handler = ngx_ssl_cleanup_ctx;
|
cln->handler = ngx_ssl_cleanup_ctx;
|
||||||
cln->data = &conf->ssl;
|
cln->data = &conf->ssl;
|
||||||
|
|
||||||
|
if (ngx_http_ssl_compile_certificates(cf, conf) != NGX_OK) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conf->certificate_values) {
|
||||||
|
|
||||||
|
#ifdef SSL_R_CERT_CB_ERROR
|
||||||
|
|
||||||
|
/* install callback to lookup certificates */
|
||||||
|
|
||||||
|
SSL_CTX_set_cert_cb(conf->ssl.ctx, ngx_http_ssl_certificate, NULL);
|
||||||
|
|
||||||
|
#else
|
||||||
|
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
||||||
|
"variables in "
|
||||||
|
"\"ssl_certificate\" and \"ssl_certificate_key\" "
|
||||||
|
"directives are not supported on this platform");
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* configure certificates */
|
||||||
|
|
||||||
if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates,
|
if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates,
|
||||||
conf->certificate_keys, conf->passwords)
|
conf->certificate_keys, conf->passwords)
|
||||||
!= NGX_OK)
|
!= NGX_OK)
|
||||||
{
|
{
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers,
|
if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers,
|
||||||
conf->prefer_server_ciphers)
|
conf->prefer_server_ciphers)
|
||||||
@ -831,6 +860,85 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_ssl_compile_certificates(ngx_conf_t *cf,
|
||||||
|
ngx_http_ssl_srv_conf_t *conf)
|
||||||
|
{
|
||||||
|
ngx_str_t *cert, *key;
|
||||||
|
ngx_uint_t i, nelts;
|
||||||
|
ngx_http_complex_value_t *cv;
|
||||||
|
ngx_http_compile_complex_value_t ccv;
|
||||||
|
|
||||||
|
cert = conf->certificates->elts;
|
||||||
|
key = conf->certificate_keys->elts;
|
||||||
|
nelts = conf->certificates->nelts;
|
||||||
|
|
||||||
|
for (i = 0; i < nelts; i++) {
|
||||||
|
|
||||||
|
if (ngx_http_script_variables_count(&cert[i])) {
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_http_script_variables_count(&key[i])) {
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
|
||||||
|
found:
|
||||||
|
|
||||||
|
conf->certificate_values = ngx_array_create(cf->pool, nelts,
|
||||||
|
sizeof(ngx_http_complex_value_t));
|
||||||
|
if (conf->certificate_values == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
conf->certificate_key_values = ngx_array_create(cf->pool, nelts,
|
||||||
|
sizeof(ngx_http_complex_value_t));
|
||||||
|
if (conf->certificate_key_values == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < nelts; i++) {
|
||||||
|
|
||||||
|
cv = ngx_array_push(conf->certificate_values);
|
||||||
|
if (cv == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
|
||||||
|
|
||||||
|
ccv.cf = cf;
|
||||||
|
ccv.value = &cert[i];
|
||||||
|
ccv.complex_value = cv;
|
||||||
|
ccv.zero = 1;
|
||||||
|
|
||||||
|
if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
cv = ngx_array_push(conf->certificate_key_values);
|
||||||
|
if (cv == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
|
||||||
|
|
||||||
|
ccv.cf = cf;
|
||||||
|
ccv.value = &key[i];
|
||||||
|
ccv.complex_value = cv;
|
||||||
|
ccv.zero = 1;
|
||||||
|
|
||||||
|
if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
ngx_http_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
ngx_http_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
{
|
{
|
||||||
|
@ -36,6 +36,9 @@ typedef struct {
|
|||||||
ngx_array_t *certificates;
|
ngx_array_t *certificates;
|
||||||
ngx_array_t *certificate_keys;
|
ngx_array_t *certificate_keys;
|
||||||
|
|
||||||
|
ngx_array_t *certificate_values;
|
||||||
|
ngx_array_t *certificate_key_values;
|
||||||
|
|
||||||
ngx_str_t dhparam;
|
ngx_str_t dhparam;
|
||||||
ngx_str_t ecdh_curve;
|
ngx_str_t ecdh_curve;
|
||||||
ngx_str_t client_certificate;
|
ngx_str_t client_certificate;
|
||||||
|
@ -88,6 +88,10 @@ void ngx_http_close_connection(ngx_connection_t *c);
|
|||||||
#if (NGX_HTTP_SSL && defined SSL_CTRL_SET_TLSEXT_HOSTNAME)
|
#if (NGX_HTTP_SSL && defined SSL_CTRL_SET_TLSEXT_HOSTNAME)
|
||||||
int ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg);
|
int ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg);
|
||||||
#endif
|
#endif
|
||||||
|
#if (NGX_HTTP_SSL && defined SSL_R_CERT_CB_ERROR)
|
||||||
|
int ngx_http_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
ngx_int_t ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b);
|
ngx_int_t ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b);
|
||||||
ngx_int_t ngx_http_parse_uri(ngx_http_request_t *r);
|
ngx_int_t ngx_http_parse_uri(ngx_http_request_t *r);
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
|
|
||||||
static void ngx_http_wait_request_handler(ngx_event_t *ev);
|
static void ngx_http_wait_request_handler(ngx_event_t *ev);
|
||||||
|
static ngx_http_request_t *ngx_http_alloc_request(ngx_connection_t *c);
|
||||||
static void ngx_http_process_request_line(ngx_event_t *rev);
|
static void ngx_http_process_request_line(ngx_event_t *rev);
|
||||||
static void ngx_http_process_request_headers(ngx_event_t *rev);
|
static void ngx_http_process_request_headers(ngx_event_t *rev);
|
||||||
static ssize_t ngx_http_read_request_header(ngx_http_request_t *r);
|
static ssize_t ngx_http_read_request_header(ngx_http_request_t *r);
|
||||||
@ -502,18 +503,46 @@ ngx_http_wait_request_handler(ngx_event_t *rev)
|
|||||||
|
|
||||||
ngx_http_request_t *
|
ngx_http_request_t *
|
||||||
ngx_http_create_request(ngx_connection_t *c)
|
ngx_http_create_request(ngx_connection_t *c)
|
||||||
|
{
|
||||||
|
ngx_http_request_t *r;
|
||||||
|
ngx_http_log_ctx_t *ctx;
|
||||||
|
ngx_http_core_loc_conf_t *clcf;
|
||||||
|
|
||||||
|
r = ngx_http_alloc_request(c);
|
||||||
|
if (r == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->requests++;
|
||||||
|
|
||||||
|
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
|
||||||
|
|
||||||
|
ngx_set_connection_log(c, clcf->error_log);
|
||||||
|
|
||||||
|
ctx = c->log->data;
|
||||||
|
ctx->request = r;
|
||||||
|
ctx->current_request = r;
|
||||||
|
|
||||||
|
#if (NGX_STAT_STUB)
|
||||||
|
(void) ngx_atomic_fetch_add(ngx_stat_reading, 1);
|
||||||
|
r->stat_reading = 1;
|
||||||
|
(void) ngx_atomic_fetch_add(ngx_stat_requests, 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_http_request_t *
|
||||||
|
ngx_http_alloc_request(ngx_connection_t *c)
|
||||||
{
|
{
|
||||||
ngx_pool_t *pool;
|
ngx_pool_t *pool;
|
||||||
ngx_time_t *tp;
|
ngx_time_t *tp;
|
||||||
ngx_http_request_t *r;
|
ngx_http_request_t *r;
|
||||||
ngx_http_log_ctx_t *ctx;
|
|
||||||
ngx_http_connection_t *hc;
|
ngx_http_connection_t *hc;
|
||||||
ngx_http_core_srv_conf_t *cscf;
|
ngx_http_core_srv_conf_t *cscf;
|
||||||
ngx_http_core_loc_conf_t *clcf;
|
|
||||||
ngx_http_core_main_conf_t *cmcf;
|
ngx_http_core_main_conf_t *cmcf;
|
||||||
|
|
||||||
c->requests++;
|
|
||||||
|
|
||||||
hc = c->data;
|
hc = c->data;
|
||||||
|
|
||||||
cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_core_module);
|
cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_core_module);
|
||||||
@ -541,10 +570,6 @@ ngx_http_create_request(ngx_connection_t *c)
|
|||||||
|
|
||||||
r->read_event_handler = ngx_http_block_reading;
|
r->read_event_handler = ngx_http_block_reading;
|
||||||
|
|
||||||
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
|
|
||||||
|
|
||||||
ngx_set_connection_log(r->connection, clcf->error_log);
|
|
||||||
|
|
||||||
r->header_in = hc->busy ? hc->busy->buf : c->buffer;
|
r->header_in = hc->busy ? hc->busy->buf : c->buffer;
|
||||||
|
|
||||||
if (ngx_list_init(&r->headers_out.headers, r->pool, 20,
|
if (ngx_list_init(&r->headers_out.headers, r->pool, 20,
|
||||||
@ -604,17 +629,8 @@ ngx_http_create_request(ngx_connection_t *c)
|
|||||||
|
|
||||||
r->http_state = NGX_HTTP_READING_REQUEST_STATE;
|
r->http_state = NGX_HTTP_READING_REQUEST_STATE;
|
||||||
|
|
||||||
ctx = c->log->data;
|
|
||||||
ctx->request = r;
|
|
||||||
ctx->current_request = r;
|
|
||||||
r->log_handler = ngx_http_log_error_handler;
|
r->log_handler = ngx_http_log_error_handler;
|
||||||
|
|
||||||
#if (NGX_STAT_STUB)
|
|
||||||
(void) ngx_atomic_fetch_add(ngx_stat_reading, 1);
|
|
||||||
r->stat_reading = 1;
|
|
||||||
(void) ngx_atomic_fetch_add(ngx_stat_requests, 1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -931,6 +947,74 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef SSL_R_CERT_CB_ERROR
|
||||||
|
|
||||||
|
int
|
||||||
|
ngx_http_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg)
|
||||||
|
{
|
||||||
|
ngx_str_t cert, key;
|
||||||
|
ngx_uint_t i, nelts;
|
||||||
|
ngx_connection_t *c;
|
||||||
|
ngx_http_request_t *r;
|
||||||
|
ngx_http_ssl_srv_conf_t *sscf;
|
||||||
|
ngx_http_complex_value_t *certs, *keys;
|
||||||
|
|
||||||
|
c = ngx_ssl_get_connection(ssl_conn);
|
||||||
|
|
||||||
|
if (c->ssl->handshaked) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = ngx_http_alloc_request(c);
|
||||||
|
if (r == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r->logged = 1;
|
||||||
|
|
||||||
|
sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
|
||||||
|
|
||||||
|
nelts = sscf->certificate_values->nelts;
|
||||||
|
certs = sscf->certificate_values->elts;
|
||||||
|
keys = sscf->certificate_key_values->elts;
|
||||||
|
|
||||||
|
for (i = 0; i < nelts; i++) {
|
||||||
|
|
||||||
|
if (ngx_http_complex_value(r, &certs[i], &cert) != NGX_OK) {
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
||||||
|
"ssl cert: \"%s\"", cert.data);
|
||||||
|
|
||||||
|
if (ngx_http_complex_value(r, &keys[i], &key) != NGX_OK) {
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
||||||
|
"ssl key: \"%s\"", key.data);
|
||||||
|
|
||||||
|
if (ngx_ssl_connection_certificate(c, r->pool, &cert, &key, NULL)
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_http_free_request(r, 0);
|
||||||
|
c->destroyed = 0;
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
failed:
|
||||||
|
|
||||||
|
ngx_http_free_request(r, 0);
|
||||||
|
c->destroyed = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -3514,9 +3598,11 @@ ngx_http_free_request(ngx_http_request_t *r, ngx_int_t rc)
|
|||||||
r->headers_out.status = rc;
|
r->headers_out.status = rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!r->logged) {
|
||||||
log->action = "logging request";
|
log->action = "logging request";
|
||||||
|
|
||||||
ngx_http_log_request(r);
|
ngx_http_log_request(r);
|
||||||
|
}
|
||||||
|
|
||||||
log->action = "closing request";
|
log->action = "closing request";
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user