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 #ifdef SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB
21 ngx_resolver_t
*resolver
;
22 ngx_msec_t resolver_timeout
;
41 typedef struct ngx_ssl_ocsp_ctx_s ngx_ssl_ocsp_ctx_t
;
43 struct ngx_ssl_ocsp_ctx_s
{
54 ngx_resolver_t
*resolver
;
55 ngx_msec_t resolver_timeout
;
59 void (*handler
)(ngx_ssl_ocsp_ctx_t
*r
);
64 ngx_peer_connection_t peer
;
66 ngx_int_t (*process
)(ngx_ssl_ocsp_ctx_t
*r
);
75 u_char
*header_name_start
;
76 u_char
*header_name_end
;
85 static ngx_int_t
ngx_ssl_stapling_file(ngx_conf_t
*cf
, ngx_ssl_t
*ssl
,
87 static ngx_int_t
ngx_ssl_stapling_issuer(ngx_conf_t
*cf
, ngx_ssl_t
*ssl
);
88 static ngx_int_t
ngx_ssl_stapling_responder(ngx_conf_t
*cf
, ngx_ssl_t
*ssl
,
89 ngx_str_t
*responder
);
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
);
101 static void ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t
*resolve
);
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
);
118 ngx_ssl_stapling(ngx_conf_t
*cf
, ngx_ssl_t
*ssl
, ngx_str_t
*file
,
119 ngx_str_t
*responder
, ngx_uint_t verify
)
122 ngx_pool_cleanup_t
*cln
;
123 ngx_ssl_stapling_t
*staple
;
125 staple
= ngx_pcalloc(cf
->pool
, sizeof(ngx_ssl_stapling_t
));
126 if (staple
== NULL
) {
130 cln
= ngx_pool_cleanup_add(cf
->pool
, 0);
135 cln
->handler
= ngx_ssl_stapling_cleanup
;
138 if (SSL_CTX_set_ex_data(ssl
->ctx
, ngx_ssl_stapling_index
, staple
)
141 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
142 "SSL_CTX_set_ex_data() failed");
146 staple
->ssl_ctx
= ssl
->ctx
;
147 staple
->timeout
= 60000;
148 staple
->verify
= verify
;
151 /* use OCSP response from the file */
153 if (ngx_ssl_stapling_file(cf
, ssl
, file
) != NGX_OK
) {
160 rc
= ngx_ssl_stapling_issuer(cf
, ssl
);
162 if (rc
== NGX_DECLINED
) {
170 rc
= ngx_ssl_stapling_responder(cf
, ssl
, responder
);
172 if (rc
== NGX_DECLINED
) {
182 SSL_CTX_set_tlsext_status_cb(ssl
->ctx
, ngx_ssl_certificate_status_callback
);
183 SSL_CTX_set_tlsext_status_arg(ssl
->ctx
, staple
);
190 ngx_ssl_stapling_file(ngx_conf_t
*cf
, ngx_ssl_t
*ssl
, ngx_str_t
*file
)
195 OCSP_RESPONSE
*response
;
196 ngx_ssl_stapling_t
*staple
;
198 staple
= SSL_CTX_get_ex_data(ssl
->ctx
, ngx_ssl_stapling_index
);
200 if (ngx_conf_full_name(cf
->cycle
, file
, 1) != NGX_OK
) {
204 bio
= BIO_new_file((char *) file
->data
, "r");
206 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
207 "BIO_new_file(\"%s\") failed", file
->data
);
211 response
= d2i_OCSP_RESPONSE_bio(bio
, NULL
);
212 if (response
== NULL
) {
213 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
214 "d2i_OCSP_RESPONSE_bio(\"%s\") failed", file
->data
);
219 len
= i2d_OCSP_RESPONSE(response
, NULL
);
221 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
222 "i2d_OCSP_RESPONSE(\"%s\") failed", file
->data
);
226 buf
= ngx_alloc(len
, ssl
->log
);
232 len
= i2d_OCSP_RESPONSE(response
, &p
);
234 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
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
);
258 ngx_ssl_stapling_issuer(ngx_conf_t
*cf
, ngx_ssl_t
*ssl
)
263 X509_STORE_CTX
*store_ctx
;
264 STACK_OF(X509
) *chain
;
265 ngx_ssl_stapling_t
*staple
;
267 staple
= SSL_CTX_get_ex_data(ssl
->ctx
, ngx_ssl_stapling_index
);
268 cert
= SSL_CTX_get_ex_data(ssl
->ctx
, ngx_ssl_certificate_index
);
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
);
278 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, ssl
->log
, 0,
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
);
286 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, ssl
->log
, 0,
287 "SSL get issuer: found %p in extra certs", issuer
);
290 staple
->issuer
= issuer
;
296 store
= SSL_CTX_get_cert_store(ssl
->ctx
);
298 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
299 "SSL_CTX_get_cert_store() failed");
303 store_ctx
= X509_STORE_CTX_new();
304 if (store_ctx
== NULL
) {
305 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
306 "X509_STORE_CTX_new() failed");
310 if (X509_STORE_CTX_init(store_ctx
, store
, NULL
, NULL
) == 0) {
311 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
312 "X509_STORE_CTX_init() failed");
316 rc
= X509_STORE_CTX_get1_issuer(&issuer
, store_ctx
, cert
);
319 ngx_ssl_error(NGX_LOG_EMERG
, ssl
->log
, 0,
320 "X509_STORE_CTX_get1_issuer() failed");
321 X509_STORE_CTX_free(store_ctx
);
326 ngx_log_error(NGX_LOG_WARN
, ssl
->log
, 0,
327 "\"ssl_stapling\" ignored, issuer certificate not found");
328 X509_STORE_CTX_free(store_ctx
);
332 X509_STORE_CTX_free(store_ctx
);
334 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, ssl
->log
, 0,
335 "SSL get issuer: found %p in cert store", issuer
);
338 staple
->issuer
= issuer
;
345 ngx_ssl_stapling_responder(ngx_conf_t
*cf
, ngx_ssl_t
*ssl
, ngx_str_t
*responder
)
349 ngx_ssl_stapling_t
*staple
;
350 STACK_OF(OPENSSL_STRING
) *aia
;
352 staple
= SSL_CTX_get_ex_data(ssl
->ctx
, ngx_ssl_stapling_index
);
354 if (responder
->len
== 0) {
356 /* extract OCSP responder URL from certificate */
358 aia
= X509_get1_ocsp(staple
->cert
);
360 ngx_log_error(NGX_LOG_WARN
, ssl
->log
, 0,
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);
372 ngx_log_error(NGX_LOG_WARN
, ssl
->log
, 0,
373 "\"ssl_stapling\" ignored, "
374 "no OCSP responder URL in the certificate");
375 X509_email_free(aia
);
379 responder
->len
= ngx_strlen(s
);
380 responder
->data
= ngx_palloc(cf
->pool
, responder
->len
);
381 if (responder
->data
== NULL
) {
382 X509_email_free(aia
);
386 ngx_memcpy(responder
->data
, s
, responder
->len
);
387 X509_email_free(aia
);
390 ngx_memzero(&u
, sizeof(ngx_url_t
));
397 && ngx_strncasecmp(u
.url
.data
, (u_char
*) "http://", 7) == 0)
403 ngx_log_error(NGX_LOG_WARN
, ssl
->log
, 0,
404 "\"ssl_stapling\" ignored, "
405 "invalid URL prefix in OCSP responder \"%V\"", &u
.url
);
409 if (ngx_parse_url(cf
->pool
, &u
) != NGX_OK
) {
411 ngx_log_error(NGX_LOG_WARN
, ssl
->log
, 0,
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) {
426 ngx_str_set(&staple
->uri
, "/");
434 ngx_ssl_stapling_resolver(ngx_conf_t
*cf
, ngx_ssl_t
*ssl
,
435 ngx_resolver_t
*resolver
, ngx_msec_t resolver_timeout
)
437 ngx_ssl_stapling_t
*staple
;
439 staple
= SSL_CTX_get_ex_data(ssl
->ctx
, ngx_ssl_stapling_index
);
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
;
456 c
= ngx_ssl_get_connection(ssl_conn
);
458 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, c
->log
, 0,
459 "SSL certificate status callback");
462 rc
= SSL_TLSEXT_ERR_NOACK
;
464 if (staple
->staple
.len
) {
465 /* we have to copy ocsp response as OpenSSL will free it by itself */
467 p
= OPENSSL_malloc(staple
->staple
.len
);
469 ngx_ssl_error(NGX_LOG_ALERT
, c
->log
, 0, "OPENSSL_malloc() failed");
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) {
552 /* check the response */
554 len
= ctx
->response
->last
- ctx
->response
->pos
;
555 p
= ctx
->response
->pos
;
557 ocsp
= d2i_OCSP_RESPONSE(NULL
, &p
, len
);
559 ngx_ssl_error(NGX_LOG_ERR
, ctx
->log
, 0,
560 "d2i_OCSP_RESPONSE() failed");
564 n
= OCSP_response_status(ocsp
);
566 if (n
!= OCSP_RESPONSE_STATUS_SUCCESSFUL
) {
567 ngx_log_error(NGX_LOG_ERR
, ctx
->log
, 0,
568 "OCSP response not successful (%d: %s)",
569 n
, OCSP_response_status_str(n
));
573 basic
= OCSP_response_get1_basic(ocsp
);
575 ngx_ssl_error(NGX_LOG_ERR
, ctx
->log
, 0,
576 "OCSP_response_get1_basic() failed");
580 store
= SSL_CTX_get_cert_store(staple
->ssl_ctx
);
582 ngx_ssl_error(NGX_LOG_CRIT
, ctx
->log
, 0,
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
)
597 ngx_ssl_error(NGX_LOG_ERR
, ctx
->log
, 0,
598 "OCSP_basic_verify() failed");
602 id
= OCSP_cert_to_id(NULL
, ctx
->cert
, ctx
->issuer
);
604 ngx_ssl_error(NGX_LOG_CRIT
, ctx
->log
, 0,
605 "OCSP_cert_to_id() failed");
609 if (OCSP_resp_find_status(basic
, id
, &n
, NULL
, NULL
,
610 &thisupdate
, &nextupdate
)
613 ngx_log_error(NGX_LOG_ERR
, ctx
->log
, 0,
614 "certificate status not found in the OCSP response",
615 n
, OCSP_response_status_str(n
));
619 if (n
!= V_OCSP_CERTSTATUS_GOOD
) {
620 ngx_log_error(NGX_LOG_ERR
, ctx
->log
, 0,
621 "certificate status \"%s\" in the OCSP response",
622 n
, OCSP_cert_status_str(n
));
626 if (OCSP_check_validity(thisupdate
, nextupdate
, 300, -1) != 1) {
627 ngx_ssl_error(NGX_LOG_ERR
, ctx
->log
, 0,
628 "OCSP_check_validity() failed");
632 OCSP_CERTID_free(id
);
633 OCSP_BASICRESP_free(basic
);
634 OCSP_RESPONSE_free(ocsp
);
636 /* copy the response to memory not in ctx->pool */
639 response
.data
= ngx_alloc(response
.len
, ctx
->log
);
641 if (response
.data
== NULL
) {
645 ngx_memcpy(response
.data
, ctx
->response
->pos
, response
.len
);
647 ngx_log_debug2(NGX_LOG_DEBUG_EVENT
, ctx
->log
, 0,
648 "ssl ocsp response, %s, %uz",
649 OCSP_cert_status_str(n
), response
.len
);
651 if (staple
->staple
.data
) {
652 ngx_free(staple
->staple
.data
);
655 staple
->staple
= response
;
660 staple
->valid
= ngx_time() + 3600; /* ssl_stapling_valid */
662 ngx_ssl_ocsp_done(ctx
);
668 staple
->valid
= ngx_time() + 300; /* ssl_stapling_err_valid */
671 OCSP_CERTID_free(id
);
675 OCSP_BASICRESP_free(basic
);
679 OCSP_RESPONSE_free(ocsp
);
682 ngx_ssl_ocsp_done(ctx
);
687 ngx_ssl_stapling_cleanup(void *data
)
689 ngx_ssl_stapling_t
*staple
= data
;
691 if (staple
->issuer
) {
692 X509_free(staple
->issuer
);
695 if (staple
->staple
.data
) {
696 ngx_free(staple
->staple
.data
);
701 static ngx_ssl_ocsp_ctx_t
*
702 ngx_ssl_ocsp_start(void)
706 ngx_ssl_ocsp_ctx_t
*ctx
;
708 pool
= ngx_create_pool(2048, ngx_cycle
->log
);
713 ctx
= ngx_pcalloc(pool
, sizeof(ngx_ssl_ocsp_ctx_t
));
715 ngx_destroy_pool(pool
);
719 log
= ngx_palloc(pool
, sizeof(ngx_log_t
));
721 ngx_destroy_pool(pool
);
727 *log
= *ctx
->pool
->log
;
729 ctx
->pool
->log
= log
;
732 log
->handler
= ngx_ssl_ocsp_log_error
;
734 log
->action
= "requesting certificate status";
741 ngx_ssl_ocsp_done(ngx_ssl_ocsp_ctx_t
*ctx
)
743 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, ctx
->log
, 0,
746 if (ctx
->peer
.connection
) {
747 ngx_close_connection(ctx
->peer
.connection
);
750 ngx_destroy_pool(ctx
->pool
);
755 ngx_ssl_ocsp_error(ngx_ssl_ocsp_ctx_t
*ctx
)
757 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, ctx
->log
, 0,
766 ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t
*ctx
)
768 ngx_resolver_ctx_t
*resolve
, temp
;
770 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, ctx
->log
, 0,
773 if (ngx_ssl_ocsp_create_request(ctx
) != NGX_OK
) {
774 ngx_ssl_ocsp_error(ctx
);
779 /* resolve OCSP responder hostname */
781 temp
.name
= ctx
->host
;
783 resolve
= ngx_resolve_start(ctx
->resolver
, &temp
);
784 if (resolve
== NULL
) {
785 ngx_ssl_ocsp_error(ctx
);
789 if (resolve
== NGX_NO_RESOLVER
) {
790 ngx_log_error(NGX_LOG_WARN
, ctx
->log
, 0,
791 "no resolver defined to resolve %V", &ctx
->host
);
795 resolve
->name
= ctx
->host
;
796 resolve
->type
= NGX_RESOLVE_A
;
797 resolve
->handler
= ngx_ssl_ocsp_resolve_handler
;
799 resolve
->timeout
= ctx
->resolver_timeout
;
801 if (ngx_resolve_name(resolve
) != NGX_OK
) {
802 ngx_ssl_ocsp_error(ctx
);
811 ngx_ssl_ocsp_connect(ctx
);
816 ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t
*resolve
)
818 ngx_ssl_ocsp_ctx_t
*ctx
= resolve
->data
;
824 struct sockaddr_in
*sin
;
826 ngx_log_debug0(NGX_LOG_ALERT
, ctx
->log
, 0,
827 "ssl ocsp resolve handler");
829 if (resolve
->state
) {
830 ngx_log_error(NGX_LOG_ERR
, ctx
->log
, 0,
831 "%V could not be resolved (%i: %s)",
832 &resolve
->name
, resolve
->state
,
833 ngx_resolver_strerror(resolve
->state
));
841 for (i
= 0; i
< resolve
->naddrs
; i
++) {
842 addr
= ntohl(resolve
->addrs
[i
]);
844 ngx_log_debug4(NGX_LOG_DEBUG_EVENT
, ctx
->log
, 0,
845 "name was resolved to %ud.%ud.%ud.%ud",
846 (addr
>> 24) & 0xff, (addr
>> 16) & 0xff,
847 (addr
>> 8) & 0xff, addr
& 0xff);
852 ctx
->naddrs
= resolve
->naddrs
;
853 ctx
->addrs
= ngx_pcalloc(ctx
->pool
, ctx
->naddrs
* sizeof(ngx_addr_t
));
855 if (ctx
->addrs
== NULL
) {
859 port
= htons(ctx
->port
);
861 for (i
= 0; i
< resolve
->naddrs
; i
++) {
863 sin
= ngx_pcalloc(ctx
->pool
, sizeof(struct sockaddr_in
));
868 sin
->sin_family
= AF_INET
;
869 sin
->sin_port
= port
;
870 sin
->sin_addr
.s_addr
= resolve
->addrs
[i
];
872 ctx
->addrs
[i
].sockaddr
= (struct sockaddr
*) sin
;
873 ctx
->addrs
[i
].socklen
= sizeof(struct sockaddr_in
);
875 len
= NGX_INET_ADDRSTRLEN
+ sizeof(":65535") - 1;
877 p
= ngx_pnalloc(ctx
->pool
, len
);
882 len
= ngx_sock_ntop((struct sockaddr
*) sin
, p
, len
, 1);
884 ctx
->addrs
[i
].name
.len
= len
;
885 ctx
->addrs
[i
].name
.data
= p
;
888 ngx_resolve_name_done(resolve
);
890 ngx_ssl_ocsp_connect(ctx
);
895 ngx_resolve_name_done(resolve
);
896 ngx_ssl_ocsp_error(ctx
);
901 ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t
*ctx
)
905 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, ctx
->log
, 0,
908 /* TODO: use all ip addresses */
910 ctx
->peer
.sockaddr
= ctx
->addrs
[0].sockaddr
;
911 ctx
->peer
.socklen
= ctx
->addrs
[0].socklen
;
912 ctx
->peer
.name
= &ctx
->addrs
[0].name
;
913 ctx
->peer
.get
= ngx_event_get_peer
;
914 ctx
->peer
.log
= ctx
->log
;
915 ctx
->peer
.log_error
= NGX_ERROR_ERR
;
917 rc
= ngx_event_connect_peer(&ctx
->peer
);
919 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, ctx
->log
, 0,
920 "ssl ocsp connect peer done");
922 if (rc
== NGX_ERROR
|| rc
== NGX_BUSY
|| rc
== NGX_DECLINED
) {
923 ngx_ssl_ocsp_error(ctx
);
927 ctx
->peer
.connection
->data
= ctx
;
928 ctx
->peer
.connection
->pool
= ctx
->pool
;
930 ctx
->peer
.connection
->read
->handler
= ngx_ssl_ocsp_read_handler
;
931 ctx
->peer
.connection
->write
->handler
= ngx_ssl_ocsp_write_handler
;
933 ctx
->process
= ngx_ssl_ocsp_process_status_line
;
935 ngx_add_timer(ctx
->peer
.connection
->read
, ctx
->timeout
);
936 ngx_add_timer(ctx
->peer
.connection
->write
, ctx
->timeout
);
939 ngx_ssl_ocsp_write_handler(ctx
->peer
.connection
->write
);
946 ngx_ssl_ocsp_write_handler(ngx_event_t
*wev
)
950 ngx_ssl_ocsp_ctx_t
*ctx
;
955 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, wev
->log
, 0,
956 "ssl ocsp write handler");
959 ngx_log_error(NGX_LOG_ERR
, wev
->log
, NGX_ETIMEDOUT
,
960 "OCSP responder timed out");
961 ngx_ssl_ocsp_error(ctx
);
965 size
= ctx
->request
->last
- ctx
->request
->pos
;
967 n
= ngx_send(c
, ctx
->request
->pos
, size
);
969 if (n
== NGX_ERROR
) {
970 ngx_ssl_ocsp_error(ctx
);
975 ctx
->request
->pos
+= n
;
978 wev
->handler
= ngx_ssl_ocsp_dummy_handler
;
980 if (wev
->timer_set
) {
984 if (ngx_handle_write_event(wev
, 0) != NGX_OK
) {
985 ngx_ssl_ocsp_error(ctx
);
992 if (!wev
->timer_set
) {
993 ngx_add_timer(wev
, ctx
->timeout
);
999 ngx_ssl_ocsp_read_handler(ngx_event_t
*rev
)
1003 ngx_ssl_ocsp_ctx_t
*ctx
;
1004 ngx_connection_t
*c
;
1009 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, rev
->log
, 0,
1010 "ssl ocsp read handler");
1012 if (rev
->timedout
) {
1013 ngx_log_error(NGX_LOG_ERR
, rev
->log
, NGX_ETIMEDOUT
,
1014 "OCSP responder timed out");
1015 ngx_ssl_ocsp_error(ctx
);
1019 if (ctx
->response
== NULL
) {
1020 ctx
->response
= ngx_create_temp_buf(ctx
->pool
, 16384);
1021 if (ctx
->response
== NULL
) {
1022 ngx_ssl_ocsp_error(ctx
);
1029 size
= ctx
->response
->end
- ctx
->response
->last
;
1031 n
= ngx_recv(c
, ctx
->response
->last
, size
);
1034 ctx
->response
->last
+= n
;
1036 rc
= ctx
->process(ctx
);
1038 if (rc
== NGX_ERROR
) {
1039 ngx_ssl_ocsp_error(ctx
);
1046 if (n
== NGX_AGAIN
) {
1048 if (ngx_handle_read_event(rev
, 0) != NGX_OK
) {
1049 ngx_ssl_ocsp_error(ctx
);
1060 rc
= ctx
->process(ctx
);
1062 if (rc
== NGX_DONE
) {
1063 /* ctx->handler() was called */
1067 ngx_log_error(NGX_LOG_ERR
, ctx
->log
, 0,
1068 "OCSP responder prematurely closed connection");
1070 ngx_ssl_ocsp_error(ctx
);
1075 ngx_ssl_ocsp_dummy_handler(ngx_event_t
*ev
)
1077 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, ev
->log
, 0,
1078 "ssl ocsp dummy handler");
1083 ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t
*ctx
)
1088 ngx_str_t binary
, base64
;
1093 ocsp
= OCSP_REQUEST_new();
1095 ngx_ssl_error(NGX_LOG_CRIT
, ctx
->log
, 0,
1096 "OCSP_REQUEST_new() failed");
1100 id
= OCSP_cert_to_id(NULL
, ctx
->cert
, ctx
->issuer
);
1102 ngx_ssl_error(NGX_LOG_CRIT
, ctx
->log
, 0,
1103 "OCSP_cert_to_id() failed");
1107 if (OCSP_request_add0_id(ocsp
, id
) == NULL
) {
1108 ngx_ssl_error(NGX_LOG_CRIT
, ctx
->log
, 0,
1109 "OCSP_request_add0_id() failed");
1113 len
= i2d_OCSP_REQUEST(ocsp
, NULL
);
1115 ngx_ssl_error(NGX_LOG_CRIT
, ctx
->log
, 0,
1116 "i2d_OCSP_REQUEST() failed");
1121 binary
.data
= ngx_palloc(ctx
->pool
, len
);
1122 if (binary
.data
== NULL
) {
1127 len
= i2d_OCSP_REQUEST(ocsp
, &p
);
1129 ngx_ssl_error(NGX_LOG_EMERG
, ctx
->log
, 0,
1130 "i2d_OCSP_REQUEST() failed");
1134 base64
.len
= ngx_base64_encoded_length(binary
.len
);
1135 base64
.data
= ngx_palloc(ctx
->pool
, base64
.len
);
1136 if (base64
.data
== NULL
) {
1140 ngx_encode_base64(&base64
, &binary
);
1142 escape
= ngx_escape_uri(NULL
, base64
.data
, base64
.len
,
1143 NGX_ESCAPE_URI_COMPONENT
);
1145 ngx_log_debug2(NGX_LOG_DEBUG_EVENT
, ctx
->log
, 0,
1146 "ssl ocsp request length %z, escape %d",
1147 base64
.len
, escape
);
1149 len
= sizeof("GET ") - 1 + ctx
->uri
.len
+ sizeof("/") - 1
1150 + base64
.len
+ 2 * escape
+ sizeof(" HTTP/1.0" CRLF
) - 1
1151 + sizeof("Host: ") - 1 + ctx
->host
.len
+ sizeof(CRLF
) - 1
1154 b
= ngx_create_temp_buf(ctx
->pool
, len
);
1161 p
= ngx_cpymem(p
, "GET ", sizeof("GET ") - 1);
1162 p
= ngx_cpymem(p
, ctx
->uri
.data
, ctx
->uri
.len
);
1164 if (ctx
->uri
.data
[ctx
->uri
.len
- 1] != '/') {
1169 p
= ngx_cpymem(p
, base64
.data
, base64
.len
);
1172 p
= (u_char
*) ngx_escape_uri(p
, base64
.data
, base64
.len
,
1173 NGX_ESCAPE_URI_COMPONENT
);
1176 p
= ngx_cpymem(p
, " HTTP/1.0" CRLF
, sizeof(" HTTP/1.0" CRLF
) - 1);
1177 p
= ngx_cpymem(p
, "Host: ", sizeof("Host: ") - 1);
1178 p
= ngx_cpymem(p
, ctx
->host
.data
, ctx
->host
.len
);
1179 *p
++ = CR
; *p
++ = LF
;
1181 /* add "\r\n" at the header end */
1182 *p
++ = CR
; *p
++ = LF
;
1191 OCSP_REQUEST_free(ocsp
);
1198 ngx_ssl_ocsp_process_status_line(ngx_ssl_ocsp_ctx_t
*ctx
)
1202 rc
= ngx_ssl_ocsp_parse_status_line(ctx
);
1206 ngx_log_debug2(NGX_LOG_DEBUG_EVENT
, ctx
->log
, 0,
1207 "ssl ocsp status line \"%*s\"",
1208 ctx
->response
->pos
- ctx
->response
->start
,
1209 ctx
->response
->start
);
1212 ctx
->process
= ngx_ssl_ocsp_process_headers
;
1213 return ctx
->process(ctx
);
1216 if (rc
== NGX_AGAIN
) {
1220 /* rc == NGX_ERROR */
1222 ngx_log_error(NGX_LOG_ERR
, ctx
->log
, 0,
1223 "OCSP responder sent invalid response");
1230 ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t
*ctx
)
1241 sw_first_major_digit
,
1243 sw_first_minor_digit
,
1246 sw_space_after_status
,
1251 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, ctx
->log
, 0,
1252 "ssl ocsp process status line");
1257 for (p
= b
->pos
; p
< b
->last
; p
++) {
1306 state
= sw_first_major_digit
;
1313 /* the first digit of major HTTP version */
1314 case sw_first_major_digit
:
1315 if (ch
< '1' || ch
> '9') {
1319 state
= sw_major_digit
;
1322 /* the major HTTP version or dot */
1323 case sw_major_digit
:
1325 state
= sw_first_minor_digit
;
1329 if (ch
< '0' || ch
> '9') {
1335 /* the first digit of minor HTTP version */
1336 case sw_first_minor_digit
:
1337 if (ch
< '0' || ch
> '9') {
1341 state
= sw_minor_digit
;
1344 /* the minor HTTP version or the end of the request line */
1345 case sw_minor_digit
:
1351 if (ch
< '0' || ch
> '9') {
1357 /* HTTP status code */
1363 if (ch
< '0' || ch
> '9') {
1367 ctx
->code
= ctx
->code
* 10 + ch
- '0';
1369 if (++ctx
->count
== 3) {
1370 state
= sw_space_after_status
;
1375 /* space or end of line */
1376 case sw_space_after_status
:
1379 state
= sw_status_text
;
1381 case '.': /* IIS may send 403.1, 403.2, etc */
1382 state
= sw_status_text
;
1385 state
= sw_almost_done
;
1394 /* any text until end of line */
1395 case sw_status_text
:
1398 state
= sw_almost_done
;
1405 /* end of status line */
1406 case sw_almost_done
:
1424 ctx
->state
= sw_start
;
1431 ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t
*ctx
)
1436 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, ctx
->log
, 0,
1437 "ssl ocsp process headers");
1440 rc
= ngx_ssl_ocsp_parse_header_line(ctx
);
1444 ngx_log_debug4(NGX_LOG_DEBUG_EVENT
, ctx
->log
, 0,
1445 "ssl ocsp header \"%*s: %*s\"",
1446 ctx
->header_name_end
- ctx
->header_name_start
,
1447 ctx
->header_name_start
,
1448 ctx
->header_end
- ctx
->header_start
,
1451 len
= ctx
->header_name_end
- ctx
->header_name_start
;
1453 if (len
== sizeof("Content-Type") - 1
1454 && ngx_strncasecmp(ctx
->header_name_start
,
1455 (u_char
*) "Content-Type",
1456 sizeof("Content-Type") - 1)
1459 len
= ctx
->header_end
- ctx
->header_start
;
1461 if (len
!= sizeof("application/ocsp-response") - 1
1462 || ngx_strncasecmp(ctx
->header_start
,
1463 (u_char
*) "application/ocsp-response",
1464 sizeof("application/ocsp-response") - 1)
1467 ngx_log_error(NGX_LOG_ERR
, ctx
->log
, 0,
1468 "OCSP responder sent invalid "
1469 "\"Content-Type\" header: \"%*s\"",
1470 ctx
->header_end
- ctx
->header_start
,
1478 /* TODO: honor Content-Length */
1483 if (rc
== NGX_DONE
) {
1487 if (rc
== NGX_AGAIN
) {
1491 /* rc == NGX_ERROR */
1493 ngx_log_error(NGX_LOG_ERR
, ctx
->log
, 0,
1494 "OCSP responder sent invalid response");
1499 ctx
->process
= ngx_ssl_ocsp_process_body
;
1500 return ctx
->process(ctx
);
1504 ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t
*ctx
)
1510 sw_space_before_value
,
1512 sw_space_after_value
,
1514 sw_header_almost_done
1519 for (p
= ctx
->response
->pos
; p
< ctx
->response
->last
; p
++) {
1523 ngx_log_debug3(NGX_LOG_DEBUG_EVENT
, ctx
->log
, 0,
1524 "s:%d in:'%02Xd:%c'", state
, ch
, ch
);
1534 ctx
->header_end
= p
;
1535 state
= sw_header_almost_done
;
1538 ctx
->header_end
= p
;
1542 ctx
->header_name_start
= p
;
1544 c
= (u_char
) (ch
| 0x20);
1545 if (c
>= 'a' && c
<= 'z') {
1549 if (ch
>= '0' && ch
<= '9') {
1559 c
= (u_char
) (ch
| 0x20);
1560 if (c
>= 'a' && c
<= 'z') {
1565 ctx
->header_name_end
= p
;
1566 state
= sw_space_before_value
;
1574 if (ch
>= '0' && ch
<= '9') {
1579 ctx
->header_name_end
= p
;
1580 ctx
->header_start
= p
;
1581 ctx
->header_end
= p
;
1582 state
= sw_almost_done
;
1587 ctx
->header_name_end
= p
;
1588 ctx
->header_start
= p
;
1589 ctx
->header_end
= p
;
1595 /* space* before header value */
1596 case sw_space_before_value
:
1601 ctx
->header_start
= p
;
1602 ctx
->header_end
= p
;
1603 state
= sw_almost_done
;
1606 ctx
->header_start
= p
;
1607 ctx
->header_end
= p
;
1610 ctx
->header_start
= p
;
1620 ctx
->header_end
= p
;
1621 state
= sw_space_after_value
;
1624 ctx
->header_end
= p
;
1625 state
= sw_almost_done
;
1628 ctx
->header_end
= p
;
1633 /* space* before end of header line */
1634 case sw_space_after_value
:
1639 state
= sw_almost_done
;
1649 /* end of header line */
1650 case sw_almost_done
:
1659 case sw_header_almost_done
:
1669 ctx
->response
->pos
= p
;
1676 ctx
->response
->pos
= p
+ 1;
1677 ctx
->state
= sw_start
;
1683 ctx
->response
->pos
= p
+ 1;
1684 ctx
->state
= sw_start
;
1691 ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t
*ctx
)
1693 ngx_log_debug0(NGX_LOG_DEBUG_EVENT
, ctx
->log
, 0,
1694 "ssl ocsp process body");
1706 ngx_ssl_ocsp_log_error(ngx_log_t
*log
, u_char
*buf
, size_t len
)
1709 ngx_ssl_ocsp_ctx_t
*ctx
;
1714 p
= ngx_snprintf(buf
, len
, " while %s", log
->action
);
1721 p
= ngx_snprintf(p
, len
, ", responder: %V", &ctx
->host
);
1732 ngx_ssl_stapling(ngx_conf_t
*cf
, ngx_ssl_t
*ssl
, ngx_str_t
*file
,
1733 ngx_str_t
*responder
, ngx_uint_t verify
)
1735 ngx_log_error(NGX_LOG_WARN
, ssl
->log
, 0,
1736 "\"ssl_stapling\" ignored, not supported");
1742 ngx_ssl_stapling_resolver(ngx_conf_t
*cf
, ngx_ssl_t
*ssl
,
1743 ngx_resolver_t
*resolver
, ngx_msec_t resolver_timeout
)