comparison src/event/ngx_event_openssl_stapling.c @ 8411:7995cd199b52 quic

Merged with the default branch.
author Sergey Kandaurov <pluknet@nginx.com>
date Tue, 26 May 2020 20:26:44 +0300
parents bd4d1b9db0ee
children 1ece2ac2555a
comparison
equal deleted inserted replaced
8410:c7d1b500bd0a 8411:7995cd199b52
20 20
21 ngx_resolver_t *resolver; 21 ngx_resolver_t *resolver;
22 ngx_msec_t resolver_timeout; 22 ngx_msec_t resolver_timeout;
23 23
24 ngx_addr_t *addrs; 24 ngx_addr_t *addrs;
25 ngx_uint_t naddrs;
25 ngx_str_t host; 26 ngx_str_t host;
26 ngx_str_t uri; 27 ngx_str_t uri;
27 in_port_t port; 28 in_port_t port;
28 29
29 SSL_CTX *ssl_ctx; 30 SSL_CTX *ssl_ctx;
30 31
31 X509 *cert; 32 X509 *cert;
32 X509 *issuer; 33 X509 *issuer;
34 STACK_OF(X509) *chain;
33 35
34 u_char *name; 36 u_char *name;
35 37
36 time_t valid; 38 time_t valid;
37 time_t refresh; 39 time_t refresh;
39 unsigned verify:1; 41 unsigned verify:1;
40 unsigned loading:1; 42 unsigned loading:1;
41 } ngx_ssl_stapling_t; 43 } ngx_ssl_stapling_t;
42 44
43 45
46 typedef struct {
47 ngx_addr_t *addrs;
48 ngx_uint_t naddrs;
49
50 ngx_str_t host;
51 ngx_str_t uri;
52 in_port_t port;
53 ngx_uint_t depth;
54
55 ngx_shm_zone_t *shm_zone;
56
57 ngx_resolver_t *resolver;
58 ngx_msec_t resolver_timeout;
59 } ngx_ssl_ocsp_conf_t;
60
61
62 typedef struct {
63 ngx_rbtree_t rbtree;
64 ngx_rbtree_node_t sentinel;
65 ngx_queue_t expire_queue;
66 } ngx_ssl_ocsp_cache_t;
67
68
69 typedef struct {
70 ngx_str_node_t node;
71 ngx_queue_t queue;
72 int status;
73 time_t valid;
74 } ngx_ssl_ocsp_cache_node_t;
75
76
44 typedef struct ngx_ssl_ocsp_ctx_s ngx_ssl_ocsp_ctx_t; 77 typedef struct ngx_ssl_ocsp_ctx_s ngx_ssl_ocsp_ctx_t;
45 78
79
80 struct ngx_ssl_ocsp_s {
81 STACK_OF(X509) *certs;
82 ngx_uint_t ncert;
83
84 int cert_status;
85 ngx_int_t status;
86
87 ngx_ssl_ocsp_conf_t *conf;
88 ngx_ssl_ocsp_ctx_t *ctx;
89 };
90
91
46 struct ngx_ssl_ocsp_ctx_s { 92 struct ngx_ssl_ocsp_ctx_s {
93 SSL_CTX *ssl_ctx;
94
47 X509 *cert; 95 X509 *cert;
48 X509 *issuer; 96 X509 *issuer;
97 STACK_OF(X509) *chain;
98
99 int status;
100 time_t valid;
49 101
50 u_char *name; 102 u_char *name;
51 103
52 ngx_uint_t naddrs; 104 ngx_uint_t naddrs;
105 ngx_uint_t naddr;
53 106
54 ngx_addr_t *addrs; 107 ngx_addr_t *addrs;
55 ngx_str_t host; 108 ngx_str_t host;
56 ngx_str_t uri; 109 ngx_str_t uri;
57 in_port_t port; 110 in_port_t port;
62 ngx_msec_t timeout; 115 ngx_msec_t timeout;
63 116
64 void (*handler)(ngx_ssl_ocsp_ctx_t *ctx); 117 void (*handler)(ngx_ssl_ocsp_ctx_t *ctx);
65 void *data; 118 void *data;
66 119
120 ngx_str_t key;
67 ngx_buf_t *request; 121 ngx_buf_t *request;
68 ngx_buf_t *response; 122 ngx_buf_t *response;
69 ngx_peer_connection_t peer; 123 ngx_peer_connection_t peer;
70 124
125 ngx_shm_zone_t *shm_zone;
126
71 ngx_int_t (*process)(ngx_ssl_ocsp_ctx_t *ctx); 127 ngx_int_t (*process)(ngx_ssl_ocsp_ctx_t *ctx);
72 128
73 ngx_uint_t state; 129 ngx_uint_t state;
74 130
75 ngx_uint_t code; 131 ngx_uint_t code;
76 ngx_uint_t count; 132 ngx_uint_t count;
77 133 ngx_uint_t flags;
78 ngx_uint_t done; 134 ngx_uint_t done;
79 135
80 u_char *header_name_start; 136 u_char *header_name_start;
81 u_char *header_name_end; 137 u_char *header_name_end;
82 u_char *header_start; 138 u_char *header_start;
103 159
104 static time_t ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time); 160 static time_t ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time);
105 161
106 static void ngx_ssl_stapling_cleanup(void *data); 162 static void ngx_ssl_stapling_cleanup(void *data);
107 163
108 static ngx_ssl_ocsp_ctx_t *ngx_ssl_ocsp_start(void); 164 static void ngx_ssl_ocsp_validate_next(ngx_connection_t *c);
165 static void ngx_ssl_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx);
166 static ngx_int_t ngx_ssl_ocsp_responder(ngx_connection_t *c,
167 ngx_ssl_ocsp_ctx_t *ctx);
168
169 static ngx_ssl_ocsp_ctx_t *ngx_ssl_ocsp_start(ngx_log_t *log);
109 static void ngx_ssl_ocsp_done(ngx_ssl_ocsp_ctx_t *ctx); 170 static void ngx_ssl_ocsp_done(ngx_ssl_ocsp_ctx_t *ctx);
171 static void ngx_ssl_ocsp_next(ngx_ssl_ocsp_ctx_t *ctx);
110 static void ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx); 172 static void ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx);
111 static void ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve); 173 static void ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve);
112 static void ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx); 174 static void ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx);
113 static void ngx_ssl_ocsp_write_handler(ngx_event_t *wev); 175 static void ngx_ssl_ocsp_write_handler(ngx_event_t *wev);
114 static void ngx_ssl_ocsp_read_handler(ngx_event_t *rev); 176 static void ngx_ssl_ocsp_read_handler(ngx_event_t *rev);
118 static ngx_int_t ngx_ssl_ocsp_process_status_line(ngx_ssl_ocsp_ctx_t *ctx); 180 static ngx_int_t ngx_ssl_ocsp_process_status_line(ngx_ssl_ocsp_ctx_t *ctx);
119 static ngx_int_t ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t *ctx); 181 static ngx_int_t ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t *ctx);
120 static ngx_int_t ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx); 182 static ngx_int_t ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx);
121 static ngx_int_t ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx); 183 static ngx_int_t ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx);
122 static ngx_int_t ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx); 184 static ngx_int_t ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx);
185 static ngx_int_t ngx_ssl_ocsp_verify(ngx_ssl_ocsp_ctx_t *ctx);
186
187 static ngx_int_t ngx_ssl_ocsp_cache_lookup(ngx_ssl_ocsp_ctx_t *ctx);
188 static ngx_int_t ngx_ssl_ocsp_cache_store(ngx_ssl_ocsp_ctx_t *ctx);
189 static ngx_int_t ngx_ssl_ocsp_create_key(ngx_ssl_ocsp_ctx_t *ctx);
123 190
124 static u_char *ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len); 191 static u_char *ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len);
125 192
126 193
127 ngx_int_t 194 ngx_int_t
171 if (X509_set_ex_data(cert, ngx_ssl_stapling_index, staple) == 0) { 238 if (X509_set_ex_data(cert, ngx_ssl_stapling_index, staple) == 0) {
172 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed"); 239 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed");
173 return NGX_ERROR; 240 return NGX_ERROR;
174 } 241 }
175 242
243 #ifdef SSL_CTRL_SELECT_CURRENT_CERT
244 /* OpenSSL 1.0.2+ */
245 SSL_CTX_select_current_cert(ssl->ctx, cert);
246 #endif
247
248 #ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
249 /* OpenSSL 1.0.1+ */
250 SSL_CTX_get_extra_chain_certs(ssl->ctx, &staple->chain);
251 #else
252 staple->chain = ssl->ctx->extra_certs;
253 #endif
254
176 staple->ssl_ctx = ssl->ctx; 255 staple->ssl_ctx = ssl->ctx;
177 staple->timeout = 60000; 256 staple->timeout = 60000;
178 staple->verify = verify; 257 staple->verify = verify;
179 staple->cert = cert; 258 staple->cert = cert;
180 staple->name = X509_get_ex_data(staple->cert, 259 staple->name = X509_get_ex_data(staple->cert,
287 { 366 {
288 int i, n, rc; 367 int i, n, rc;
289 X509 *cert, *issuer; 368 X509 *cert, *issuer;
290 X509_STORE *store; 369 X509_STORE *store;
291 X509_STORE_CTX *store_ctx; 370 X509_STORE_CTX *store_ctx;
292 STACK_OF(X509) *chain;
293 371
294 cert = staple->cert; 372 cert = staple->cert;
295 373
296 #ifdef SSL_CTRL_SELECT_CURRENT_CERT 374 n = sk_X509_num(staple->chain);
297 /* OpenSSL 1.0.2+ */
298 SSL_CTX_select_current_cert(ssl->ctx, cert);
299 #endif
300
301 #ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
302 /* OpenSSL 1.0.1+ */
303 SSL_CTX_get_extra_chain_certs(ssl->ctx, &chain);
304 #else
305 chain = ssl->ctx->extra_certs;
306 #endif
307
308 n = sk_X509_num(chain);
309 375
310 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0, 376 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
311 "SSL get issuer: %d extra certs", n); 377 "SSL get issuer: %d extra certs", n);
312 378
313 for (i = 0; i < n; i++) { 379 for (i = 0; i < n; i++) {
314 issuer = sk_X509_value(chain, i); 380 issuer = sk_X509_value(staple->chain, i);
315 if (X509_check_issued(issuer, cert) == X509_V_OK) { 381 if (X509_check_issued(issuer, cert) == X509_V_OK) {
316 #if OPENSSL_VERSION_NUMBER >= 0x10100001L 382 #if OPENSSL_VERSION_NUMBER >= 0x10100001L
317 X509_up_ref(issuer); 383 X509_up_ref(issuer);
318 #else 384 #else
319 CRYPTO_add(&issuer->references, 1, CRYPTO_LOCK_X509); 385 CRYPTO_add(&issuer->references, 1, CRYPTO_LOCK_X509);
460 526
461 return NGX_ERROR; 527 return NGX_ERROR;
462 } 528 }
463 529
464 staple->addrs = u.addrs; 530 staple->addrs = u.addrs;
531 staple->naddrs = u.naddrs;
465 staple->host = u.host; 532 staple->host = u.host;
466 staple->uri = u.uri; 533 staple->uri = u.uri;
467 staple->port = u.port; 534 staple->port = u.port;
468 535
469 if (staple->uri.len == 0) { 536 if (staple->uri.len == 0) {
557 return; 624 return;
558 } 625 }
559 626
560 staple->loading = 1; 627 staple->loading = 1;
561 628
562 ctx = ngx_ssl_ocsp_start(); 629 ctx = ngx_ssl_ocsp_start(ngx_cycle->log);
563 if (ctx == NULL) { 630 if (ctx == NULL) {
564 return; 631 return;
565 } 632 }
566 633
634 ctx->ssl_ctx = staple->ssl_ctx;
567 ctx->cert = staple->cert; 635 ctx->cert = staple->cert;
568 ctx->issuer = staple->issuer; 636 ctx->issuer = staple->issuer;
637 ctx->chain = staple->chain;
569 ctx->name = staple->name; 638 ctx->name = staple->name;
639 ctx->flags = (staple->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY);
570 640
571 ctx->addrs = staple->addrs; 641 ctx->addrs = staple->addrs;
642 ctx->naddrs = staple->naddrs;
572 ctx->host = staple->host; 643 ctx->host = staple->host;
573 ctx->uri = staple->uri; 644 ctx->uri = staple->uri;
574 ctx->port = staple->port; 645 ctx->port = staple->port;
575 ctx->timeout = staple->timeout; 646 ctx->timeout = staple->timeout;
576 647
587 658
588 659
589 static void 660 static void
590 ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx) 661 ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
591 { 662 {
592 int n; 663 time_t now;
593 size_t len; 664 ngx_str_t response;
594 time_t now, valid; 665 ngx_ssl_stapling_t *staple;
595 ngx_str_t response;
596 X509_STORE *store;
597 const u_char *p;
598 STACK_OF(X509) *chain;
599 OCSP_CERTID *id;
600 OCSP_RESPONSE *ocsp;
601 OCSP_BASICRESP *basic;
602 ngx_ssl_stapling_t *staple;
603 ASN1_GENERALIZEDTIME *thisupdate, *nextupdate;
604 666
605 staple = ctx->data; 667 staple = ctx->data;
606 now = ngx_time(); 668 now = ngx_time();
607 ocsp = NULL; 669
608 basic = NULL; 670 if (ngx_ssl_ocsp_verify(ctx) != NGX_OK) {
609 id = NULL;
610
611 if (ctx->code != 200) {
612 goto error; 671 goto error;
613 } 672 }
614 673
615 /* check the response */ 674 if (ctx->status != V_OCSP_CERTSTATUS_GOOD) {
616
617 len = ctx->response->last - ctx->response->pos;
618 p = ctx->response->pos;
619
620 ocsp = d2i_OCSP_RESPONSE(NULL, &p, len);
621 if (ocsp == NULL) {
622 ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
623 "d2i_OCSP_RESPONSE() failed");
624 goto error;
625 }
626
627 n = OCSP_response_status(ocsp);
628
629 if (n != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
630 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
631 "OCSP response not successful (%d: %s)",
632 n, OCSP_response_status_str(n));
633 goto error;
634 }
635
636 basic = OCSP_response_get1_basic(ocsp);
637 if (basic == NULL) {
638 ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
639 "OCSP_response_get1_basic() failed");
640 goto error;
641 }
642
643 store = SSL_CTX_get_cert_store(staple->ssl_ctx);
644 if (store == NULL) {
645 ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
646 "SSL_CTX_get_cert_store() failed");
647 goto error;
648 }
649
650 #ifdef SSL_CTRL_SELECT_CURRENT_CERT
651 /* OpenSSL 1.0.2+ */
652 SSL_CTX_select_current_cert(staple->ssl_ctx, ctx->cert);
653 #endif
654
655 #ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
656 /* OpenSSL 1.0.1+ */
657 SSL_CTX_get_extra_chain_certs(staple->ssl_ctx, &chain);
658 #else
659 chain = staple->ssl_ctx->extra_certs;
660 #endif
661
662 if (OCSP_basic_verify(basic, chain, store,
663 staple->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY)
664 != 1)
665 {
666 ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
667 "OCSP_basic_verify() failed");
668 goto error;
669 }
670
671 id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
672 if (id == NULL) {
673 ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
674 "OCSP_cert_to_id() failed");
675 goto error;
676 }
677
678 if (OCSP_resp_find_status(basic, id, &n, NULL, NULL,
679 &thisupdate, &nextupdate)
680 != 1)
681 {
682 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
683 "certificate status not found in the OCSP response");
684 goto error;
685 }
686
687 if (n != V_OCSP_CERTSTATUS_GOOD) {
688 ngx_log_error(NGX_LOG_ERR, ctx->log, 0, 675 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
689 "certificate status \"%s\" in the OCSP response", 676 "certificate status \"%s\" in the OCSP response",
690 OCSP_cert_status_str(n)); 677 OCSP_cert_status_str(ctx->status));
691 goto error; 678 goto error;
692 } 679 }
693 680
694 if (OCSP_check_validity(thisupdate, nextupdate, 300, -1) != 1) {
695 ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
696 "OCSP_check_validity() failed");
697 goto error;
698 }
699
700 if (nextupdate) {
701 valid = ngx_ssl_stapling_time(nextupdate);
702 if (valid == (time_t) NGX_ERROR) {
703 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
704 "invalid nextUpdate time in certificate status");
705 goto error;
706 }
707
708 } else {
709 valid = NGX_MAX_TIME_T_VALUE;
710 }
711
712 OCSP_CERTID_free(id);
713 OCSP_BASICRESP_free(basic);
714 OCSP_RESPONSE_free(ocsp);
715
716 id = NULL;
717 basic = NULL;
718 ocsp = NULL;
719
720 /* copy the response to memory not in ctx->pool */ 681 /* copy the response to memory not in ctx->pool */
721 682
722 response.len = len; 683 response.len = ctx->response->last - ctx->response->pos;
723 response.data = ngx_alloc(response.len, ctx->log); 684 response.data = ngx_alloc(response.len, ctx->log);
724 685
725 if (response.data == NULL) { 686 if (response.data == NULL) {
726 goto error; 687 goto error;
727 } 688 }
728 689
729 ngx_memcpy(response.data, ctx->response->pos, response.len); 690 ngx_memcpy(response.data, ctx->response->pos, response.len);
730 691
731 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
732 "ssl ocsp response, %s, %uz",
733 OCSP_cert_status_str(n), response.len);
734
735 if (staple->staple.data) { 692 if (staple->staple.data) {
736 ngx_free(staple->staple.data); 693 ngx_free(staple->staple.data);
737 } 694 }
738 695
739 staple->staple = response; 696 staple->staple = response;
740 staple->valid = valid; 697 staple->valid = ctx->valid;
741 698
742 /* 699 /*
743 * refresh before the response expires, 700 * refresh before the response expires,
744 * but not earlier than in 5 minutes, and at least in an hour 701 * but not earlier than in 5 minutes, and at least in an hour
745 */ 702 */
746 703
747 staple->loading = 0; 704 staple->loading = 0;
748 staple->refresh = ngx_max(ngx_min(valid - 300, now + 3600), now + 300); 705 staple->refresh = ngx_max(ngx_min(ctx->valid - 300, now + 3600), now + 300);
749 706
750 ngx_ssl_ocsp_done(ctx); 707 ngx_ssl_ocsp_done(ctx);
751 return; 708 return;
752 709
753 error: 710 error:
754 711
755 staple->loading = 0; 712 staple->loading = 0;
756 staple->refresh = now + 300; 713 staple->refresh = now + 300;
757
758 if (id) {
759 OCSP_CERTID_free(id);
760 }
761
762 if (basic) {
763 OCSP_BASICRESP_free(basic);
764 }
765
766 if (ocsp) {
767 OCSP_RESPONSE_free(ocsp);
768 }
769 714
770 ngx_ssl_ocsp_done(ctx); 715 ngx_ssl_ocsp_done(ctx);
771 } 716 }
772 717
773 718
818 ngx_free(staple->staple.data); 763 ngx_free(staple->staple.data);
819 } 764 }
820 } 765 }
821 766
822 767
768 ngx_int_t
769 ngx_ssl_ocsp(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *responder,
770 ngx_uint_t depth, ngx_shm_zone_t *shm_zone)
771 {
772 ngx_url_t u;
773 ngx_ssl_ocsp_conf_t *ocf;
774
775 ocf = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_ocsp_conf_t));
776 if (ocf == NULL) {
777 return NGX_ERROR;
778 }
779
780 ocf->depth = depth;
781 ocf->shm_zone = shm_zone;
782
783 if (responder->len) {
784 ngx_memzero(&u, sizeof(ngx_url_t));
785
786 u.url = *responder;
787 u.default_port = 80;
788 u.uri_part = 1;
789
790 if (u.url.len > 7
791 && ngx_strncasecmp(u.url.data, (u_char *) "http://", 7) == 0)
792 {
793 u.url.len -= 7;
794 u.url.data += 7;
795
796 } else {
797 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
798 "invalid URL prefix in OCSP responder \"%V\" "
799 "in \"ssl_ocsp_responder\"", &u.url);
800 return NGX_ERROR;
801 }
802
803 if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
804 if (u.err) {
805 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
806 "%s in OCSP responder \"%V\" "
807 "in \"ssl_ocsp_responder\"", u.err, &u.url);
808 }
809
810 return NGX_ERROR;
811 }
812
813 ocf->addrs = u.addrs;
814 ocf->naddrs = u.naddrs;
815 ocf->host = u.host;
816 ocf->uri = u.uri;
817 ocf->port = u.port;
818 }
819
820 if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_ocsp_index, ocf) == 0) {
821 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
822 "SSL_CTX_set_ex_data() failed");
823 return NGX_ERROR;
824 }
825
826 return NGX_OK;
827 }
828
829
830 ngx_int_t
831 ngx_ssl_ocsp_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
832 ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)
833 {
834 ngx_ssl_ocsp_conf_t *ocf;
835
836 ocf = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_ocsp_index);
837 ocf->resolver = resolver;
838 ocf->resolver_timeout = resolver_timeout;
839
840 return NGX_OK;
841 }
842
843
844 ngx_int_t
845 ngx_ssl_ocsp_validate(ngx_connection_t *c)
846 {
847 X509 *cert;
848 SSL_CTX *ssl_ctx;
849 ngx_int_t rc;
850 X509_STORE *store;
851 X509_STORE_CTX *store_ctx;
852 STACK_OF(X509) *chain;
853 ngx_ssl_ocsp_t *ocsp;
854 ngx_ssl_ocsp_conf_t *ocf;
855
856 if (c->ssl->in_ocsp) {
857 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
858 return NGX_ERROR;
859 }
860
861 if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
862 return NGX_ERROR;
863 }
864
865 return NGX_AGAIN;
866 }
867
868 ssl_ctx = SSL_get_SSL_CTX(c->ssl->connection);
869
870 ocf = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_ocsp_index);
871 if (ocf == NULL) {
872 return NGX_OK;
873 }
874
875 if (SSL_get_verify_result(c->ssl->connection) != X509_V_OK) {
876 return NGX_OK;
877 }
878
879 cert = SSL_get_peer_certificate(c->ssl->connection);
880 if (cert == NULL) {
881 return NGX_OK;
882 }
883
884 ocsp = ngx_pcalloc(c->pool, sizeof(ngx_ssl_ocsp_t));
885 if (ocsp == NULL) {
886 return NGX_ERROR;
887 }
888
889 c->ssl->ocsp = ocsp;
890
891 ocsp->status = NGX_AGAIN;
892 ocsp->cert_status = V_OCSP_CERTSTATUS_GOOD;
893 ocsp->conf = ocf;
894
895 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined LIBRESSL_VERSION_NUMBER)
896
897 ocsp->certs = SSL_get0_verified_chain(c->ssl->connection);
898
899 if (ocsp->certs) {
900 ocsp->certs = X509_chain_up_ref(ocsp->certs);
901 if (ocsp->certs == NULL) {
902 return NGX_ERROR;
903 }
904 }
905
906 #endif
907
908 if (ocsp->certs == NULL) {
909 store = SSL_CTX_get_cert_store(ssl_ctx);
910 if (store == NULL) {
911 ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
912 "SSL_CTX_get_cert_store() failed");
913 return NGX_ERROR;
914 }
915
916 store_ctx = X509_STORE_CTX_new();
917 if (store_ctx == NULL) {
918 ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
919 "X509_STORE_CTX_new() failed");
920 return NGX_ERROR;
921 }
922
923 chain = SSL_get_peer_cert_chain(c->ssl->connection);
924
925 if (X509_STORE_CTX_init(store_ctx, store, cert, chain) == 0) {
926 ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
927 "X509_STORE_CTX_init() failed");
928 X509_STORE_CTX_free(store_ctx);
929 return NGX_ERROR;
930 }
931
932 rc = X509_verify_cert(store_ctx);
933 if (rc <= 0) {
934 ngx_ssl_error(NGX_LOG_ERR, c->log, 0, "X509_verify_cert() failed");
935 X509_STORE_CTX_free(store_ctx);
936 return NGX_ERROR;
937 }
938
939 ocsp->certs = X509_STORE_CTX_get1_chain(store_ctx);
940 if (ocsp->certs == NULL) {
941 ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
942 "X509_STORE_CTX_get1_chain() failed");
943 X509_STORE_CTX_free(store_ctx);
944 return NGX_ERROR;
945 }
946
947 X509_STORE_CTX_free(store_ctx);
948 }
949
950 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
951 "ssl ocsp validate, certs:%d", sk_X509_num(ocsp->certs));
952
953 ngx_ssl_ocsp_validate_next(c);
954
955 if (ocsp->status == NGX_AGAIN) {
956 c->ssl->in_ocsp = 1;
957 return NGX_AGAIN;
958 }
959
960 return NGX_OK;
961 }
962
963
964 static void
965 ngx_ssl_ocsp_validate_next(ngx_connection_t *c)
966 {
967 ngx_int_t rc;
968 ngx_uint_t n;
969 ngx_ssl_ocsp_t *ocsp;
970 ngx_ssl_ocsp_ctx_t *ctx;
971 ngx_ssl_ocsp_conf_t *ocf;
972
973 ocsp = c->ssl->ocsp;
974 ocf = ocsp->conf;
975
976 n = sk_X509_num(ocsp->certs);
977
978 for ( ;; ) {
979
980 if (ocsp->ncert == n - 1 || (ocf->depth == 2 && ocsp->ncert == 1)) {
981 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
982 "ssl ocsp validated, certs:%ui", ocsp->ncert);
983 goto done;
984 }
985
986 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
987 "ssl ocsp validate cert:%ui", ocsp->ncert);
988
989 ctx = ngx_ssl_ocsp_start(c->log);
990 if (ctx == NULL) {
991 goto failed;
992 }
993
994 ocsp->ctx = ctx;
995
996 ctx->ssl_ctx = SSL_get_SSL_CTX(c->ssl->connection);
997 ctx->cert = sk_X509_value(ocsp->certs, ocsp->ncert);
998 ctx->issuer = sk_X509_value(ocsp->certs, ocsp->ncert + 1);
999 ctx->chain = ocsp->certs;
1000
1001 ctx->resolver = ocf->resolver;
1002 ctx->resolver_timeout = ocf->resolver_timeout;
1003
1004 ctx->handler = ngx_ssl_ocsp_handler;
1005 ctx->data = c;
1006
1007 ctx->shm_zone = ocf->shm_zone;
1008
1009 ctx->addrs = ocf->addrs;
1010 ctx->naddrs = ocf->naddrs;
1011 ctx->host = ocf->host;
1012 ctx->uri = ocf->uri;
1013 ctx->port = ocf->port;
1014
1015 if (ngx_ssl_ocsp_responder(c, ctx) != NGX_OK) {
1016 goto failed;
1017 }
1018
1019 if (ctx->uri.len == 0) {
1020 ngx_str_set(&ctx->uri, "/");
1021 }
1022
1023 ocsp->ncert++;
1024
1025 rc = ngx_ssl_ocsp_cache_lookup(ctx);
1026
1027 if (rc == NGX_ERROR) {
1028 goto failed;
1029 }
1030
1031 if (rc == NGX_DECLINED) {
1032 break;
1033 }
1034
1035 /* rc == NGX_OK */
1036
1037 if (ctx->status != V_OCSP_CERTSTATUS_GOOD) {
1038 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1039 "ssl ocsp cached status \"%s\"",
1040 OCSP_cert_status_str(ctx->status));
1041 ocsp->cert_status = ctx->status;
1042 goto done;
1043 }
1044
1045 ocsp->ctx = NULL;
1046 ngx_ssl_ocsp_done(ctx);
1047 }
1048
1049 ngx_ssl_ocsp_request(ctx);
1050 return;
1051
1052 done:
1053
1054 ocsp->status = NGX_OK;
1055 return;
1056
1057 failed:
1058
1059 ocsp->status = NGX_ERROR;
1060 }
1061
1062
1063 static void
1064 ngx_ssl_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
1065 {
1066 ngx_int_t rc;
1067 ngx_ssl_ocsp_t *ocsp;
1068 ngx_connection_t *c;
1069
1070 c = ctx->data;
1071 ocsp = c->ssl->ocsp;
1072 ocsp->ctx = NULL;
1073
1074 rc = ngx_ssl_ocsp_verify(ctx);
1075 if (rc != NGX_OK) {
1076 ocsp->status = rc;
1077 ngx_ssl_ocsp_done(ctx);
1078 goto done;
1079 }
1080
1081 rc = ngx_ssl_ocsp_cache_store(ctx);
1082 if (rc != NGX_OK) {
1083 ocsp->status = rc;
1084 ngx_ssl_ocsp_done(ctx);
1085 goto done;
1086 }
1087
1088 if (ctx->status != V_OCSP_CERTSTATUS_GOOD) {
1089 ocsp->cert_status = ctx->status;
1090 ocsp->status = NGX_OK;
1091 ngx_ssl_ocsp_done(ctx);
1092 goto done;
1093 }
1094
1095 ngx_ssl_ocsp_done(ctx);
1096
1097 ngx_ssl_ocsp_validate_next(c);
1098
1099 done:
1100
1101 if (ocsp->status == NGX_AGAIN || !c->ssl->in_ocsp) {
1102 return;
1103 }
1104
1105 c->ssl->handshaked = 1;
1106
1107 c->ssl->handler(c);
1108 }
1109
1110
1111 static ngx_int_t
1112 ngx_ssl_ocsp_responder(ngx_connection_t *c, ngx_ssl_ocsp_ctx_t *ctx)
1113 {
1114 char *s;
1115 ngx_str_t responder;
1116 ngx_url_t u;
1117 STACK_OF(OPENSSL_STRING) *aia;
1118
1119 if (ctx->host.len) {
1120 return NGX_OK;
1121 }
1122
1123 /* extract OCSP responder URL from certificate */
1124
1125 aia = X509_get1_ocsp(ctx->cert);
1126 if (aia == NULL) {
1127 ngx_log_error(NGX_LOG_ERR, c->log, 0,
1128 "no OCSP responder URL in certificate");
1129 return NGX_ERROR;
1130 }
1131
1132 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
1133 s = sk_OPENSSL_STRING_value(aia, 0);
1134 #else
1135 s = sk_value(aia, 0);
1136 #endif
1137 if (s == NULL) {
1138 ngx_log_error(NGX_LOG_ERR, c->log, 0,
1139 "no OCSP responder URL in certificate");
1140 X509_email_free(aia);
1141 return NGX_ERROR;
1142 }
1143
1144 responder.len = ngx_strlen(s);
1145 responder.data = ngx_palloc(ctx->pool, responder.len);
1146 if (responder.data == NULL) {
1147 X509_email_free(aia);
1148 return NGX_ERROR;
1149 }
1150
1151 ngx_memcpy(responder.data, s, responder.len);
1152 X509_email_free(aia);
1153
1154 ngx_memzero(&u, sizeof(ngx_url_t));
1155
1156 u.url = responder;
1157 u.default_port = 80;
1158 u.uri_part = 1;
1159 u.no_resolve = 1;
1160
1161 if (u.url.len > 7
1162 && ngx_strncasecmp(u.url.data, (u_char *) "http://", 7) == 0)
1163 {
1164 u.url.len -= 7;
1165 u.url.data += 7;
1166
1167 } else {
1168 ngx_log_error(NGX_LOG_ERR, c->log, 0,
1169 "invalid URL prefix in OCSP responder \"%V\" "
1170 "in certificate", &u.url);
1171 return NGX_ERROR;
1172 }
1173
1174 if (ngx_parse_url(ctx->pool, &u) != NGX_OK) {
1175 if (u.err) {
1176 ngx_log_error(NGX_LOG_ERR, c->log, 0,
1177 "%s in OCSP responder \"%V\" in certificate",
1178 u.err, &u.url);
1179 }
1180
1181 return NGX_ERROR;
1182 }
1183
1184 if (u.host.len == 0) {
1185 ngx_log_error(NGX_LOG_ERR, c->log, 0,
1186 "empty host in OCSP responder in certificate");
1187 return NGX_ERROR;
1188 }
1189
1190 ctx->addrs = u.addrs;
1191 ctx->naddrs = u.naddrs;
1192 ctx->host = u.host;
1193 ctx->uri = u.uri;
1194 ctx->port = u.port;
1195
1196 return NGX_OK;
1197 }
1198
1199
1200 ngx_int_t
1201 ngx_ssl_ocsp_get_status(ngx_connection_t *c, const char **s)
1202 {
1203 ngx_ssl_ocsp_t *ocsp;
1204
1205 ocsp = c->ssl->ocsp;
1206 if (ocsp == NULL) {
1207 return NGX_OK;
1208 }
1209
1210 if (ocsp->status == NGX_ERROR) {
1211 *s = "certificate status request failed";
1212 return NGX_DECLINED;
1213 }
1214
1215 switch (ocsp->cert_status) {
1216
1217 case V_OCSP_CERTSTATUS_GOOD:
1218 return NGX_OK;
1219
1220 case V_OCSP_CERTSTATUS_REVOKED:
1221 *s = "certificate revoked";
1222 break;
1223
1224 default: /* V_OCSP_CERTSTATUS_UNKNOWN */
1225 *s = "certificate status unknown";
1226 }
1227
1228 return NGX_DECLINED;
1229 }
1230
1231
1232 void
1233 ngx_ssl_ocsp_cleanup(ngx_connection_t *c)
1234 {
1235 ngx_ssl_ocsp_t *ocsp;
1236
1237 ocsp = c->ssl->ocsp;
1238 if (ocsp == NULL) {
1239 return;
1240 }
1241
1242 if (ocsp->ctx) {
1243 ngx_ssl_ocsp_done(ocsp->ctx);
1244 ocsp->ctx = NULL;
1245 }
1246
1247 if (ocsp->certs) {
1248 sk_X509_pop_free(ocsp->certs, X509_free);
1249 ocsp->certs = NULL;
1250 }
1251 }
1252
1253
823 static ngx_ssl_ocsp_ctx_t * 1254 static ngx_ssl_ocsp_ctx_t *
824 ngx_ssl_ocsp_start(void) 1255 ngx_ssl_ocsp_start(ngx_log_t *log)
825 { 1256 {
826 ngx_log_t *log;
827 ngx_pool_t *pool; 1257 ngx_pool_t *pool;
828 ngx_ssl_ocsp_ctx_t *ctx; 1258 ngx_ssl_ocsp_ctx_t *ctx;
829 1259
830 pool = ngx_create_pool(2048, ngx_cycle->log); 1260 pool = ngx_create_pool(2048, log);
831 if (pool == NULL) { 1261 if (pool == NULL) {
832 return NULL; 1262 return NULL;
833 } 1263 }
834 1264
835 ctx = ngx_pcalloc(pool, sizeof(ngx_ssl_ocsp_ctx_t)); 1265 ctx = ngx_pcalloc(pool, sizeof(ngx_ssl_ocsp_ctx_t));
883 ctx->handler(ctx); 1313 ctx->handler(ctx);
884 } 1314 }
885 1315
886 1316
887 static void 1317 static void
1318 ngx_ssl_ocsp_next(ngx_ssl_ocsp_ctx_t *ctx)
1319 {
1320 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1321 "ssl ocsp next");
1322
1323 if (++ctx->naddr >= ctx->naddrs) {
1324 ngx_ssl_ocsp_error(ctx);
1325 return;
1326 }
1327
1328 ctx->request->pos = ctx->request->start;
1329
1330 if (ctx->response) {
1331 ctx->response->last = ctx->response->pos;
1332 }
1333
1334 if (ctx->peer.connection) {
1335 ngx_close_connection(ctx->peer.connection);
1336 ctx->peer.connection = NULL;
1337 }
1338
1339 ctx->state = 0;
1340 ctx->count = 0;
1341 ctx->done = 0;
1342
1343 ngx_ssl_ocsp_connect(ctx);
1344 }
1345
1346
1347 static void
888 ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx) 1348 ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx)
889 { 1349 {
890 ngx_resolver_ctx_t *resolve, temp; 1350 ngx_resolver_ctx_t *resolve, temp;
891 1351
892 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0, 1352 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
907 ngx_ssl_ocsp_error(ctx); 1367 ngx_ssl_ocsp_error(ctx);
908 return; 1368 return;
909 } 1369 }
910 1370
911 if (resolve == NGX_NO_RESOLVER) { 1371 if (resolve == NGX_NO_RESOLVER) {
1372 if (ctx->naddrs == 0) {
1373 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1374 "no resolver defined to resolve %V", &ctx->host);
1375
1376 ngx_ssl_ocsp_error(ctx);
1377 return;
1378 }
1379
912 ngx_log_error(NGX_LOG_WARN, ctx->log, 0, 1380 ngx_log_error(NGX_LOG_WARN, ctx->log, 0,
913 "no resolver defined to resolve %V", &ctx->host); 1381 "no resolver defined to resolve %V", &ctx->host);
914 goto connect; 1382 goto connect;
915 } 1383 }
916 1384
1020 1488
1021 1489
1022 static void 1490 static void
1023 ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx) 1491 ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx)
1024 { 1492 {
1025 ngx_int_t rc; 1493 ngx_int_t rc;
1026 1494 ngx_addr_t *addr;
1027 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0, 1495
1028 "ssl ocsp connect"); 1496 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1029 1497 "ssl ocsp connect %ui/%ui", ctx->naddr, ctx->naddrs);
1030 /* TODO: use all ip addresses */ 1498
1031 1499 addr = &ctx->addrs[ctx->naddr];
1032 ctx->peer.sockaddr = ctx->addrs[0].sockaddr; 1500
1033 ctx->peer.socklen = ctx->addrs[0].socklen; 1501 ctx->peer.sockaddr = addr->sockaddr;
1034 ctx->peer.name = &ctx->addrs[0].name; 1502 ctx->peer.socklen = addr->socklen;
1503 ctx->peer.name = &addr->name;
1035 ctx->peer.get = ngx_event_get_peer; 1504 ctx->peer.get = ngx_event_get_peer;
1036 ctx->peer.log = ctx->log; 1505 ctx->peer.log = ctx->log;
1037 ctx->peer.log_error = NGX_ERROR_ERR; 1506 ctx->peer.log_error = NGX_ERROR_ERR;
1038 1507
1039 rc = ngx_event_connect_peer(&ctx->peer); 1508 rc = ngx_event_connect_peer(&ctx->peer);
1040 1509
1041 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0, 1510 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1042 "ssl ocsp connect peer done"); 1511 "ssl ocsp connect peer done");
1043 1512
1044 if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) { 1513 if (rc == NGX_ERROR) {
1045 ngx_ssl_ocsp_error(ctx); 1514 ngx_ssl_ocsp_error(ctx);
1046 return; 1515 return;
1047 } 1516 }
1048 1517
1518 if (rc == NGX_BUSY || rc == NGX_DECLINED) {
1519 ngx_ssl_ocsp_next(ctx);
1520 return;
1521 }
1522
1049 ctx->peer.connection->data = ctx; 1523 ctx->peer.connection->data = ctx;
1050 ctx->peer.connection->pool = ctx->pool; 1524 ctx->peer.connection->pool = ctx->pool;
1051 1525
1052 ctx->peer.connection->read->handler = ngx_ssl_ocsp_read_handler; 1526 ctx->peer.connection->read->handler = ngx_ssl_ocsp_read_handler;
1053 ctx->peer.connection->write->handler = ngx_ssl_ocsp_write_handler; 1527 ctx->peer.connection->write->handler = ngx_ssl_ocsp_write_handler;
1054 1528
1055 ctx->process = ngx_ssl_ocsp_process_status_line; 1529 ctx->process = ngx_ssl_ocsp_process_status_line;
1056 1530
1057 ngx_add_timer(ctx->peer.connection->read, ctx->timeout); 1531 if (ctx->timeout) {
1058 ngx_add_timer(ctx->peer.connection->write, ctx->timeout); 1532 ngx_add_timer(ctx->peer.connection->read, ctx->timeout);
1533 ngx_add_timer(ctx->peer.connection->write, ctx->timeout);
1534 }
1059 1535
1060 if (rc == NGX_OK) { 1536 if (rc == NGX_OK) {
1061 ngx_ssl_ocsp_write_handler(ctx->peer.connection->write); 1537 ngx_ssl_ocsp_write_handler(ctx->peer.connection->write);
1062 return; 1538 return;
1063 } 1539 }
1078 "ssl ocsp write handler"); 1554 "ssl ocsp write handler");
1079 1555
1080 if (wev->timedout) { 1556 if (wev->timedout) {
1081 ngx_log_error(NGX_LOG_ERR, wev->log, NGX_ETIMEDOUT, 1557 ngx_log_error(NGX_LOG_ERR, wev->log, NGX_ETIMEDOUT,
1082 "OCSP responder timed out"); 1558 "OCSP responder timed out");
1083 ngx_ssl_ocsp_error(ctx); 1559 ngx_ssl_ocsp_next(ctx);
1084 return; 1560 return;
1085 } 1561 }
1086 1562
1087 size = ctx->request->last - ctx->request->pos; 1563 size = ctx->request->last - ctx->request->pos;
1088 1564
1089 n = ngx_send(c, ctx->request->pos, size); 1565 n = ngx_send(c, ctx->request->pos, size);
1090 1566
1091 if (n == NGX_ERROR) { 1567 if (n == NGX_ERROR) {
1092 ngx_ssl_ocsp_error(ctx); 1568 ngx_ssl_ocsp_next(ctx);
1093 return; 1569 return;
1094 } 1570 }
1095 1571
1096 if (n > 0) { 1572 if (n > 0) {
1097 ctx->request->pos += n; 1573 ctx->request->pos += n;
1109 1585
1110 return; 1586 return;
1111 } 1587 }
1112 } 1588 }
1113 1589
1114 if (!wev->timer_set) { 1590 if (!wev->timer_set && ctx->timeout) {
1115 ngx_add_timer(wev, ctx->timeout); 1591 ngx_add_timer(wev, ctx->timeout);
1116 } 1592 }
1117 } 1593 }
1118 1594
1119 1595
1132 "ssl ocsp read handler"); 1608 "ssl ocsp read handler");
1133 1609
1134 if (rev->timedout) { 1610 if (rev->timedout) {
1135 ngx_log_error(NGX_LOG_ERR, rev->log, NGX_ETIMEDOUT, 1611 ngx_log_error(NGX_LOG_ERR, rev->log, NGX_ETIMEDOUT,
1136 "OCSP responder timed out"); 1612 "OCSP responder timed out");
1137 ngx_ssl_ocsp_error(ctx); 1613 ngx_ssl_ocsp_next(ctx);
1138 return; 1614 return;
1139 } 1615 }
1140 1616
1141 if (ctx->response == NULL) { 1617 if (ctx->response == NULL) {
1142 ctx->response = ngx_create_temp_buf(ctx->pool, 16384); 1618 ctx->response = ngx_create_temp_buf(ctx->pool, 16384);
1156 ctx->response->last += n; 1632 ctx->response->last += n;
1157 1633
1158 rc = ctx->process(ctx); 1634 rc = ctx->process(ctx);
1159 1635
1160 if (rc == NGX_ERROR) { 1636 if (rc == NGX_ERROR) {
1161 ngx_ssl_ocsp_error(ctx); 1637 ngx_ssl_ocsp_next(ctx);
1162 return; 1638 return;
1163 } 1639 }
1164 1640
1165 continue; 1641 continue;
1166 } 1642 }
1187 } 1663 }
1188 1664
1189 ngx_log_error(NGX_LOG_ERR, ctx->log, 0, 1665 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1190 "OCSP responder prematurely closed connection"); 1666 "OCSP responder prematurely closed connection");
1191 1667
1192 ngx_ssl_ocsp_error(ctx); 1668 ngx_ssl_ocsp_next(ctx);
1193 } 1669 }
1194 1670
1195 1671
1196 static void 1672 static void
1197 ngx_ssl_ocsp_dummy_handler(ngx_event_t *ev) 1673 ngx_ssl_ocsp_dummy_handler(ngx_event_t *ev)
1829 2305
1830 return NGX_AGAIN; 2306 return NGX_AGAIN;
1831 } 2307 }
1832 2308
1833 2309
2310 static ngx_int_t
2311 ngx_ssl_ocsp_verify(ngx_ssl_ocsp_ctx_t *ctx)
2312 {
2313 int n;
2314 size_t len;
2315 X509_STORE *store;
2316 const u_char *p;
2317 OCSP_CERTID *id;
2318 OCSP_RESPONSE *ocsp;
2319 OCSP_BASICRESP *basic;
2320 ASN1_GENERALIZEDTIME *thisupdate, *nextupdate;
2321
2322 ocsp = NULL;
2323 basic = NULL;
2324 id = NULL;
2325
2326 if (ctx->code != 200) {
2327 goto error;
2328 }
2329
2330 /* check the response */
2331
2332 len = ctx->response->last - ctx->response->pos;
2333 p = ctx->response->pos;
2334
2335 ocsp = d2i_OCSP_RESPONSE(NULL, &p, len);
2336 if (ocsp == NULL) {
2337 ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
2338 "d2i_OCSP_RESPONSE() failed");
2339 goto error;
2340 }
2341
2342 n = OCSP_response_status(ocsp);
2343
2344 if (n != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
2345 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
2346 "OCSP response not successful (%d: %s)",
2347 n, OCSP_response_status_str(n));
2348 goto error;
2349 }
2350
2351 basic = OCSP_response_get1_basic(ocsp);
2352 if (basic == NULL) {
2353 ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
2354 "OCSP_response_get1_basic() failed");
2355 goto error;
2356 }
2357
2358 store = SSL_CTX_get_cert_store(ctx->ssl_ctx);
2359 if (store == NULL) {
2360 ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
2361 "SSL_CTX_get_cert_store() failed");
2362 goto error;
2363 }
2364
2365 if (OCSP_basic_verify(basic, ctx->chain, store, ctx->flags) != 1) {
2366 ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
2367 "OCSP_basic_verify() failed");
2368 goto error;
2369 }
2370
2371 id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
2372 if (id == NULL) {
2373 ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
2374 "OCSP_cert_to_id() failed");
2375 goto error;
2376 }
2377
2378 if (OCSP_resp_find_status(basic, id, &ctx->status, NULL, NULL,
2379 &thisupdate, &nextupdate)
2380 != 1)
2381 {
2382 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
2383 "certificate status not found in the OCSP response");
2384 goto error;
2385 }
2386
2387 if (OCSP_check_validity(thisupdate, nextupdate, 300, -1) != 1) {
2388 ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
2389 "OCSP_check_validity() failed");
2390 goto error;
2391 }
2392
2393 if (nextupdate) {
2394 ctx->valid = ngx_ssl_stapling_time(nextupdate);
2395 if (ctx->valid == (time_t) NGX_ERROR) {
2396 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
2397 "invalid nextUpdate time in certificate status");
2398 goto error;
2399 }
2400
2401 } else {
2402 ctx->valid = NGX_MAX_TIME_T_VALUE;
2403 }
2404
2405 OCSP_CERTID_free(id);
2406 OCSP_BASICRESP_free(basic);
2407 OCSP_RESPONSE_free(ocsp);
2408
2409 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
2410 "ssl ocsp response, %s, %uz",
2411 OCSP_cert_status_str(ctx->status), len);
2412
2413 return NGX_OK;
2414
2415 error:
2416
2417 if (id) {
2418 OCSP_CERTID_free(id);
2419 }
2420
2421 if (basic) {
2422 OCSP_BASICRESP_free(basic);
2423 }
2424
2425 if (ocsp) {
2426 OCSP_RESPONSE_free(ocsp);
2427 }
2428
2429 return NGX_ERROR;
2430 }
2431
2432
2433 ngx_int_t
2434 ngx_ssl_ocsp_cache_init(ngx_shm_zone_t *shm_zone, void *data)
2435 {
2436 size_t len;
2437 ngx_slab_pool_t *shpool;
2438 ngx_ssl_ocsp_cache_t *cache;
2439
2440 if (data) {
2441 shm_zone->data = data;
2442 return NGX_OK;
2443 }
2444
2445 shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
2446
2447 if (shm_zone->shm.exists) {
2448 shm_zone->data = shpool->data;
2449 return NGX_OK;
2450 }
2451
2452 cache = ngx_slab_alloc(shpool, sizeof(ngx_ssl_ocsp_cache_t));
2453 if (cache == NULL) {
2454 return NGX_ERROR;
2455 }
2456
2457 shpool->data = cache;
2458 shm_zone->data = cache;
2459
2460 ngx_rbtree_init(&cache->rbtree, &cache->sentinel,
2461 ngx_str_rbtree_insert_value);
2462
2463 ngx_queue_init(&cache->expire_queue);
2464
2465 len = sizeof(" in OCSP cache \"\"") + shm_zone->shm.name.len;
2466
2467 shpool->log_ctx = ngx_slab_alloc(shpool, len);
2468 if (shpool->log_ctx == NULL) {
2469 return NGX_ERROR;
2470 }
2471
2472 ngx_sprintf(shpool->log_ctx, " in OCSP cache \"%V\"%Z",
2473 &shm_zone->shm.name);
2474
2475 shpool->log_nomem = 0;
2476
2477 return NGX_OK;
2478 }
2479
2480
2481 static ngx_int_t
2482 ngx_ssl_ocsp_cache_lookup(ngx_ssl_ocsp_ctx_t *ctx)
2483 {
2484 uint32_t hash;
2485 ngx_shm_zone_t *shm_zone;
2486 ngx_slab_pool_t *shpool;
2487 ngx_ssl_ocsp_cache_t *cache;
2488 ngx_ssl_ocsp_cache_node_t *node;
2489
2490 shm_zone = ctx->shm_zone;
2491
2492 if (shm_zone == NULL) {
2493 return NGX_DECLINED;
2494 }
2495
2496 if (ngx_ssl_ocsp_create_key(ctx) != NGX_OK) {
2497 return NGX_ERROR;
2498 }
2499
2500 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0, "ssl ocsp cache lookup");
2501
2502 cache = shm_zone->data;
2503 shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
2504 hash = ngx_hash_key(ctx->key.data, ctx->key.len);
2505
2506 ngx_shmtx_lock(&shpool->mutex);
2507
2508 node = (ngx_ssl_ocsp_cache_node_t *)
2509 ngx_str_rbtree_lookup(&cache->rbtree, &ctx->key, hash);
2510
2511 if (node) {
2512 if (node->valid > ngx_time()) {
2513 ctx->status = node->status;
2514 ngx_shmtx_unlock(&shpool->mutex);
2515
2516 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
2517 "ssl ocsp cache hit, %s",
2518 OCSP_cert_status_str(ctx->status));
2519
2520 return NGX_OK;
2521 }
2522
2523 ngx_queue_remove(&node->queue);
2524 ngx_rbtree_delete(&cache->rbtree, &node->node.node);
2525 ngx_slab_free_locked(shpool, node);
2526
2527 ngx_shmtx_unlock(&shpool->mutex);
2528
2529 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
2530 "ssl ocsp cache expired");
2531
2532 return NGX_DECLINED;
2533 }
2534
2535 ngx_shmtx_unlock(&shpool->mutex);
2536
2537 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0, "ssl ocsp cache miss");
2538
2539 return NGX_DECLINED;
2540 }
2541
2542
2543 static ngx_int_t
2544 ngx_ssl_ocsp_cache_store(ngx_ssl_ocsp_ctx_t *ctx)
2545 {
2546 time_t now, valid;
2547 uint32_t hash;
2548 ngx_queue_t *q;
2549 ngx_shm_zone_t *shm_zone;
2550 ngx_slab_pool_t *shpool;
2551 ngx_ssl_ocsp_cache_t *cache;
2552 ngx_ssl_ocsp_cache_node_t *node;
2553
2554 shm_zone = ctx->shm_zone;
2555
2556 if (shm_zone == NULL) {
2557 return NGX_OK;
2558 }
2559
2560 valid = ctx->valid;
2561
2562 now = ngx_time();
2563
2564 if (valid < now) {
2565 return NGX_OK;
2566 }
2567
2568 if (valid == NGX_MAX_TIME_T_VALUE) {
2569 valid = now + 3600;
2570 }
2571
2572 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
2573 "ssl ocsp cache store, valid:%T", valid - now);
2574
2575 cache = shm_zone->data;
2576 shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
2577 hash = ngx_hash_key(ctx->key.data, ctx->key.len);
2578
2579 ngx_shmtx_lock(&shpool->mutex);
2580
2581 node = ngx_slab_calloc_locked(shpool,
2582 sizeof(ngx_ssl_ocsp_cache_node_t) + ctx->key.len);
2583 if (node == NULL) {
2584
2585 if (!ngx_queue_empty(&cache->expire_queue)) {
2586 q = ngx_queue_last(&cache->expire_queue);
2587 node = ngx_queue_data(q, ngx_ssl_ocsp_cache_node_t, queue);
2588
2589 ngx_rbtree_delete(&cache->rbtree, &node->node.node);
2590 ngx_queue_remove(q);
2591 ngx_slab_free_locked(shpool, node);
2592
2593 node = ngx_slab_alloc_locked(shpool,
2594 sizeof(ngx_ssl_ocsp_cache_node_t) + ctx->key.len);
2595 }
2596
2597 if (node == NULL) {
2598 ngx_shmtx_unlock(&shpool->mutex);
2599 ngx_log_error(NGX_LOG_ALERT, ctx->log, 0,
2600 "could not allocate new entry%s", shpool->log_ctx);
2601 return NGX_ERROR;
2602 }
2603 }
2604
2605 node->node.str.len = ctx->key.len;
2606 node->node.str.data = (u_char *) node + sizeof(ngx_ssl_ocsp_cache_node_t);
2607 ngx_memcpy(node->node.str.data, ctx->key.data, ctx->key.len);
2608 node->node.node.key = hash;
2609 node->status = ctx->status;
2610 node->valid = valid;
2611
2612 ngx_rbtree_insert(&cache->rbtree, &node->node.node);
2613 ngx_queue_insert_head(&cache->expire_queue, &node->queue);
2614
2615 ngx_shmtx_unlock(&shpool->mutex);
2616
2617 return NGX_OK;
2618 }
2619
2620
2621 static ngx_int_t
2622 ngx_ssl_ocsp_create_key(ngx_ssl_ocsp_ctx_t *ctx)
2623 {
2624 u_char *p;
2625 X509_NAME *name;
2626 ASN1_INTEGER *serial;
2627
2628 p = ngx_pnalloc(ctx->pool, 60);
2629 if (p == NULL) {
2630 return NGX_ERROR;
2631 }
2632
2633 ctx->key.data = p;
2634 ctx->key.len = 60;
2635
2636 name = X509_get_subject_name(ctx->issuer);
2637 if (X509_NAME_digest(name, EVP_sha1(), p, NULL) == 0) {
2638 return NGX_ERROR;
2639 }
2640
2641 p += 20;
2642
2643 if (X509_pubkey_digest(ctx->issuer, EVP_sha1(), p, NULL) == 0) {
2644 return NGX_ERROR;
2645 }
2646
2647 p += 20;
2648
2649 serial = X509_get_serialNumber(ctx->cert);
2650 if (serial->length > 20) {
2651 return NGX_ERROR;
2652 }
2653
2654 p = ngx_cpymem(p, serial->data, serial->length);
2655 ngx_memzero(p, 20 - serial->length);
2656
2657 #if (NGX_DEBUG)
2658 {
2659 u_char buf[120];
2660
2661 ngx_hex_dump(buf, ctx->key.data, ctx->key.len);
2662
2663 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
2664 "ssl ocsp key %*s", sizeof(buf), buf);
2665 }
2666 #endif
2667
2668 return NGX_OK;
2669 }
2670
2671
1834 static u_char * 2672 static u_char *
1835 ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len) 2673 ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len)
1836 { 2674 {
1837 u_char *p; 2675 u_char *p;
1838 ngx_ssl_ocsp_ctx_t *ctx; 2676 ngx_ssl_ocsp_ctx_t *ctx;
1889 { 2727 {
1890 return NGX_OK; 2728 return NGX_OK;
1891 } 2729 }
1892 2730
1893 2731
2732 ngx_int_t
2733 ngx_ssl_ocsp(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *responder,
2734 ngx_uint_t depth, ngx_shm_zone_t *shm_zone)
2735 {
2736 ngx_log_error(NGX_LOG_EMERG, ssl->log, 0,
2737 "\"ssl_ocsp\" is not supported on this platform");
2738
2739 return NGX_ERROR;
2740 }
2741
2742
2743 ngx_int_t
2744 ngx_ssl_ocsp_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
2745 ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)
2746 {
2747 return NGX_OK;
2748 }
2749
2750
2751 ngx_int_t
2752 ngx_ssl_ocsp_validate(ngx_connection_t *c)
2753 {
2754 return NGX_OK;
2755 }
2756
2757
2758 ngx_int_t
2759 ngx_ssl_ocsp_get_status(ngx_connection_t *c, const char **s)
2760 {
2761 return NGX_OK;
2762 }
2763
2764
2765 void
2766 ngx_ssl_ocsp_cleanup(ngx_connection_t *c)
2767 {
2768 }
2769
2770
2771 ngx_int_t
2772 ngx_ssl_ocsp_cache_init(ngx_shm_zone_t *shm_zone, void *data)
2773 {
2774 return NGX_OK;
2775 }
2776
2777
1894 #endif 2778 #endif