summaryrefslogtreecommitdiffhomepage
path: root/src/http
diff options
context:
space:
mode:
authorRoman Arutyunyan <arut@nginx.com>2020-05-22 17:30:12 +0300
committerRoman Arutyunyan <arut@nginx.com>2020-05-22 17:30:12 +0300
commit60438ae395d83b0f8b21bf667a1e260d60c3f46a (patch)
tree040886d686aa1eeb2d290c039b29e608f2c6633e /src/http
parentaa94ee82f6040c8e2cbde3ae4de931c23fade3f3 (diff)
downloadnginx-60438ae395d83b0f8b21bf667a1e260d60c3f46a.tar.gz
nginx-60438ae395d83b0f8b21bf667a1e260d60c3f46a.tar.bz2
SSL: client certificate validation with OCSP (ticket #1534).
OCSP validation for client certificates is enabled by the "ssl_ocsp" directive. OCSP responder can be optionally specified by "ssl_ocsp_responder". When session is reused, peer chain is not available for validation. If the verified chain contains certificates from the peer chain not available at the server, validation will fail.
Diffstat (limited to 'src/http')
-rw-r--r--src/http/modules/ngx_http_ssl_module.c64
-rw-r--r--src/http/modules/ngx_http_ssl_module.h3
-rw-r--r--src/http/ngx_http_request.c12
3 files changed, 74 insertions, 5 deletions
diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c
index 495e628d3..1c9accdd3 100644
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -74,6 +74,14 @@ static ngx_conf_enum_t ngx_http_ssl_verify[] = {
};
+static ngx_conf_enum_t ngx_http_ssl_ocsp[] = {
+ { ngx_string("off"), 0 },
+ { ngx_string("on"), 1 },
+ { ngx_string("leaf"), 2 },
+ { ngx_null_string, 0 }
+};
+
+
static ngx_conf_deprecated_t ngx_http_ssl_deprecated = {
ngx_conf_deprecated, "ssl", "listen ... ssl"
};
@@ -214,6 +222,20 @@ static ngx_command_t ngx_http_ssl_commands[] = {
offsetof(ngx_http_ssl_srv_conf_t, crl),
NULL },
+ { ngx_string("ssl_ocsp"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_enum_slot,
+ NGX_HTTP_SRV_CONF_OFFSET,
+ offsetof(ngx_http_ssl_srv_conf_t, ocsp),
+ &ngx_http_ssl_ocsp },
+
+ { ngx_string("ssl_ocsp_responder"),
+ 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),
+ NULL },
+
{ ngx_string("ssl_stapling"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
@@ -561,6 +583,7 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
* sscf->crl = { 0, NULL };
* sscf->ciphers = { 0, NULL };
* sscf->shm_zone = NULL;
+ * sscf->ocsp_responder = { 0, NULL };
* sscf->stapling_file = { 0, NULL };
* sscf->stapling_responder = { 0, NULL };
*/
@@ -578,6 +601,7 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
sscf->session_timeout = NGX_CONF_UNSET;
sscf->session_tickets = NGX_CONF_UNSET;
sscf->session_ticket_keys = NGX_CONF_UNSET_PTR;
+ sscf->ocsp = NGX_CONF_UNSET_UINT;
sscf->stapling = NGX_CONF_UNSET;
sscf->stapling_verify = NGX_CONF_UNSET;
@@ -641,6 +665,9 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS);
+ ngx_conf_merge_uint_value(conf->ocsp, prev->ocsp, 0);
+ ngx_conf_merge_str_value(conf->ocsp_responder, prev->ocsp_responder, "");
+
ngx_conf_merge_value(conf->stapling, prev->stapling, 0);
ngx_conf_merge_value(conf->stapling_verify, prev->stapling_verify, 0);
ngx_conf_merge_str_value(conf->stapling_file, prev->stapling_file, "");
@@ -802,6 +829,22 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
return NGX_CONF_ERROR;
}
+ if (conf->ocsp) {
+
+ if (conf->verify == 3) {
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "\"ssl_ocsp\" is incompatible with "
+ "\"ssl_verify_client optional_no_ca\"");
+ return NGX_CONF_ERROR;
+ }
+
+ if (ngx_ssl_ocsp(cf, &conf->ssl, &conf->ocsp_responder, conf->ocsp)
+ != NGX_OK)
+ {
+ return NGX_CONF_ERROR;
+ }
+ }
+
if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) {
return NGX_CONF_ERROR;
}
@@ -1118,17 +1161,28 @@ ngx_http_ssl_init(ngx_conf_t *cf)
sscf = cscfp[s]->ctx->srv_conf[ngx_http_ssl_module.ctx_index];
- if (sscf->ssl.ctx == NULL || !sscf->stapling) {
+ if (sscf->ssl.ctx == NULL) {
continue;
}
clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
- if (ngx_ssl_stapling_resolver(cf, &sscf->ssl, clcf->resolver,
+ if (sscf->stapling) {
+ if (ngx_ssl_stapling_resolver(cf, &sscf->ssl, clcf->resolver,
+ clcf->resolver_timeout)
+ != NGX_OK)
+ {
+ return NGX_ERROR;
+ }
+ }
+
+ if (sscf->ocsp) {
+ if (ngx_ssl_ocsp_resolver(cf, &sscf->ssl, clcf->resolver,
clcf->resolver_timeout)
- != NGX_OK)
- {
- return NGX_ERROR;
+ != NGX_OK)
+ {
+ return NGX_ERROR;
+ }
}
}
diff --git a/src/http/modules/ngx_http_ssl_module.h b/src/http/modules/ngx_http_ssl_module.h
index 26fdccfe4..92d459f60 100644
--- a/src/http/modules/ngx_http_ssl_module.h
+++ b/src/http/modules/ngx_http_ssl_module.h
@@ -54,6 +54,9 @@ typedef struct {
ngx_flag_t session_tickets;
ngx_array_t *session_ticket_keys;
+ ngx_uint_t ocsp;
+ ngx_str_t ocsp_responder;
+
ngx_flag_t stapling;
ngx_flag_t stapling_verify;
ngx_str_t stapling_file;
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index eb53996b1..6feb6cc31 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -1993,6 +1993,7 @@ ngx_http_process_request(ngx_http_request_t *r)
if (r->http_connection->ssl) {
long rc;
X509 *cert;
+ const char *s;
ngx_http_ssl_srv_conf_t *sscf;
if (c->ssl == NULL) {
@@ -2037,6 +2038,17 @@ ngx_http_process_request(ngx_http_request_t *r)
X509_free(cert);
}
+
+ if (ngx_ssl_ocsp_get_status(c, &s) != NGX_OK) {
+ ngx_log_error(NGX_LOG_INFO, c->log, 0,
+ "client SSL certificate verify error: %s", s);
+
+ ngx_ssl_remove_cached_session(c->ssl->session_ctx,
+ (SSL_get0_session(c->ssl->connection)));
+
+ ngx_http_finalize_request(r, NGX_HTTPS_CERT_ERROR);
+ return;
+ }
}
}