14 #ifdef SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB
41 typedef struct ngx_ssl_ocsp_ctx_s ngx_ssl_ocsp_ctx_t;
43 struct ngx_ssl_ocsp_ctx_s {
59 void (*handler)(ngx_ssl_ocsp_ctx_t *r);
66 ngx_int_t (*process)(ngx_ssl_ocsp_ctx_t *r);
75 u_char *header_name_start;
76 u_char *header_name_end;
91 static int ngx_ssl_certificate_status_callback(
ngx_ssl_conn_t *ssl_conn,
93 static void ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple);
94 static void ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx);
96 static void ngx_ssl_stapling_cleanup(
void *data);
98 static ngx_ssl_ocsp_ctx_t *ngx_ssl_ocsp_start(
void);
99 static void ngx_ssl_ocsp_done(ngx_ssl_ocsp_ctx_t *ctx);
100 static void ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx);
102 static void ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx);
103 static void ngx_ssl_ocsp_write_handler(
ngx_event_t *wev);
104 static void ngx_ssl_ocsp_read_handler(
ngx_event_t *rev);
105 static void ngx_ssl_ocsp_dummy_handler(
ngx_event_t *ev);
107 static ngx_int_t ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx);
108 static ngx_int_t ngx_ssl_ocsp_process_status_line(ngx_ssl_ocsp_ctx_t *ctx);
109 static ngx_int_t ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t *ctx);
110 static ngx_int_t ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx);
111 static ngx_int_t ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx);
112 static ngx_int_t ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx);
114 static u_char *ngx_ssl_ocsp_log_error(
ngx_log_t *log, u_char *buf,
size_t len);
123 ngx_ssl_stapling_t *staple;
126 if (staple == NULL) {
135 cln->
handler = ngx_ssl_stapling_cleanup;
142 "SSL_CTX_set_ex_data() failed");
146 staple->ssl_ctx = ssl->
ctx;
147 staple->timeout = 60000;
148 staple->verify = verify;
153 if (ngx_ssl_stapling_file(cf, ssl, file) !=
NGX_OK) {
160 rc = ngx_ssl_stapling_issuer(cf, ssl);
170 rc = ngx_ssl_stapling_responder(cf, ssl, responder);
182 SSL_CTX_set_tlsext_status_cb(ssl->
ctx, ngx_ssl_certificate_status_callback);
183 SSL_CTX_set_tlsext_status_arg(ssl->
ctx, staple);
195 OCSP_RESPONSE *response;
196 ngx_ssl_stapling_t *staple;
204 bio = BIO_new_file((
char *) file->
data,
"r");
207 "BIO_new_file(\"%s\") failed", file->
data);
211 response = d2i_OCSP_RESPONSE_bio(bio, NULL);
212 if (response == NULL) {
214 "d2i_OCSP_RESPONSE_bio(\"%s\") failed", file->
data);
219 len = i2d_OCSP_RESPONSE(response, NULL);
222 "i2d_OCSP_RESPONSE(\"%s\") failed", file->
data);
232 len = i2d_OCSP_RESPONSE(response, &p);
235 "i2d_OCSP_RESPONSE(\"%s\") failed", file->
data);
240 OCSP_RESPONSE_free(response);
243 staple->staple.data = buf;
244 staple->staple.len = len;
250 OCSP_RESPONSE_free(response);
263 X509_STORE_CTX *store_ctx;
264 STACK_OF(X509) *chain;
265 ngx_ssl_stapling_t *staple;
270 #if OPENSSL_VERSION_NUMBER >= 0x10001000L
271 SSL_CTX_get_extra_chain_certs(ssl->
ctx, &chain);
273 chain = ssl->
ctx->extra_certs;
276 n = sk_X509_num(chain);
279 "SSL get issuer: %d extra certs", n);
281 for (i = 0; i < n; i++) {
282 issuer = sk_X509_value(chain, i);
283 if (X509_check_issued(issuer, cert) == X509_V_OK) {
284 CRYPTO_add(&issuer->references, 1, CRYPTO_LOCK_X509);
287 "SSL get issuer: found %p in extra certs", issuer);
290 staple->issuer = issuer;
296 store = SSL_CTX_get_cert_store(ssl->
ctx);
299 "SSL_CTX_get_cert_store() failed");
303 store_ctx = X509_STORE_CTX_new();
304 if (store_ctx == NULL) {
306 "X509_STORE_CTX_new() failed");
310 if (X509_STORE_CTX_init(store_ctx, store, NULL, NULL) == 0) {
312 "X509_STORE_CTX_init() failed");
316 rc = X509_STORE_CTX_get1_issuer(&issuer, store_ctx, cert);
320 "X509_STORE_CTX_get1_issuer() failed");
321 X509_STORE_CTX_free(store_ctx);
327 "\"ssl_stapling\" ignored, issuer certificate not found");
328 X509_STORE_CTX_free(store_ctx);
332 X509_STORE_CTX_free(store_ctx);
335 "SSL get issuer: found %p in cert store", issuer);
338 staple->issuer = issuer;
349 ngx_ssl_stapling_t *staple;
350 STACK_OF(OPENSSL_STRING) *aia;
354 if (responder->
len == 0) {
358 aia = X509_get1_ocsp(staple->cert);
361 "\"ssl_stapling\" ignored, "
362 "no OCSP responder URL in the certificate");
366 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
367 s = sk_OPENSSL_STRING_value(aia, 0);
369 s = sk_value(aia, 0);
373 "\"ssl_stapling\" ignored, "
374 "no OCSP responder URL in the certificate");
375 X509_email_free(aia);
381 if (responder->
data == NULL) {
382 X509_email_free(aia);
387 X509_email_free(aia);
404 "\"ssl_stapling\" ignored, "
405 "invalid URL prefix in OCSP responder \"%V\"", &u.
url);
412 "\"ssl_stapling\" ignored, "
413 "%s in OCSP responder \"%V\"", u.
err, &u.
url);
420 staple->addrs = u.
addrs;
421 staple->host = u.
host;
423 staple->port = u.
port;
425 if (staple->uri.len == 0) {
437 ngx_ssl_stapling_t *staple;
441 staple->resolver = resolver;
442 staple->resolver_timeout = resolver_timeout;
449 ngx_ssl_certificate_status_callback(
ngx_ssl_conn_t *ssl_conn,
void *data)
454 ngx_ssl_stapling_t *staple;
459 "SSL certificate status callback");
462 rc = SSL_TLSEXT_ERR_NOACK;
464 if (staple->staple.len) {
467 p = OPENSSL_malloc(staple->staple.len);
470 return SSL_TLSEXT_ERR_NOACK;
473 ngx_memcpy(p, staple->staple.data, staple->staple.len);
475 SSL_set_tlsext_status_ocsp_resp(ssl_conn, p, staple->staple.len);
477 rc = SSL_TLSEXT_ERR_OK;
480 ngx_ssl_stapling_update(staple);
487 ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple)
489 ngx_ssl_ocsp_ctx_t *
ctx;
491 if (staple->host.len == 0
492 || staple->loading || staple->valid >=
ngx_time())
499 ctx = ngx_ssl_ocsp_start();
504 ctx->cert = staple->cert;
505 ctx->issuer = staple->issuer;
507 ctx->addrs = staple->addrs;
508 ctx->host = staple->host;
509 ctx->uri = staple->uri;
510 ctx->port = staple->port;
511 ctx->timeout = staple->timeout;
513 ctx->resolver = staple->resolver;
514 ctx->resolver_timeout = staple->resolver_timeout;
516 ctx->handler = ngx_ssl_stapling_ocsp_handler;
519 ngx_ssl_ocsp_request(ctx);
526 ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
528 #if OPENSSL_VERSION_NUMBER >= 0x0090707fL
536 STACK_OF(X509) *chain;
539 OCSP_BASICRESP *basic;
540 ngx_ssl_stapling_t *staple;
541 ASN1_GENERALIZEDTIME *thisupdate, *nextupdate;
548 if (ctx->code != 200) {
554 len = ctx->response->last - ctx->response->pos;
555 p = ctx->response->pos;
557 ocsp = d2i_OCSP_RESPONSE(NULL, &p, len);
560 "d2i_OCSP_RESPONSE() failed");
564 n = OCSP_response_status(ocsp);
566 if (n != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
568 "OCSP response not successful (%d: %s)",
569 n, OCSP_response_status_str(n));
573 basic = OCSP_response_get1_basic(ocsp);
576 "OCSP_response_get1_basic() failed");
580 store = SSL_CTX_get_cert_store(staple->ssl_ctx);
583 "SSL_CTX_get_cert_store() failed");
587 #if OPENSSL_VERSION_NUMBER >= 0x10001000L
588 SSL_CTX_get_extra_chain_certs(staple->ssl_ctx, &chain);
590 chain = staple->ssl_ctx->extra_certs;
593 if (OCSP_basic_verify(basic, chain, store,
594 staple->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY)
598 "OCSP_basic_verify() failed");
602 id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
605 "OCSP_cert_to_id() failed");
609 if (OCSP_resp_find_status(basic,
id, &n, NULL, NULL,
610 &thisupdate, &nextupdate)
614 "certificate status not found in the OCSP response");
618 if (n != V_OCSP_CERTSTATUS_GOOD) {
620 "certificate status \"%s\" in the OCSP response",
621 OCSP_cert_status_str(n));
625 if (OCSP_check_validity(thisupdate, nextupdate, 300, -1) != 1) {
627 "OCSP_check_validity() failed");
631 OCSP_CERTID_free(
id);
632 OCSP_BASICRESP_free(basic);
633 OCSP_RESPONSE_free(ocsp);
640 if (response.
data == NULL) {
647 "ssl ocsp response, %s, %uz",
648 OCSP_cert_status_str(n), response.
len);
650 if (staple->staple.data) {
654 staple->staple = response;
661 ngx_ssl_ocsp_done(ctx);
670 OCSP_CERTID_free(
id);
674 OCSP_BASICRESP_free(basic);
678 OCSP_RESPONSE_free(ocsp);
681 ngx_ssl_ocsp_done(ctx);
686 ngx_ssl_stapling_cleanup(
void *data)
688 ngx_ssl_stapling_t *staple = data;
690 if (staple->issuer) {
691 X509_free(staple->issuer);
694 if (staple->staple.data) {
700 static ngx_ssl_ocsp_ctx_t *
701 ngx_ssl_ocsp_start(
void)
705 ngx_ssl_ocsp_ctx_t *ctx;
712 ctx =
ngx_pcalloc(pool,
sizeof(ngx_ssl_ocsp_ctx_t));
726 *log = *ctx->pool->log;
728 ctx->pool->log = log;
731 log->
handler = ngx_ssl_ocsp_log_error;
733 log->
action =
"requesting certificate status";
740 ngx_ssl_ocsp_done(ngx_ssl_ocsp_ctx_t *ctx)
745 if (ctx->peer.connection) {
754 ngx_ssl_ocsp_error(ngx_ssl_ocsp_ctx_t *ctx)
765 ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx)
772 if (ngx_ssl_ocsp_create_request(ctx) !=
NGX_OK) {
773 ngx_ssl_ocsp_error(ctx);
780 temp.
name = ctx->host;
783 if (resolve == NULL) {
784 ngx_ssl_ocsp_error(ctx);
790 "no resolver defined to resolve %V", &ctx->host);
794 resolve->
name = ctx->host;
796 resolve->
handler = ngx_ssl_ocsp_resolve_handler;
798 resolve->
timeout = ctx->resolver_timeout;
801 ngx_ssl_ocsp_error(ctx);
810 ngx_ssl_ocsp_connect(ctx);
817 ngx_ssl_ocsp_ctx_t *ctx = resolve->
data;
823 struct sockaddr_in *sin;
826 "ssl ocsp resolve handler");
828 if (resolve->
state) {
830 "%V could not be resolved (%i: %s)",
840 for (i = 0; i < resolve->
naddrs; i++) {
841 addr = ntohl(resolve->
addrs[i]);
844 "name was resolved to %ud.%ud.%ud.%ud",
845 (addr >> 24) & 0xff, (addr >> 16) & 0xff,
846 (addr >> 8) & 0xff, addr & 0xff);
851 ctx->naddrs = resolve->
naddrs;
854 if (ctx->addrs == NULL) {
858 port = htons(ctx->port);
860 for (i = 0; i < resolve->
naddrs; i++) {
862 sin =
ngx_pcalloc(ctx->pool,
sizeof(
struct sockaddr_in));
867 sin->sin_family = AF_INET;
868 sin->sin_port = port;
869 sin->sin_addr.s_addr = resolve->
addrs[
i];
871 ctx->addrs[
i].sockaddr = (
struct sockaddr *) sin;
872 ctx->addrs[
i].socklen =
sizeof(
struct sockaddr_in);
883 ctx->addrs[
i].name.len = len;
884 ctx->addrs[
i].name.data = p;
889 ngx_ssl_ocsp_connect(ctx);
895 ngx_ssl_ocsp_error(ctx);
900 ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx)
909 ctx->peer.sockaddr = ctx->addrs[0].sockaddr;
910 ctx->peer.socklen = ctx->addrs[0].socklen;
911 ctx->peer.name = &ctx->addrs[0].name;
913 ctx->peer.log = ctx->log;
919 "ssl ocsp connect peer done");
922 ngx_ssl_ocsp_error(ctx);
926 ctx->peer.connection->data = ctx;
927 ctx->peer.connection->pool = ctx->pool;
929 ctx->peer.connection->read->handler = ngx_ssl_ocsp_read_handler;
930 ctx->peer.connection->write->handler = ngx_ssl_ocsp_write_handler;
932 ctx->process = ngx_ssl_ocsp_process_status_line;
938 ngx_ssl_ocsp_write_handler(ctx->peer.connection->write);
949 ngx_ssl_ocsp_ctx_t *ctx;
955 "ssl ocsp write handler");
959 "OCSP responder timed out");
960 ngx_ssl_ocsp_error(ctx);
964 size = ctx->request->last - ctx->request->pos;
966 n =
ngx_send(c, ctx->request->pos, size);
969 ngx_ssl_ocsp_error(ctx);
974 ctx->request->pos += n;
977 wev->
handler = ngx_ssl_ocsp_dummy_handler;
984 ngx_ssl_ocsp_error(ctx);
1002 ngx_ssl_ocsp_ctx_t *ctx;
1009 "ssl ocsp read handler");
1013 "OCSP responder timed out");
1014 ngx_ssl_ocsp_error(ctx);
1018 if (ctx->response == NULL) {
1020 if (ctx->response == NULL) {
1021 ngx_ssl_ocsp_error(ctx);
1028 size = ctx->response->end - ctx->response->last;
1030 n =
ngx_recv(c, ctx->response->last, size);
1033 ctx->response->last += n;
1035 rc = ctx->process(ctx);
1038 ngx_ssl_ocsp_error(ctx);
1048 ngx_ssl_ocsp_error(ctx);
1059 rc = ctx->process(ctx);
1067 "OCSP responder prematurely closed connection");
1069 ngx_ssl_ocsp_error(ctx);
1077 "ssl ocsp dummy handler");
1082 ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx)
1092 ocsp = OCSP_REQUEST_new();
1095 "OCSP_REQUEST_new() failed");
1099 id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
1102 "OCSP_cert_to_id() failed");
1106 if (OCSP_request_add0_id(ocsp,
id) == NULL) {
1108 "OCSP_request_add0_id() failed");
1112 len = i2d_OCSP_REQUEST(ocsp, NULL);
1115 "i2d_OCSP_REQUEST() failed");
1121 if (binary.
data == NULL) {
1126 len = i2d_OCSP_REQUEST(ocsp, &p);
1129 "i2d_OCSP_REQUEST() failed");
1135 if (base64.
data == NULL) {
1145 "ssl ocsp request length %z, escape %d",
1146 base64.
len, escape);
1148 len =
sizeof(
"GET ") - 1 + ctx->uri.len +
sizeof(
"/") - 1
1149 + base64.
len + 2 * escape +
sizeof(
" HTTP/1.0" CRLF) - 1
1150 +
sizeof(
"Host: ") - 1 + ctx->host.len +
sizeof(
CRLF) - 1
1160 p =
ngx_cpymem(p,
"GET ",
sizeof(
"GET ") - 1);
1161 p =
ngx_cpymem(p, ctx->uri.data, ctx->uri.len);
1163 if (ctx->uri.data[ctx->uri.len - 1] !=
'/') {
1176 p =
ngx_cpymem(p,
"Host: ",
sizeof(
"Host: ") - 1);
1177 p =
ngx_cpymem(p, ctx->host.data, ctx->host.len);
1178 *p++ =
CR; *p++ =
LF;
1181 *p++ =
CR; *p++ =
LF;
1190 OCSP_REQUEST_free(ocsp);
1197 ngx_ssl_ocsp_process_status_line(ngx_ssl_ocsp_ctx_t *ctx)
1201 rc = ngx_ssl_ocsp_parse_status_line(ctx);
1206 "ssl ocsp status line \"%*s\"",
1207 ctx->response->pos - ctx->response->start,
1208 ctx->response->start);
1211 ctx->process = ngx_ssl_ocsp_process_headers;
1212 return ctx->process(ctx);
1222 "OCSP responder sent invalid response");
1229 ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t *ctx)
1240 sw_first_major_digit,
1242 sw_first_minor_digit,
1245 sw_space_after_status,
1251 "ssl ocsp process status line");
1256 for (p = b->
pos; p < b->last; p++) {
1305 state = sw_first_major_digit;
1313 case sw_first_major_digit:
1314 if (ch < '1' || ch >
'9') {
1318 state = sw_major_digit;
1322 case sw_major_digit:
1324 state = sw_first_minor_digit;
1328 if (ch < '0' || ch >
'9') {
1335 case sw_first_minor_digit:
1336 if (ch < '0' || ch >
'9') {
1340 state = sw_minor_digit;
1344 case sw_minor_digit:
1350 if (ch < '0' || ch >
'9') {
1362 if (ch < '0' || ch >
'9') {
1366 ctx->code = ctx->code * 10 + ch -
'0';
1368 if (++ctx->count == 3) {
1369 state = sw_space_after_status;
1375 case sw_space_after_status:
1378 state = sw_status_text;
1381 state = sw_status_text;
1384 state = sw_almost_done;
1394 case sw_status_text:
1397 state = sw_almost_done;
1405 case sw_almost_done:
1423 ctx->state = sw_start;
1430 ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx)
1436 "ssl ocsp process headers");
1439 rc = ngx_ssl_ocsp_parse_header_line(ctx);
1444 "ssl ocsp header \"%*s: %*s\"",
1445 ctx->header_name_end - ctx->header_name_start,
1446 ctx->header_name_start,
1447 ctx->header_end - ctx->header_start,
1450 len = ctx->header_name_end - ctx->header_name_start;
1452 if (len ==
sizeof(
"Content-Type") - 1
1454 (u_char *)
"Content-Type",
1455 sizeof(
"Content-Type") - 1)
1458 len = ctx->header_end - ctx->header_start;
1460 if (len !=
sizeof(
"application/ocsp-response") - 1
1462 (u_char *)
"application/ocsp-response",
1463 sizeof(
"application/ocsp-response") - 1)
1467 "OCSP responder sent invalid "
1468 "\"Content-Type\" header: \"%*s\"",
1469 ctx->header_end - ctx->header_start,
1493 "OCSP responder sent invalid response");
1498 ctx->process = ngx_ssl_ocsp_process_body;
1499 return ctx->process(ctx);
1503 ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx)
1509 sw_space_before_value,
1511 sw_space_after_value,
1513 sw_header_almost_done
1518 for (p = ctx->response->pos; p < ctx->response->last; p++) {
1523 "s:%d in:'%02Xd:%c'", state, ch, ch);
1533 ctx->header_end = p;
1534 state = sw_header_almost_done;
1537 ctx->header_end = p;
1541 ctx->header_name_start = p;
1543 c = (u_char) (ch | 0x20);
1544 if (c >=
'a' && c <=
'z') {
1548 if (ch >=
'0' && ch <=
'9') {
1558 c = (u_char) (ch | 0x20);
1559 if (c >=
'a' && c <=
'z') {
1564 ctx->header_name_end = p;
1565 state = sw_space_before_value;
1573 if (ch >=
'0' && ch <=
'9') {
1578 ctx->header_name_end = p;
1579 ctx->header_start = p;
1580 ctx->header_end = p;
1581 state = sw_almost_done;
1586 ctx->header_name_end = p;
1587 ctx->header_start = p;
1588 ctx->header_end = p;
1595 case sw_space_before_value:
1600 ctx->header_start = p;
1601 ctx->header_end = p;
1602 state = sw_almost_done;
1605 ctx->header_start = p;
1606 ctx->header_end = p;
1609 ctx->header_start = p;
1619 ctx->header_end = p;
1620 state = sw_space_after_value;
1623 ctx->header_end = p;
1624 state = sw_almost_done;
1627 ctx->header_end = p;
1633 case sw_space_after_value:
1638 state = sw_almost_done;
1649 case sw_almost_done:
1658 case sw_header_almost_done:
1668 ctx->response->pos = p;
1675 ctx->response->pos = p + 1;
1676 ctx->state = sw_start;
1682 ctx->response->pos = p + 1;
1683 ctx->state = sw_start;
1690 ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx)
1693 "ssl ocsp process body");
1705 ngx_ssl_ocsp_log_error(
ngx_log_t *log, u_char *buf,
size_t len)
1708 ngx_ssl_ocsp_ctx_t *ctx;
1720 p =
ngx_snprintf(p, len,
", responder: %V", &ctx->host);
1735 "\"ssl_stapling\" ignored, not supported");