diff --git a/contrib/vim/syntax/nginx.vim b/contrib/vim/syntax/nginx.vim index 29eef7a23..4a20fd67b 100644 --- a/contrib/vim/syntax/nginx.vim +++ b/contrib/vim/syntax/nginx.vim @@ -592,6 +592,7 @@ syn keyword ngxDirective contained ssl_handshake_timeout syn keyword ngxDirective contained ssl_ocsp syn keyword ngxDirective contained ssl_ocsp_cache syn keyword ngxDirective contained ssl_ocsp_responder +syn keyword ngxDirective contained ssl_ocsp_responder_certificate syn keyword ngxDirective contained ssl_password_file syn keyword ngxDirective contained ssl_prefer_server_ciphers syn keyword ngxDirective contained ssl_preread diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h index 0c9e9e840..f847ce84f 100644 --- a/src/event/ngx_event_openssl.h +++ b/src/event/ngx_event_openssl.h @@ -248,7 +248,7 @@ ngx_int_t ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify); ngx_int_t ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_resolver_t *resolver, ngx_msec_t resolver_timeout); -ngx_int_t ngx_ssl_ocsp(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *responder, +ngx_int_t ngx_ssl_ocsp(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *responder, ngx_str_t *ocsp_responder_certificate, ngx_uint_t depth, ngx_shm_zone_t *shm_zone); ngx_int_t ngx_ssl_ocsp_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_resolver_t *resolver, ngx_msec_t resolver_timeout); diff --git a/src/event/ngx_event_openssl_stapling.c b/src/event/ngx_event_openssl_stapling.c index a0a8031c7..170395c32 100644 --- a/src/event/ngx_event_openssl_stapling.c +++ b/src/event/ngx_event_openssl_stapling.c @@ -57,6 +57,7 @@ typedef struct { ngx_shm_zone_t *shm_zone; ngx_resolver_t *resolver; + STACK_OF(X509) *responder_chain; ngx_msec_t resolver_timeout; } ngx_ssl_ocsp_conf_t; @@ -97,6 +98,7 @@ struct ngx_ssl_ocsp_ctx_s { X509 *cert; X509 *issuer; STACK_OF(X509) *chain; + STACK_OF(X509) *responder_chain; int status; time_t valid; @@ -804,7 +806,7 @@ ngx_ssl_stapling_cleanup(void *data) ngx_int_t -ngx_ssl_ocsp(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *responder, +ngx_ssl_ocsp(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *responder, ngx_str_t *ocsp_responder_certificate, ngx_uint_t depth, ngx_shm_zone_t *shm_zone) { ngx_url_t u; @@ -855,6 +857,24 @@ ngx_ssl_ocsp(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *responder, ocf->port = u.port; } + char *err; + STACK_OF(X509) *chain; + + if (ocsp_responder_certificate != NULL && ocsp_responder_certificate->len) { + chain = ngx_ssl_cache_fetch(cf, NGX_SSL_CACHE_CERT, &err, ocsp_responder_certificate, NULL); + if (chain == NULL) { + if (err != NULL) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "cannot load ocsp responder certificate \"%s\": %s", + ocsp_responder_certificate->data, err); + } + return NGX_ERROR; + } + else{ + ocf->responder_chain = chain; + } + } + if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_ocsp_index, ocf) == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_set_ex_data() failed"); @@ -1046,6 +1066,7 @@ ngx_ssl_ocsp_validate_next(ngx_connection_t *c) ctx->cert = sk_X509_value(ocsp->certs, ocsp->ncert); ctx->issuer = sk_X509_value(ocsp->certs, ocsp->ncert + 1); ctx->chain = ocsp->certs; + ctx->responder_chain = ocf->responder_chain; ctx->resolver = ocf->resolver; ctx->resolver_timeout = ocf->resolver_timeout; @@ -2408,10 +2429,20 @@ ngx_ssl_ocsp_verify(ngx_ssl_ocsp_ctx_t *ctx) goto error; } - if (OCSP_basic_verify(basic, ctx->chain, store, ctx->flags) != 1) { - ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0, - "OCSP_basic_verify() failed"); - goto error; + if (ctx->responder_chain != NULL) { + ctx->flags |= OCSP_TRUSTOTHER; + if (OCSP_basic_verify(basic, ctx->responder_chain, store, ctx->flags) != 1) { + ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0, + "OCSP_basic_verify() failed"); + goto error; + } + } + else { + if (OCSP_basic_verify(basic, ctx->chain, store, ctx->flags) != 1) { + ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0, + "OCSP_basic_verify() failed"); + goto error; + } } id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer); @@ -2768,7 +2799,7 @@ ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_int_t -ngx_ssl_ocsp(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *responder, +ngx_ssl_ocsp(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *responder, ngx_str_t *ocsp_responder_certificate, ngx_uint_t depth, ngx_shm_zone_t *shm_zone) { ngx_log_error(NGX_LOG_EMERG, ssl->log, 0, diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index dbfe5c08b..b57d295f1 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -243,7 +243,14 @@ static ngx_command_t ngx_http_ssl_commands[] = { offsetof(ngx_http_ssl_srv_conf_t, ocsp_responder), NULL }, - { ngx_string("ssl_ocsp_cache"), + { ngx_string("ssl_ocsp_responder_certificate"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_ssl_srv_conf_t, ocsp_responder_certificate), + NULL }, + + { ngx_string("ssl_ocsp_cache"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, ngx_http_ssl_ocsp_cache, NGX_HTTP_SRV_CONF_OFFSET, @@ -838,7 +845,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) return NGX_CONF_ERROR; } - if (ngx_ssl_ocsp(cf, &conf->ssl, &conf->ocsp_responder, conf->ocsp, + if (ngx_ssl_ocsp(cf, &conf->ssl, &conf->ocsp_responder, &conf->ocsp_responder_certificate, conf->ocsp, conf->ocsp_cache_zone) != NGX_OK) { diff --git a/src/http/modules/ngx_http_ssl_module.h b/src/http/modules/ngx_http_ssl_module.h index 8650fab93..ea4dfacef 100644 --- a/src/http/modules/ngx_http_ssl_module.h +++ b/src/http/modules/ngx_http_ssl_module.h @@ -58,6 +58,7 @@ typedef struct { ngx_uint_t ocsp; ngx_str_t ocsp_responder; + ngx_str_t ocsp_responder_certificate; ngx_shm_zone_t *ocsp_cache_zone; ngx_flag_t stapling; diff --git a/src/stream/ngx_stream_ssl_module.c b/src/stream/ngx_stream_ssl_module.c index 2f1b99624..c104933fe 100644 --- a/src/stream/ngx_stream_ssl_module.c +++ b/src/stream/ngx_stream_ssl_module.c @@ -245,6 +245,13 @@ static ngx_command_t ngx_stream_ssl_commands[] = { offsetof(ngx_stream_ssl_srv_conf_t, ocsp_responder), NULL }, + { ngx_string("ssl_ocsp_responder_certificate"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_STREAM_SRV_CONF_OFFSET, + offsetof(ngx_stream_ssl_srv_conf_t, ocsp_responder_certificate), + NULL }, + { ngx_string("ssl_ocsp_cache"), NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, ngx_stream_ssl_ocsp_cache, @@ -1083,7 +1090,7 @@ ngx_stream_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) return NGX_CONF_ERROR; } - if (ngx_ssl_ocsp(cf, &conf->ssl, &conf->ocsp_responder, conf->ocsp, + if (ngx_ssl_ocsp(cf, &conf->ssl, &conf->ocsp_responder, &conf->ocsp_responder_certificate, conf->ocsp, conf->ocsp_cache_zone) != NGX_OK) { diff --git a/src/stream/ngx_stream_ssl_module.h b/src/stream/ngx_stream_ssl_module.h index ffa03a6f3..e7283a2f3 100644 --- a/src/stream/ngx_stream_ssl_module.h +++ b/src/stream/ngx_stream_ssl_module.h @@ -58,6 +58,7 @@ typedef struct { ngx_uint_t ocsp; ngx_str_t ocsp_responder; + ngx_str_t ocsp_responder_certificate; ngx_shm_zone_t *ocsp_cache_zone; ngx_flag_t stapling;