Skip to content

Commit 581cf22

Browse files
committed
Stream: client certificate validation with OCSP.
1 parent 48ac1ee commit 581cf22

File tree

2 files changed

+159
-0
lines changed

2 files changed

+159
-0
lines changed

src/stream/ngx_stream_ssl_module.c

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ static char *ngx_stream_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
5151
void *conf);
5252
static char *ngx_stream_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
5353
void *conf);
54+
static char *ngx_stream_ssl_ocsp_cache(ngx_conf_t *cf, ngx_command_t *cmd,
55+
void *conf);
5456
static char *ngx_stream_ssl_alpn(ngx_conf_t *cf, ngx_command_t *cmd,
5557
void *conf);
5658

@@ -80,6 +82,14 @@ static ngx_conf_enum_t ngx_stream_ssl_verify[] = {
8082
};
8183

8284

85+
static ngx_conf_enum_t ngx_stream_ssl_ocsp[] = {
86+
{ ngx_string("off"), 0 },
87+
{ ngx_string("on"), 1 },
88+
{ ngx_string("leaf"), 2 },
89+
{ ngx_null_string, 0 }
90+
};
91+
92+
8393
static ngx_conf_post_t ngx_stream_ssl_conf_command_post =
8494
{ ngx_stream_ssl_conf_command_check };
8595

@@ -212,6 +222,27 @@ static ngx_command_t ngx_stream_ssl_commands[] = {
212222
offsetof(ngx_stream_ssl_srv_conf_t, crl),
213223
NULL },
214224

225+
{ ngx_string("ssl_ocsp"),
226+
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
227+
ngx_conf_set_enum_slot,
228+
NGX_STREAM_SRV_CONF_OFFSET,
229+
offsetof(ngx_stream_ssl_srv_conf_t, ocsp),
230+
&ngx_stream_ssl_ocsp },
231+
232+
{ ngx_string("ssl_ocsp_responder"),
233+
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
234+
ngx_conf_set_str_slot,
235+
NGX_STREAM_SRV_CONF_OFFSET,
236+
offsetof(ngx_stream_ssl_srv_conf_t, ocsp_responder),
237+
NULL },
238+
239+
{ ngx_string("ssl_ocsp_cache"),
240+
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
241+
ngx_stream_ssl_ocsp_cache,
242+
NGX_STREAM_SRV_CONF_OFFSET,
243+
0,
244+
NULL },
245+
215246
{ ngx_string("ssl_conf_command"),
216247
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE2,
217248
ngx_conf_set_keyval_slot,
@@ -777,6 +808,7 @@ ngx_stream_ssl_create_srv_conf(ngx_conf_t *cf)
777808
* sscf->alpn = { 0, NULL };
778809
* sscf->ciphers = { 0, NULL };
779810
* sscf->shm_zone = NULL;
811+
* sscf->ocsp_responder = { 0, NULL };
780812
*/
781813

782814
sscf->handshake_timeout = NGX_CONF_UNSET_MSEC;
@@ -792,6 +824,8 @@ ngx_stream_ssl_create_srv_conf(ngx_conf_t *cf)
792824
sscf->session_timeout = NGX_CONF_UNSET;
793825
sscf->session_tickets = NGX_CONF_UNSET;
794826
sscf->session_ticket_keys = NGX_CONF_UNSET_PTR;
827+
sscf->ocsp = NGX_CONF_UNSET_UINT;
828+
sscf->ocsp_cache_zone = NGX_CONF_UNSET_PTR;
795829

796830
return sscf;
797831
}
@@ -846,6 +880,10 @@ ngx_stream_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
846880

847881
ngx_conf_merge_ptr_value(conf->conf_commands, prev->conf_commands, NULL);
848882

883+
ngx_conf_merge_uint_value(conf->ocsp, prev->ocsp, 0);
884+
ngx_conf_merge_str_value(conf->ocsp_responder, prev->ocsp_responder, "");
885+
ngx_conf_merge_ptr_value(conf->ocsp_cache_zone,
886+
prev->ocsp_cache_zone, NULL);
849887

850888
conf->ssl.log = cf->log;
851889

@@ -959,6 +997,23 @@ ngx_stream_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
959997
}
960998
}
961999

1000+
if (conf->ocsp) {
1001+
1002+
if (conf->verify == 3) {
1003+
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
1004+
"\"ssl_ocsp\" is incompatible with "
1005+
"\"ssl_verify_client optional_no_ca\"");
1006+
return NGX_CONF_ERROR;
1007+
}
1008+
1009+
if (ngx_ssl_ocsp(cf, &conf->ssl, &conf->ocsp_responder, conf->ocsp,
1010+
conf->ocsp_cache_zone)
1011+
!= NGX_OK)
1012+
{
1013+
return NGX_CONF_ERROR;
1014+
}
1015+
}
1016+
9621017
if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) {
9631018
return NGX_CONF_ERROR;
9641019
}
@@ -1231,6 +1286,85 @@ ngx_stream_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
12311286
}
12321287

12331288

1289+
static char *
1290+
ngx_stream_ssl_ocsp_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1291+
{
1292+
ngx_stream_ssl_srv_conf_t *sscf = conf;
1293+
1294+
size_t len;
1295+
ngx_int_t n;
1296+
ngx_str_t *value, name, size;
1297+
ngx_uint_t j;
1298+
1299+
if (sscf->ocsp_cache_zone != NGX_CONF_UNSET_PTR) {
1300+
return "is duplicate";
1301+
}
1302+
1303+
value = cf->args->elts;
1304+
1305+
if (ngx_strcmp(value[1].data, "off") == 0) {
1306+
sscf->ocsp_cache_zone = NULL;
1307+
return NGX_CONF_OK;
1308+
}
1309+
1310+
if (value[1].len <= sizeof("shared:") - 1
1311+
|| ngx_strncmp(value[1].data, "shared:", sizeof("shared:") - 1) != 0)
1312+
{
1313+
goto invalid;
1314+
}
1315+
1316+
len = 0;
1317+
1318+
for (j = sizeof("shared:") - 1; j < value[1].len; j++) {
1319+
if (value[1].data[j] == ':') {
1320+
break;
1321+
}
1322+
1323+
len++;
1324+
}
1325+
1326+
if (len == 0 || j == value[1].len) {
1327+
goto invalid;
1328+
}
1329+
1330+
name.len = len;
1331+
name.data = value[1].data + sizeof("shared:") - 1;
1332+
1333+
size.len = value[1].len - j - 1;
1334+
size.data = name.data + len + 1;
1335+
1336+
n = ngx_parse_size(&size);
1337+
1338+
if (n == NGX_ERROR) {
1339+
goto invalid;
1340+
}
1341+
1342+
if (n < (ngx_int_t) (8 * ngx_pagesize)) {
1343+
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1344+
"OCSP cache \"%V\" is too small", &value[1]);
1345+
1346+
return NGX_CONF_ERROR;
1347+
}
1348+
1349+
sscf->ocsp_cache_zone = ngx_shared_memory_add(cf, &name, n,
1350+
&ngx_stream_ssl_module_ctx);
1351+
if (sscf->ocsp_cache_zone == NULL) {
1352+
return NGX_CONF_ERROR;
1353+
}
1354+
1355+
sscf->ocsp_cache_zone->init = ngx_ssl_ocsp_cache_init;
1356+
1357+
return NGX_CONF_OK;
1358+
1359+
invalid:
1360+
1361+
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1362+
"invalid OCSP cache \"%V\"", &value[1]);
1363+
1364+
return NGX_CONF_ERROR;
1365+
}
1366+
1367+
12341368
static char *
12351369
ngx_stream_ssl_alpn(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
12361370
{
@@ -1308,6 +1442,27 @@ ngx_stream_ssl_init(ngx_conf_t *cf)
13081442
ngx_stream_core_main_conf_t *cmcf;
13091443

13101444
cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
1445+
cscfp = cmcf->servers.elts;
1446+
1447+
for (s = 0; s < cmcf->servers.nelts; s++) {
1448+
1449+
sscf = cscfp[s]->ctx->srv_conf[ngx_stream_ssl_module.ctx_index];
1450+
1451+
if (sscf->ssl.ctx == NULL) {
1452+
continue;
1453+
}
1454+
1455+
cscf = cscfp[s]->ctx->srv_conf[ngx_stream_core_module.ctx_index];
1456+
1457+
if (sscf->ocsp) {
1458+
if (ngx_ssl_ocsp_resolver(cf, &sscf->ssl, cscf->resolver,
1459+
cscf->resolver_timeout)
1460+
!= NGX_OK)
1461+
{
1462+
return NGX_ERROR;
1463+
}
1464+
}
1465+
}
13111466

13121467
h = ngx_array_push(&cmcf->phases[NGX_STREAM_SSL_PHASE].handlers);
13131468
if (h == NULL) {

src/stream/ngx_stream_ssl_module.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ typedef struct {
5353

5454
ngx_flag_t session_tickets;
5555
ngx_array_t *session_ticket_keys;
56+
57+
ngx_uint_t ocsp;
58+
ngx_str_t ocsp_responder;
59+
ngx_shm_zone_t *ocsp_cache_zone;
5660
} ngx_stream_ssl_srv_conf_t;
5761

5862

0 commit comments

Comments
 (0)