3 * Copyright (C) Maxim Dounin
4 * Copyright (C) Nginx, Inc.
8 #include <ngx_config.h>
10 #include <ngx_event.h>
11 #include <ngx_event_connect.h>
14 #if (!defined OPENSSL_NO_OCSP && defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB)
21 ngx_resolver_t *resolver;
22 ngx_msec_t resolver_timeout;
44 typedef struct ngx_ssl_ocsp_ctx_s ngx_ssl_ocsp_ctx_t;
46 struct ngx_ssl_ocsp_ctx_s {
59 ngx_resolver_t *resolver;
60 ngx_msec_t resolver_timeout;
64 void (*handler)(ngx_ssl_ocsp_ctx_t *ctx);
69 ngx_peer_connection_t peer;
71 ngx_int_t (*process)(ngx_ssl_ocsp_ctx_t *ctx);
80 u_char *header_name_start;
81 u_char *header_name_end;
90 static ngx_int_t ngx_ssl_stapling_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl,
91 X509 *cert, ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify);
92 static ngx_int_t ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl,
93 ngx_ssl_stapling_t *staple, ngx_str_t *file);
94 static ngx_int_t ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl,
95 ngx_ssl_stapling_t *staple);
96 static ngx_int_t ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl,
97 ngx_ssl_stapling_t *staple, ngx_str_t *responder);
99 static int ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn,
101 static void ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple);
102 static void ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx);
104 static time_t ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time);
106 static void ngx_ssl_stapling_cleanup(void *data);
108 static ngx_ssl_ocsp_ctx_t *ngx_ssl_ocsp_start(void);
109 static void ngx_ssl_ocsp_done(ngx_ssl_ocsp_ctx_t *ctx);
110 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);
112 static void ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx);
113 static void ngx_ssl_ocsp_write_handler(ngx_event_t *wev);
114 static void ngx_ssl_ocsp_read_handler(ngx_event_t *rev);
115 static void ngx_ssl_ocsp_dummy_handler(ngx_event_t *ev);
117 static ngx_int_t ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx);
118 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);
120 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);
122 static ngx_int_t ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx);
124 static u_char *ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len);
128 ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file,
129 ngx_str_t *responder, ngx_uint_t verify)
133 for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
135 cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index))
137 if (ngx_ssl_stapling_certificate(cf, ssl, cert, file, responder, verify)
144 SSL_CTX_set_tlsext_status_cb(ssl->ctx, ngx_ssl_certificate_status_callback);
151 ngx_ssl_stapling_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, X509 *cert,
152 ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify)
155 ngx_pool_cleanup_t *cln;
156 ngx_ssl_stapling_t *staple;
158 staple = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_stapling_t));
159 if (staple == NULL) {
163 cln = ngx_pool_cleanup_add(cf->pool, 0);
168 cln->handler = ngx_ssl_stapling_cleanup;
171 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");
176 staple->ssl_ctx = ssl->ctx;
177 staple->timeout = 60000;
178 staple->verify = verify;
180 staple->name = X509_get_ex_data(staple->cert,
181 ngx_ssl_certificate_name_index);
184 /* use OCSP response from the file */
186 if (ngx_ssl_stapling_file(cf, ssl, staple, file) != NGX_OK) {
193 rc = ngx_ssl_stapling_issuer(cf, ssl, staple);
195 if (rc == NGX_DECLINED) {
203 rc = ngx_ssl_stapling_responder(cf, ssl, staple, responder);
205 if (rc == NGX_DECLINED) {
218 ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl,
219 ngx_ssl_stapling_t *staple, ngx_str_t *file)
224 OCSP_RESPONSE *response;
226 if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) {
230 bio = BIO_new_file((char *) file->data, "r");
232 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
233 "BIO_new_file(\"%s\") failed", file->data);
237 response = d2i_OCSP_RESPONSE_bio(bio, NULL);
238 if (response == NULL) {
239 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
240 "d2i_OCSP_RESPONSE_bio(\"%s\") failed", file->data);
245 len = i2d_OCSP_RESPONSE(response, NULL);
247 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
248 "i2d_OCSP_RESPONSE(\"%s\") failed", file->data);
252 buf = ngx_alloc(len, ssl->log);
258 len = i2d_OCSP_RESPONSE(response, &p);
260 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
261 "i2d_OCSP_RESPONSE(\"%s\") failed", file->data);
266 OCSP_RESPONSE_free(response);
269 staple->staple.data = buf;
270 staple->staple.len = len;
271 staple->valid = NGX_MAX_TIME_T_VALUE;
277 OCSP_RESPONSE_free(response);
285 ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl,
286 ngx_ssl_stapling_t *staple)
291 X509_STORE_CTX *store_ctx;
292 STACK_OF(X509) *chain;
296 #ifdef SSL_CTRL_SELECT_CURRENT_CERT
298 SSL_CTX_select_current_cert(ssl->ctx, cert);
301 #ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
303 SSL_CTX_get_extra_chain_certs(ssl->ctx, &chain);
305 chain = ssl->ctx->extra_certs;
308 n = sk_X509_num(chain);
310 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
311 "SSL get issuer: %d extra certs", n);
313 for (i = 0; i < n; i++) {
314 issuer = sk_X509_value(chain, i);
315 if (X509_check_issued(issuer, cert) == X509_V_OK) {
316 #if OPENSSL_VERSION_NUMBER >= 0x10100001L
319 CRYPTO_add(&issuer->references, 1, CRYPTO_LOCK_X509);
322 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
323 "SSL get issuer: found %p in extra certs", issuer);
325 staple->issuer = issuer;
331 store = SSL_CTX_get_cert_store(ssl->ctx);
333 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
334 "SSL_CTX_get_cert_store() failed");
338 store_ctx = X509_STORE_CTX_new();
339 if (store_ctx == NULL) {
340 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
341 "X509_STORE_CTX_new() failed");
345 if (X509_STORE_CTX_init(store_ctx, store, NULL, NULL) == 0) {
346 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
347 "X509_STORE_CTX_init() failed");
348 X509_STORE_CTX_free(store_ctx);
352 rc = X509_STORE_CTX_get1_issuer(&issuer, store_ctx, cert);
355 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
356 "X509_STORE_CTX_get1_issuer() failed");
357 X509_STORE_CTX_free(store_ctx);
362 ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
363 "\"ssl_stapling\" ignored, "
364 "issuer certificate not found for certificate \"%s\"",
366 X509_STORE_CTX_free(store_ctx);
370 X509_STORE_CTX_free(store_ctx);
372 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
373 "SSL get issuer: found %p in cert store", issuer);
375 staple->issuer = issuer;
382 ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl,
383 ngx_ssl_stapling_t *staple, ngx_str_t *responder)
388 STACK_OF(OPENSSL_STRING) *aia;
390 if (responder->len == 0) {
392 /* extract OCSP responder URL from certificate */
394 aia = X509_get1_ocsp(staple->cert);
396 ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
397 "\"ssl_stapling\" ignored, "
398 "no OCSP responder URL in the certificate \"%s\"",
403 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
404 s = sk_OPENSSL_STRING_value(aia, 0);
406 s = sk_value(aia, 0);
409 ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
410 "\"ssl_stapling\" ignored, "
411 "no OCSP responder URL in the certificate \"%s\"",
413 X509_email_free(aia);
419 responder->len = ngx_strlen(s);
420 responder->data = ngx_palloc(cf->pool, responder->len);
421 if (responder->data == NULL) {
422 X509_email_free(aia);
426 ngx_memcpy(responder->data, s, responder->len);
427 X509_email_free(aia);
430 ngx_memzero(&u, sizeof(ngx_url_t));
437 && ngx_strncasecmp(u.url.data, (u_char *) "http://", 7) == 0)
443 ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
444 "\"ssl_stapling\" ignored, "
445 "invalid URL prefix in OCSP responder \"%V\" "
446 "in the certificate \"%s\"",
447 &u.url, staple->name);
451 if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
453 ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
454 "\"ssl_stapling\" ignored, "
455 "%s in OCSP responder \"%V\" "
456 "in the certificate \"%s\"",
457 u.err, &u.url, staple->name);
464 staple->addrs = u.addrs;
465 staple->host = u.host;
467 staple->port = u.port;
469 if (staple->uri.len == 0) {
470 ngx_str_set(&staple->uri, "/");
478 ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
479 ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)
482 ngx_ssl_stapling_t *staple;
484 for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
486 cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index))
488 staple = X509_get_ex_data(cert, ngx_ssl_stapling_index);
489 staple->resolver = resolver;
490 staple->resolver_timeout = resolver_timeout;
498 ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn, void *data)
504 ngx_ssl_stapling_t *staple;
506 c = ngx_ssl_get_connection(ssl_conn);
508 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
509 "SSL certificate status callback");
511 rc = SSL_TLSEXT_ERR_NOACK;
513 cert = SSL_get_certificate(ssl_conn);
514 staple = X509_get_ex_data(cert, ngx_ssl_stapling_index);
516 if (staple == NULL) {
520 if (staple->staple.len
521 && staple->valid >= ngx_time())
523 /* we have to copy ocsp response as OpenSSL will free it by itself */
525 p = OPENSSL_malloc(staple->staple.len);
527 ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "OPENSSL_malloc() failed");
528 return SSL_TLSEXT_ERR_NOACK;
531 ngx_memcpy(p, staple->staple.data, staple->staple.len);
533 SSL_set_tlsext_status_ocsp_resp(ssl_conn, p, staple->staple.len);
535 rc = SSL_TLSEXT_ERR_OK;
538 ngx_ssl_stapling_update(staple);
545 ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple)
547 ngx_ssl_ocsp_ctx_t *ctx;
549 if (staple->host.len == 0
550 || staple->loading || staple->refresh >= ngx_time())
557 ctx = ngx_ssl_ocsp_start();
562 ctx->cert = staple->cert;
563 ctx->issuer = staple->issuer;
564 ctx->name = staple->name;
566 ctx->addrs = staple->addrs;
567 ctx->host = staple->host;
568 ctx->uri = staple->uri;
569 ctx->port = staple->port;
570 ctx->timeout = staple->timeout;
572 ctx->resolver = staple->resolver;
573 ctx->resolver_timeout = staple->resolver_timeout;
575 ctx->handler = ngx_ssl_stapling_ocsp_handler;
578 ngx_ssl_ocsp_request(ctx);
585 ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
587 #if OPENSSL_VERSION_NUMBER >= 0x0090707fL
596 STACK_OF(X509) *chain;
599 OCSP_BASICRESP *basic;
600 ngx_ssl_stapling_t *staple;
601 ASN1_GENERALIZEDTIME *thisupdate, *nextupdate;
609 if (ctx->code != 200) {
613 /* check the response */
615 len = ctx->response->last - ctx->response->pos;
616 p = ctx->response->pos;
618 ocsp = d2i_OCSP_RESPONSE(NULL, &p, len);
620 ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
621 "d2i_OCSP_RESPONSE() failed");
625 n = OCSP_response_status(ocsp);
627 if (n != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
628 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
629 "OCSP response not successful (%d: %s)",
630 n, OCSP_response_status_str(n));
634 basic = OCSP_response_get1_basic(ocsp);
636 ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
637 "OCSP_response_get1_basic() failed");
641 store = SSL_CTX_get_cert_store(staple->ssl_ctx);
643 ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
644 "SSL_CTX_get_cert_store() failed");
648 #ifdef SSL_CTRL_SELECT_CURRENT_CERT
650 SSL_CTX_select_current_cert(staple->ssl_ctx, ctx->cert);
653 #ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
655 SSL_CTX_get_extra_chain_certs(staple->ssl_ctx, &chain);
657 chain = staple->ssl_ctx->extra_certs;
660 if (OCSP_basic_verify(basic, chain, store,
661 staple->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY)
664 ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
665 "OCSP_basic_verify() failed");
669 id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
671 ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
672 "OCSP_cert_to_id() failed");
676 if (OCSP_resp_find_status(basic, id, &n, NULL, NULL,
677 &thisupdate, &nextupdate)
680 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
681 "certificate status not found in the OCSP response");
685 if (n != V_OCSP_CERTSTATUS_GOOD) {
686 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
687 "certificate status \"%s\" in the OCSP response",
688 OCSP_cert_status_str(n));
692 if (OCSP_check_validity(thisupdate, nextupdate, 300, -1) != 1) {
693 ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
694 "OCSP_check_validity() failed");
699 valid = ngx_ssl_stapling_time(nextupdate);
700 if (valid == (time_t) NGX_ERROR) {
701 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
702 "invalid nextUpdate time in certificate status");
707 valid = NGX_MAX_TIME_T_VALUE;
710 OCSP_CERTID_free(id);
711 OCSP_BASICRESP_free(basic);
712 OCSP_RESPONSE_free(ocsp);
718 /* copy the response to memory not in ctx->pool */
721 response.data = ngx_alloc(response.len, ctx->log);
723 if (response.data == NULL) {
727 ngx_memcpy(response.data, ctx->response->pos, response.len);
729 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
730 "ssl ocsp response, %s, %uz",
731 OCSP_cert_status_str(n), response.len);
733 if (staple->staple.data) {
734 ngx_free(staple->staple.data);
737 staple->staple = response;
738 staple->valid = valid;
741 * refresh before the response expires,
742 * but not earlier than in 5 minutes, and at least in an hour
746 staple->refresh = ngx_max(ngx_min(valid - 300, now + 3600), now + 300);
748 ngx_ssl_ocsp_done(ctx);
754 staple->refresh = now + 300;
757 OCSP_CERTID_free(id);
761 OCSP_BASICRESP_free(basic);
765 OCSP_RESPONSE_free(ocsp);
768 ngx_ssl_ocsp_done(ctx);
773 ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time)
781 * OpenSSL doesn't provide a way to convert ASN1_GENERALIZEDTIME
782 * into time_t. To do this, we use ASN1_GENERALIZEDTIME_print(),
783 * which uses the "MMM DD HH:MM:SS YYYY [GMT]" format (e.g.,
784 * "Feb 3 00:55:52 2015 GMT"), and parse the result.
787 bio = BIO_new(BIO_s_mem());
792 /* fake weekday prepended to match C asctime() format */
794 BIO_write(bio, "Tue ", sizeof("Tue ") - 1);
795 ASN1_GENERALIZEDTIME_print(bio, asn1time);
796 len = BIO_get_mem_data(bio, &value);
798 time = ngx_parse_http_time((u_char *) value, len);
807 ngx_ssl_stapling_cleanup(void *data)
809 ngx_ssl_stapling_t *staple = data;
811 if (staple->issuer) {
812 X509_free(staple->issuer);
815 if (staple->staple.data) {
816 ngx_free(staple->staple.data);
821 static ngx_ssl_ocsp_ctx_t *
822 ngx_ssl_ocsp_start(void)
826 ngx_ssl_ocsp_ctx_t *ctx;
828 pool = ngx_create_pool(2048, ngx_cycle->log);
833 ctx = ngx_pcalloc(pool, sizeof(ngx_ssl_ocsp_ctx_t));
835 ngx_destroy_pool(pool);
839 log = ngx_palloc(pool, sizeof(ngx_log_t));
841 ngx_destroy_pool(pool);
847 *log = *ctx->pool->log;
849 ctx->pool->log = log;
852 log->handler = ngx_ssl_ocsp_log_error;
854 log->action = "requesting certificate status";
861 ngx_ssl_ocsp_done(ngx_ssl_ocsp_ctx_t *ctx)
863 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
866 if (ctx->peer.connection) {
867 ngx_close_connection(ctx->peer.connection);
870 ngx_destroy_pool(ctx->pool);
875 ngx_ssl_ocsp_error(ngx_ssl_ocsp_ctx_t *ctx)
877 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
886 ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx)
888 ngx_resolver_ctx_t *resolve, temp;
890 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
893 if (ngx_ssl_ocsp_create_request(ctx) != NGX_OK) {
894 ngx_ssl_ocsp_error(ctx);
899 /* resolve OCSP responder hostname */
901 temp.name = ctx->host;
903 resolve = ngx_resolve_start(ctx->resolver, &temp);
904 if (resolve == NULL) {
905 ngx_ssl_ocsp_error(ctx);
909 if (resolve == NGX_NO_RESOLVER) {
910 ngx_log_error(NGX_LOG_WARN, ctx->log, 0,
911 "no resolver defined to resolve %V", &ctx->host);
915 resolve->name = ctx->host;
916 resolve->handler = ngx_ssl_ocsp_resolve_handler;
918 resolve->timeout = ctx->resolver_timeout;
920 if (ngx_resolve_name(resolve) != NGX_OK) {
921 ngx_ssl_ocsp_error(ctx);
930 ngx_ssl_ocsp_connect(ctx);
935 ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve)
937 ngx_ssl_ocsp_ctx_t *ctx = resolve->data;
943 struct sockaddr *sockaddr;
945 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
946 "ssl ocsp resolve handler");
948 if (resolve->state) {
949 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
950 "%V could not be resolved (%i: %s)",
951 &resolve->name, resolve->state,
952 ngx_resolver_strerror(resolve->state));
958 u_char text[NGX_SOCKADDR_STRLEN];
963 for (i = 0; i < resolve->naddrs; i++) {
964 addr.len = ngx_sock_ntop(resolve->addrs[i].sockaddr,
965 resolve->addrs[i].socklen,
966 text, NGX_SOCKADDR_STRLEN, 0);
968 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
969 "name was resolved to %V", &addr);
975 ctx->naddrs = resolve->naddrs;
976 ctx->addrs = ngx_pcalloc(ctx->pool, ctx->naddrs * sizeof(ngx_addr_t));
978 if (ctx->addrs == NULL) {
982 for (i = 0; i < resolve->naddrs; i++) {
984 socklen = resolve->addrs[i].socklen;
986 sockaddr = ngx_palloc(ctx->pool, socklen);
987 if (sockaddr == NULL) {
991 ngx_memcpy(sockaddr, resolve->addrs[i].sockaddr, socklen);
992 ngx_inet_set_port(sockaddr, ctx->port);
994 ctx->addrs[i].sockaddr = sockaddr;
995 ctx->addrs[i].socklen = socklen;
997 p = ngx_pnalloc(ctx->pool, NGX_SOCKADDR_STRLEN);
1002 len = ngx_sock_ntop(sockaddr, socklen, p, NGX_SOCKADDR_STRLEN, 1);
1004 ctx->addrs[i].name.len = len;
1005 ctx->addrs[i].name.data = p;
1008 ngx_resolve_name_done(resolve);
1010 ngx_ssl_ocsp_connect(ctx);
1015 ngx_resolve_name_done(resolve);
1016 ngx_ssl_ocsp_error(ctx);
1021 ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx)
1025 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1026 "ssl ocsp connect");
1028 /* TODO: use all ip addresses */
1030 ctx->peer.sockaddr = ctx->addrs[0].sockaddr;
1031 ctx->peer.socklen = ctx->addrs[0].socklen;
1032 ctx->peer.name = &ctx->addrs[0].name;
1033 ctx->peer.get = ngx_event_get_peer;
1034 ctx->peer.log = ctx->log;
1035 ctx->peer.log_error = NGX_ERROR_ERR;
1037 rc = ngx_event_connect_peer(&ctx->peer);
1039 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1040 "ssl ocsp connect peer done");
1042 if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
1043 ngx_ssl_ocsp_error(ctx);
1047 ctx->peer.connection->data = ctx;
1048 ctx->peer.connection->pool = ctx->pool;
1050 ctx->peer.connection->read->handler = ngx_ssl_ocsp_read_handler;
1051 ctx->peer.connection->write->handler = ngx_ssl_ocsp_write_handler;
1053 ctx->process = ngx_ssl_ocsp_process_status_line;
1055 ngx_add_timer(ctx->peer.connection->read, ctx->timeout);
1056 ngx_add_timer(ctx->peer.connection->write, ctx->timeout);
1059 ngx_ssl_ocsp_write_handler(ctx->peer.connection->write);
1066 ngx_ssl_ocsp_write_handler(ngx_event_t *wev)
1069 ngx_connection_t *c;
1070 ngx_ssl_ocsp_ctx_t *ctx;
1075 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, wev->log, 0,
1076 "ssl ocsp write handler");
1078 if (wev->timedout) {
1079 ngx_log_error(NGX_LOG_ERR, wev->log, NGX_ETIMEDOUT,
1080 "OCSP responder timed out");
1081 ngx_ssl_ocsp_error(ctx);
1085 size = ctx->request->last - ctx->request->pos;
1087 n = ngx_send(c, ctx->request->pos, size);
1089 if (n == NGX_ERROR) {
1090 ngx_ssl_ocsp_error(ctx);
1095 ctx->request->pos += n;
1098 wev->handler = ngx_ssl_ocsp_dummy_handler;
1100 if (wev->timer_set) {
1104 if (ngx_handle_write_event(wev, 0) != NGX_OK) {
1105 ngx_ssl_ocsp_error(ctx);
1112 if (!wev->timer_set) {
1113 ngx_add_timer(wev, ctx->timeout);
1119 ngx_ssl_ocsp_read_handler(ngx_event_t *rev)
1123 ngx_connection_t *c;
1124 ngx_ssl_ocsp_ctx_t *ctx;
1129 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, rev->log, 0,
1130 "ssl ocsp read handler");
1132 if (rev->timedout) {
1133 ngx_log_error(NGX_LOG_ERR, rev->log, NGX_ETIMEDOUT,
1134 "OCSP responder timed out");
1135 ngx_ssl_ocsp_error(ctx);
1139 if (ctx->response == NULL) {
1140 ctx->response = ngx_create_temp_buf(ctx->pool, 16384);
1141 if (ctx->response == NULL) {
1142 ngx_ssl_ocsp_error(ctx);
1149 size = ctx->response->end - ctx->response->last;
1151 n = ngx_recv(c, ctx->response->last, size);
1154 ctx->response->last += n;
1156 rc = ctx->process(ctx);
1158 if (rc == NGX_ERROR) {
1159 ngx_ssl_ocsp_error(ctx);
1166 if (n == NGX_AGAIN) {
1168 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
1169 ngx_ssl_ocsp_error(ctx);
1180 rc = ctx->process(ctx);
1182 if (rc == NGX_DONE) {
1183 /* ctx->handler() was called */
1187 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1188 "OCSP responder prematurely closed connection");
1190 ngx_ssl_ocsp_error(ctx);
1195 ngx_ssl_ocsp_dummy_handler(ngx_event_t *ev)
1197 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0,
1198 "ssl ocsp dummy handler");
1203 ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx)
1208 ngx_str_t binary, base64;
1213 ocsp = OCSP_REQUEST_new();
1215 ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1216 "OCSP_REQUEST_new() failed");
1220 id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
1222 ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1223 "OCSP_cert_to_id() failed");
1227 if (OCSP_request_add0_id(ocsp, id) == NULL) {
1228 ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1229 "OCSP_request_add0_id() failed");
1230 OCSP_CERTID_free(id);
1234 len = i2d_OCSP_REQUEST(ocsp, NULL);
1236 ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1237 "i2d_OCSP_REQUEST() failed");
1242 binary.data = ngx_palloc(ctx->pool, len);
1243 if (binary.data == NULL) {
1248 len = i2d_OCSP_REQUEST(ocsp, &p);
1250 ngx_ssl_error(NGX_LOG_EMERG, ctx->log, 0,
1251 "i2d_OCSP_REQUEST() failed");
1255 base64.len = ngx_base64_encoded_length(binary.len);
1256 base64.data = ngx_palloc(ctx->pool, base64.len);
1257 if (base64.data == NULL) {
1261 ngx_encode_base64(&base64, &binary);
1263 escape = ngx_escape_uri(NULL, base64.data, base64.len,
1264 NGX_ESCAPE_URI_COMPONENT);
1266 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1267 "ssl ocsp request length %z, escape %d",
1268 base64.len, (int) escape);
1270 len = sizeof("GET ") - 1 + ctx->uri.len + sizeof("/") - 1
1271 + base64.len + 2 * escape + sizeof(" HTTP/1.0" CRLF) - 1
1272 + sizeof("Host: ") - 1 + ctx->host.len + sizeof(CRLF) - 1
1275 b = ngx_create_temp_buf(ctx->pool, len);
1282 p = ngx_cpymem(p, "GET ", sizeof("GET ") - 1);
1283 p = ngx_cpymem(p, ctx->uri.data, ctx->uri.len);
1285 if (ctx->uri.data[ctx->uri.len - 1] != '/') {
1290 p = ngx_cpymem(p, base64.data, base64.len);
1293 p = (u_char *) ngx_escape_uri(p, base64.data, base64.len,
1294 NGX_ESCAPE_URI_COMPONENT);
1297 p = ngx_cpymem(p, " HTTP/1.0" CRLF, sizeof(" HTTP/1.0" CRLF) - 1);
1298 p = ngx_cpymem(p, "Host: ", sizeof("Host: ") - 1);
1299 p = ngx_cpymem(p, ctx->host.data, ctx->host.len);
1300 *p++ = CR; *p++ = LF;
1302 /* add "\r\n" at the header end */
1303 *p++ = CR; *p++ = LF;
1308 OCSP_REQUEST_free(ocsp);
1314 OCSP_REQUEST_free(ocsp);
1321 ngx_ssl_ocsp_process_status_line(ngx_ssl_ocsp_ctx_t *ctx)
1325 rc = ngx_ssl_ocsp_parse_status_line(ctx);
1328 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1329 "ssl ocsp status %ui \"%*s\"",
1331 ctx->header_end - ctx->header_start,
1334 ctx->process = ngx_ssl_ocsp_process_headers;
1335 return ctx->process(ctx);
1338 if (rc == NGX_AGAIN) {
1342 /* rc == NGX_ERROR */
1344 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1345 "OCSP responder sent invalid response");
1352 ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t *ctx)
1363 sw_first_major_digit,
1365 sw_first_minor_digit,
1368 sw_space_after_status,
1373 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1374 "ssl ocsp process status line");
1379 for (p = b->pos; p < b->last; p++) {
1428 state = sw_first_major_digit;
1435 /* the first digit of major HTTP version */
1436 case sw_first_major_digit:
1437 if (ch < '1' || ch > '9') {
1441 state = sw_major_digit;
1444 /* the major HTTP version or dot */
1445 case sw_major_digit:
1447 state = sw_first_minor_digit;
1451 if (ch < '0' || ch > '9') {
1457 /* the first digit of minor HTTP version */
1458 case sw_first_minor_digit:
1459 if (ch < '0' || ch > '9') {
1463 state = sw_minor_digit;
1466 /* the minor HTTP version or the end of the request line */
1467 case sw_minor_digit:
1473 if (ch < '0' || ch > '9') {
1479 /* HTTP status code */
1485 if (ch < '0' || ch > '9') {
1489 ctx->code = ctx->code * 10 + ch - '0';
1491 if (++ctx->count == 3) {
1492 state = sw_space_after_status;
1493 ctx->header_start = p - 2;
1498 /* space or end of line */
1499 case sw_space_after_status:
1502 state = sw_status_text;
1504 case '.': /* IIS may send 403.1, 403.2, etc */
1505 state = sw_status_text;
1508 state = sw_almost_done;
1511 ctx->header_end = p;
1518 /* any text until end of line */
1519 case sw_status_text:
1522 state = sw_almost_done;
1525 ctx->header_end = p;
1530 /* end of status line */
1531 case sw_almost_done:
1534 ctx->header_end = p - 1;
1550 ctx->state = sw_start;
1557 ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx)
1562 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1563 "ssl ocsp process headers");
1566 rc = ngx_ssl_ocsp_parse_header_line(ctx);
1570 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1571 "ssl ocsp header \"%*s: %*s\"",
1572 ctx->header_name_end - ctx->header_name_start,
1573 ctx->header_name_start,
1574 ctx->header_end - ctx->header_start,
1577 len = ctx->header_name_end - ctx->header_name_start;
1579 if (len == sizeof("Content-Type") - 1
1580 && ngx_strncasecmp(ctx->header_name_start,
1581 (u_char *) "Content-Type",
1582 sizeof("Content-Type") - 1)
1585 len = ctx->header_end - ctx->header_start;
1587 if (len != sizeof("application/ocsp-response") - 1
1588 || ngx_strncasecmp(ctx->header_start,
1589 (u_char *) "application/ocsp-response",
1590 sizeof("application/ocsp-response") - 1)
1593 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1594 "OCSP responder sent invalid "
1595 "\"Content-Type\" header: \"%*s\"",
1596 ctx->header_end - ctx->header_start,
1604 /* TODO: honor Content-Length */
1609 if (rc == NGX_DONE) {
1613 if (rc == NGX_AGAIN) {
1617 /* rc == NGX_ERROR */
1619 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1620 "OCSP responder sent invalid response");
1625 ctx->process = ngx_ssl_ocsp_process_body;
1626 return ctx->process(ctx);
1631 ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx)
1637 sw_space_before_value,
1639 sw_space_after_value,
1641 sw_header_almost_done
1646 for (p = ctx->response->pos; p < ctx->response->last; p++) {
1650 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1651 "s:%d in:'%02Xd:%c'", state, ch, ch);
1661 ctx->header_end = p;
1662 state = sw_header_almost_done;
1665 ctx->header_end = p;
1669 ctx->header_name_start = p;
1671 c = (u_char) (ch | 0x20);
1672 if (c >= 'a' && c <= 'z') {
1676 if (ch >= '0' && ch <= '9') {
1686 c = (u_char) (ch | 0x20);
1687 if (c >= 'a' && c <= 'z') {
1692 ctx->header_name_end = p;
1693 state = sw_space_before_value;
1701 if (ch >= '0' && ch <= '9') {
1706 ctx->header_name_end = p;
1707 ctx->header_start = p;
1708 ctx->header_end = p;
1709 state = sw_almost_done;
1714 ctx->header_name_end = p;
1715 ctx->header_start = p;
1716 ctx->header_end = p;
1722 /* space* before header value */
1723 case sw_space_before_value:
1728 ctx->header_start = p;
1729 ctx->header_end = p;
1730 state = sw_almost_done;
1733 ctx->header_start = p;
1734 ctx->header_end = p;
1737 ctx->header_start = p;
1747 ctx->header_end = p;
1748 state = sw_space_after_value;
1751 ctx->header_end = p;
1752 state = sw_almost_done;
1755 ctx->header_end = p;
1760 /* space* before end of header line */
1761 case sw_space_after_value:
1766 state = sw_almost_done;
1776 /* end of header line */
1777 case sw_almost_done:
1786 case sw_header_almost_done:
1796 ctx->response->pos = p;
1803 ctx->response->pos = p + 1;
1804 ctx->state = sw_start;
1810 ctx->response->pos = p + 1;
1811 ctx->state = sw_start;
1818 ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx)
1820 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1821 "ssl ocsp process body");
1833 ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len)
1836 ngx_ssl_ocsp_ctx_t *ctx;
1841 p = ngx_snprintf(buf, len, " while %s", log->action);
1849 p = ngx_snprintf(buf, len, ", responder: %V", &ctx->host);
1854 if (ctx && ctx->peer.name) {
1855 p = ngx_snprintf(buf, len, ", peer: %V", ctx->peer.name);
1860 if (ctx && ctx->name) {
1861 p = ngx_snprintf(buf, len, ", certificate: \"%s\"", ctx->name);
1874 ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file,
1875 ngx_str_t *responder, ngx_uint_t verify)
1877 ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
1878 "\"ssl_stapling\" ignored, not supported");
1885 ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
1886 ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)