Revert "l4p/tcp: introduce tle_tcp_stream_establish() API"
[tldk.git] / app / nginx / src / event / ngx_event_openssl_stapling.c
1
2 /*
3  * Copyright (C) Maxim Dounin
4  * Copyright (C) Nginx, Inc.
5  */
6
7
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_event.h>
11 #include <ngx_event_connect.h>
12
13
14 #if (!defined OPENSSL_NO_OCSP && defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB)
15
16
17 typedef struct {
18     ngx_str_t                    staple;
19     ngx_msec_t                   timeout;
20
21     ngx_resolver_t              *resolver;
22     ngx_msec_t                   resolver_timeout;
23
24     ngx_addr_t                  *addrs;
25     ngx_str_t                    host;
26     ngx_str_t                    uri;
27     in_port_t                    port;
28
29     SSL_CTX                     *ssl_ctx;
30
31     X509                        *cert;
32     X509                        *issuer;
33
34     u_char                      *name;
35
36     time_t                       valid;
37     time_t                       refresh;
38
39     unsigned                     verify:1;
40     unsigned                     loading:1;
41 } ngx_ssl_stapling_t;
42
43
44 typedef struct ngx_ssl_ocsp_ctx_s  ngx_ssl_ocsp_ctx_t;
45
46 struct ngx_ssl_ocsp_ctx_s {
47     X509                        *cert;
48     X509                        *issuer;
49
50     u_char                      *name;
51
52     ngx_uint_t                   naddrs;
53
54     ngx_addr_t                  *addrs;
55     ngx_str_t                    host;
56     ngx_str_t                    uri;
57     in_port_t                    port;
58
59     ngx_resolver_t              *resolver;
60     ngx_msec_t                   resolver_timeout;
61
62     ngx_msec_t                   timeout;
63
64     void                       (*handler)(ngx_ssl_ocsp_ctx_t *ctx);
65     void                        *data;
66
67     ngx_buf_t                   *request;
68     ngx_buf_t                   *response;
69     ngx_peer_connection_t        peer;
70
71     ngx_int_t                  (*process)(ngx_ssl_ocsp_ctx_t *ctx);
72
73     ngx_uint_t                   state;
74
75     ngx_uint_t                   code;
76     ngx_uint_t                   count;
77
78     ngx_uint_t                   done;
79
80     u_char                      *header_name_start;
81     u_char                      *header_name_end;
82     u_char                      *header_start;
83     u_char                      *header_end;
84
85     ngx_pool_t                  *pool;
86     ngx_log_t                   *log;
87 };
88
89
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);
98
99 static int ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn,
100     void *data);
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);
103
104 static time_t ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time);
105
106 static void ngx_ssl_stapling_cleanup(void *data);
107
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);
116
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);
123
124 static u_char *ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len);
125
126
127 ngx_int_t
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)
130 {
131     X509  *cert;
132
133     for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
134          cert;
135          cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index))
136     {
137         if (ngx_ssl_stapling_certificate(cf, ssl, cert, file, responder, verify)
138             != NGX_OK)
139         {
140             return NGX_ERROR;
141         }
142     }
143
144     SSL_CTX_set_tlsext_status_cb(ssl->ctx, ngx_ssl_certificate_status_callback);
145
146     return NGX_OK;
147 }
148
149
150 static ngx_int_t
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)
153 {
154     ngx_int_t            rc;
155     ngx_pool_cleanup_t  *cln;
156     ngx_ssl_stapling_t  *staple;
157
158     staple = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_stapling_t));
159     if (staple == NULL) {
160         return NGX_ERROR;
161     }
162
163     cln = ngx_pool_cleanup_add(cf->pool, 0);
164     if (cln == NULL) {
165         return NGX_ERROR;
166     }
167
168     cln->handler = ngx_ssl_stapling_cleanup;
169     cln->data = staple;
170
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");
173         return NGX_ERROR;
174     }
175
176     staple->ssl_ctx = ssl->ctx;
177     staple->timeout = 60000;
178     staple->verify = verify;
179     staple->cert = cert;
180     staple->name = X509_get_ex_data(staple->cert,
181                                     ngx_ssl_certificate_name_index);
182
183     if (file->len) {
184         /* use OCSP response from the file */
185
186         if (ngx_ssl_stapling_file(cf, ssl, staple, file) != NGX_OK) {
187             return NGX_ERROR;
188         }
189
190         return NGX_OK;
191     }
192
193     rc = ngx_ssl_stapling_issuer(cf, ssl, staple);
194
195     if (rc == NGX_DECLINED) {
196         return NGX_OK;
197     }
198
199     if (rc != NGX_OK) {
200         return NGX_ERROR;
201     }
202
203     rc = ngx_ssl_stapling_responder(cf, ssl, staple, responder);
204
205     if (rc == NGX_DECLINED) {
206         return NGX_OK;
207     }
208
209     if (rc != NGX_OK) {
210         return NGX_ERROR;
211     }
212
213     return NGX_OK;
214 }
215
216
217 static ngx_int_t
218 ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl,
219     ngx_ssl_stapling_t *staple, ngx_str_t *file)
220 {
221     BIO            *bio;
222     int             len;
223     u_char         *p, *buf;
224     OCSP_RESPONSE  *response;
225
226     if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) {
227         return NGX_ERROR;
228     }
229
230     bio = BIO_new_file((char *) file->data, "r");
231     if (bio == NULL) {
232         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
233                       "BIO_new_file(\"%s\") failed", file->data);
234         return NGX_ERROR;
235     }
236
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);
241         BIO_free(bio);
242         return NGX_ERROR;
243     }
244
245     len = i2d_OCSP_RESPONSE(response, NULL);
246     if (len <= 0) {
247         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
248                       "i2d_OCSP_RESPONSE(\"%s\") failed", file->data);
249         goto failed;
250     }
251
252     buf = ngx_alloc(len, ssl->log);
253     if (buf == NULL) {
254         goto failed;
255     }
256
257     p = buf;
258     len = i2d_OCSP_RESPONSE(response, &p);
259     if (len <= 0) {
260         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
261                       "i2d_OCSP_RESPONSE(\"%s\") failed", file->data);
262         ngx_free(buf);
263         goto failed;
264     }
265
266     OCSP_RESPONSE_free(response);
267     BIO_free(bio);
268
269     staple->staple.data = buf;
270     staple->staple.len = len;
271     staple->valid = NGX_MAX_TIME_T_VALUE;
272
273     return NGX_OK;
274
275 failed:
276
277     OCSP_RESPONSE_free(response);
278     BIO_free(bio);
279
280     return NGX_ERROR;
281 }
282
283
284 static ngx_int_t
285 ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl,
286     ngx_ssl_stapling_t *staple)
287 {
288     int              i, n, rc;
289     X509            *cert, *issuer;
290     X509_STORE      *store;
291     X509_STORE_CTX  *store_ctx;
292     STACK_OF(X509)  *chain;
293
294     cert = staple->cert;
295
296 #ifdef SSL_CTRL_SELECT_CURRENT_CERT
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
310     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
311                    "SSL get issuer: %d extra certs", n);
312
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
317             X509_up_ref(issuer);
318 #else
319             CRYPTO_add(&issuer->references, 1, CRYPTO_LOCK_X509);
320 #endif
321
322             ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
323                            "SSL get issuer: found %p in extra certs", issuer);
324
325             staple->issuer = issuer;
326
327             return NGX_OK;
328         }
329     }
330
331     store = SSL_CTX_get_cert_store(ssl->ctx);
332     if (store == NULL) {
333         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
334                       "SSL_CTX_get_cert_store() failed");
335         return NGX_ERROR;
336     }
337
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");
342         return NGX_ERROR;
343     }
344
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);
349         return NGX_ERROR;
350     }
351
352     rc = X509_STORE_CTX_get1_issuer(&issuer, store_ctx, cert);
353
354     if (rc == -1) {
355         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
356                       "X509_STORE_CTX_get1_issuer() failed");
357         X509_STORE_CTX_free(store_ctx);
358         return NGX_ERROR;
359     }
360
361     if (rc == 0) {
362         ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
363                       "\"ssl_stapling\" ignored, "
364                       "issuer certificate not found for certificate \"%s\"",
365                       staple->name);
366         X509_STORE_CTX_free(store_ctx);
367         return NGX_DECLINED;
368     }
369
370     X509_STORE_CTX_free(store_ctx);
371
372     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
373                    "SSL get issuer: found %p in cert store", issuer);
374
375     staple->issuer = issuer;
376
377     return NGX_OK;
378 }
379
380
381 static ngx_int_t
382 ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl,
383     ngx_ssl_stapling_t *staple, ngx_str_t *responder)
384 {
385     char                      *s;
386     ngx_str_t                  rsp;
387     ngx_url_t                  u;
388     STACK_OF(OPENSSL_STRING)  *aia;
389
390     if (responder->len == 0) {
391
392         /* extract OCSP responder URL from certificate */
393
394         aia = X509_get1_ocsp(staple->cert);
395         if (aia == NULL) {
396             ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
397                           "\"ssl_stapling\" ignored, "
398                           "no OCSP responder URL in the certificate \"%s\"",
399                           staple->name);
400             return NGX_DECLINED;
401         }
402
403 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
404         s = sk_OPENSSL_STRING_value(aia, 0);
405 #else
406         s = sk_value(aia, 0);
407 #endif
408         if (s == NULL) {
409             ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
410                           "\"ssl_stapling\" ignored, "
411                           "no OCSP responder URL in the certificate \"%s\"",
412                           staple->name);
413             X509_email_free(aia);
414             return NGX_DECLINED;
415         }
416
417         responder = &rsp;
418
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);
423             return NGX_ERROR;
424         }
425
426         ngx_memcpy(responder->data, s, responder->len);
427         X509_email_free(aia);
428     }
429
430     ngx_memzero(&u, sizeof(ngx_url_t));
431
432     u.url = *responder;
433     u.default_port = 80;
434     u.uri_part = 1;
435
436     if (u.url.len > 7
437         && ngx_strncasecmp(u.url.data, (u_char *) "http://", 7) == 0)
438     {
439         u.url.len -= 7;
440         u.url.data += 7;
441
442     } else {
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);
448         return NGX_DECLINED;
449     }
450
451     if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
452         if (u.err) {
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);
458             return NGX_DECLINED;
459         }
460
461         return NGX_ERROR;
462     }
463
464     staple->addrs = u.addrs;
465     staple->host = u.host;
466     staple->uri = u.uri;
467     staple->port = u.port;
468
469     if (staple->uri.len == 0) {
470         ngx_str_set(&staple->uri, "/");
471     }
472
473     return NGX_OK;
474 }
475
476
477 ngx_int_t
478 ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
479     ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)
480 {
481     X509                *cert;
482     ngx_ssl_stapling_t  *staple;
483
484     for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
485          cert;
486          cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index))
487     {
488         staple = X509_get_ex_data(cert, ngx_ssl_stapling_index);
489         staple->resolver = resolver;
490         staple->resolver_timeout = resolver_timeout;
491     }
492
493     return NGX_OK;
494 }
495
496
497 static int
498 ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn, void *data)
499 {
500     int                  rc;
501     X509                *cert;
502     u_char              *p;
503     ngx_connection_t    *c;
504     ngx_ssl_stapling_t  *staple;
505
506     c = ngx_ssl_get_connection(ssl_conn);
507
508     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
509                    "SSL certificate status callback");
510
511     rc = SSL_TLSEXT_ERR_NOACK;
512
513     cert = SSL_get_certificate(ssl_conn);
514     staple = X509_get_ex_data(cert, ngx_ssl_stapling_index);
515
516     if (staple == NULL) {
517         return rc;
518     }
519
520     if (staple->staple.len
521         && staple->valid >= ngx_time())
522     {
523         /* we have to copy ocsp response as OpenSSL will free it by itself */
524
525         p = OPENSSL_malloc(staple->staple.len);
526         if (p == NULL) {
527             ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "OPENSSL_malloc() failed");
528             return SSL_TLSEXT_ERR_NOACK;
529         }
530
531         ngx_memcpy(p, staple->staple.data, staple->staple.len);
532
533         SSL_set_tlsext_status_ocsp_resp(ssl_conn, p, staple->staple.len);
534
535         rc = SSL_TLSEXT_ERR_OK;
536     }
537
538     ngx_ssl_stapling_update(staple);
539
540     return rc;
541 }
542
543
544 static void
545 ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple)
546 {
547     ngx_ssl_ocsp_ctx_t  *ctx;
548
549     if (staple->host.len == 0
550         || staple->loading || staple->refresh >= ngx_time())
551     {
552         return;
553     }
554
555     staple->loading = 1;
556
557     ctx = ngx_ssl_ocsp_start();
558     if (ctx == NULL) {
559         return;
560     }
561
562     ctx->cert = staple->cert;
563     ctx->issuer = staple->issuer;
564     ctx->name = staple->name;
565
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;
571
572     ctx->resolver = staple->resolver;
573     ctx->resolver_timeout = staple->resolver_timeout;
574
575     ctx->handler = ngx_ssl_stapling_ocsp_handler;
576     ctx->data = staple;
577
578     ngx_ssl_ocsp_request(ctx);
579
580     return;
581 }
582
583
584 static void
585 ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
586 {
587 #if OPENSSL_VERSION_NUMBER >= 0x0090707fL
588     const
589 #endif
590     u_char                *p;
591     int                    n;
592     size_t                 len;
593     time_t                 now, valid;
594     ngx_str_t              response;
595     X509_STORE            *store;
596     STACK_OF(X509)        *chain;
597     OCSP_CERTID           *id;
598     OCSP_RESPONSE         *ocsp;
599     OCSP_BASICRESP        *basic;
600     ngx_ssl_stapling_t    *staple;
601     ASN1_GENERALIZEDTIME  *thisupdate, *nextupdate;
602
603     staple = ctx->data;
604     now = ngx_time();
605     ocsp = NULL;
606     basic = NULL;
607     id = NULL;
608
609     if (ctx->code != 200) {
610         goto error;
611     }
612
613     /* check the response */
614
615     len = ctx->response->last - ctx->response->pos;
616     p = ctx->response->pos;
617
618     ocsp = d2i_OCSP_RESPONSE(NULL, &p, len);
619     if (ocsp == NULL) {
620         ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
621                       "d2i_OCSP_RESPONSE() failed");
622         goto error;
623     }
624
625     n = OCSP_response_status(ocsp);
626
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));
631         goto error;
632     }
633
634     basic = OCSP_response_get1_basic(ocsp);
635     if (basic == NULL) {
636         ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
637                       "OCSP_response_get1_basic() failed");
638         goto error;
639     }
640
641     store = SSL_CTX_get_cert_store(staple->ssl_ctx);
642     if (store == NULL) {
643         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
644                       "SSL_CTX_get_cert_store() failed");
645         goto error;
646     }
647
648 #ifdef SSL_CTRL_SELECT_CURRENT_CERT
649     /* OpenSSL 1.0.2+ */
650     SSL_CTX_select_current_cert(staple->ssl_ctx, ctx->cert);
651 #endif
652
653 #ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
654     /* OpenSSL 1.0.1+ */
655     SSL_CTX_get_extra_chain_certs(staple->ssl_ctx, &chain);
656 #else
657     chain = staple->ssl_ctx->extra_certs;
658 #endif
659
660     if (OCSP_basic_verify(basic, chain, store,
661                           staple->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY)
662         != 1)
663     {
664         ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
665                       "OCSP_basic_verify() failed");
666         goto error;
667     }
668
669     id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
670     if (id == NULL) {
671         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
672                       "OCSP_cert_to_id() failed");
673         goto error;
674     }
675
676     if (OCSP_resp_find_status(basic, id, &n, NULL, NULL,
677                               &thisupdate, &nextupdate)
678         != 1)
679     {
680         ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
681                       "certificate status not found in the OCSP response");
682         goto error;
683     }
684
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));
689         goto error;
690     }
691
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");
695         goto error;
696     }
697
698     if (nextupdate) {
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");
703             goto error;
704         }
705
706     } else {
707         valid = NGX_MAX_TIME_T_VALUE;
708     }
709
710     OCSP_CERTID_free(id);
711     OCSP_BASICRESP_free(basic);
712     OCSP_RESPONSE_free(ocsp);
713
714     id = NULL;
715     basic = NULL;
716     ocsp = NULL;
717
718     /* copy the response to memory not in ctx->pool */
719
720     response.len = len;
721     response.data = ngx_alloc(response.len, ctx->log);
722
723     if (response.data == NULL) {
724         goto error;
725     }
726
727     ngx_memcpy(response.data, ctx->response->pos, response.len);
728
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);
732
733     if (staple->staple.data) {
734         ngx_free(staple->staple.data);
735     }
736
737     staple->staple = response;
738     staple->valid = valid;
739
740     /*
741      * refresh before the response expires,
742      * but not earlier than in 5 minutes, and at least in an hour
743      */
744
745     staple->loading = 0;
746     staple->refresh = ngx_max(ngx_min(valid - 300, now + 3600), now + 300);
747
748     ngx_ssl_ocsp_done(ctx);
749     return;
750
751 error:
752
753     staple->loading = 0;
754     staple->refresh = now + 300;
755
756     if (id) {
757         OCSP_CERTID_free(id);
758     }
759
760     if (basic) {
761         OCSP_BASICRESP_free(basic);
762     }
763
764     if (ocsp) {
765         OCSP_RESPONSE_free(ocsp);
766     }
767
768     ngx_ssl_ocsp_done(ctx);
769 }
770
771
772 static time_t
773 ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time)
774 {
775     BIO     *bio;
776     char    *value;
777     size_t   len;
778     time_t   time;
779
780     /*
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.
785      */
786
787     bio = BIO_new(BIO_s_mem());
788     if (bio == NULL) {
789         return NGX_ERROR;
790     }
791
792     /* fake weekday prepended to match C asctime() format */
793
794     BIO_write(bio, "Tue ", sizeof("Tue ") - 1);
795     ASN1_GENERALIZEDTIME_print(bio, asn1time);
796     len = BIO_get_mem_data(bio, &value);
797
798     time = ngx_parse_http_time((u_char *) value, len);
799
800     BIO_free(bio);
801
802     return time;
803 }
804
805
806 static void
807 ngx_ssl_stapling_cleanup(void *data)
808 {
809     ngx_ssl_stapling_t  *staple = data;
810
811     if (staple->issuer) {
812         X509_free(staple->issuer);
813     }
814
815     if (staple->staple.data) {
816         ngx_free(staple->staple.data);
817     }
818 }
819
820
821 static ngx_ssl_ocsp_ctx_t *
822 ngx_ssl_ocsp_start(void)
823 {
824     ngx_log_t           *log;
825     ngx_pool_t          *pool;
826     ngx_ssl_ocsp_ctx_t  *ctx;
827
828     pool = ngx_create_pool(2048, ngx_cycle->log);
829     if (pool == NULL) {
830         return NULL;
831     }
832
833     ctx = ngx_pcalloc(pool, sizeof(ngx_ssl_ocsp_ctx_t));
834     if (ctx == NULL) {
835         ngx_destroy_pool(pool);
836         return NULL;
837     }
838
839     log = ngx_palloc(pool, sizeof(ngx_log_t));
840     if (log == NULL) {
841         ngx_destroy_pool(pool);
842         return NULL;
843     }
844
845     ctx->pool = pool;
846
847     *log = *ctx->pool->log;
848
849     ctx->pool->log = log;
850     ctx->log = log;
851
852     log->handler = ngx_ssl_ocsp_log_error;
853     log->data = ctx;
854     log->action = "requesting certificate status";
855
856     return ctx;
857 }
858
859
860 static void
861 ngx_ssl_ocsp_done(ngx_ssl_ocsp_ctx_t *ctx)
862 {
863     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
864                    "ssl ocsp done");
865
866     if (ctx->peer.connection) {
867         ngx_close_connection(ctx->peer.connection);
868     }
869
870     ngx_destroy_pool(ctx->pool);
871 }
872
873
874 static void
875 ngx_ssl_ocsp_error(ngx_ssl_ocsp_ctx_t *ctx)
876 {
877     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
878                    "ssl ocsp error");
879
880     ctx->code = 0;
881     ctx->handler(ctx);
882 }
883
884
885 static void
886 ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx)
887 {
888     ngx_resolver_ctx_t  *resolve, temp;
889
890     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
891                    "ssl ocsp request");
892
893     if (ngx_ssl_ocsp_create_request(ctx) != NGX_OK) {
894         ngx_ssl_ocsp_error(ctx);
895         return;
896     }
897
898     if (ctx->resolver) {
899         /* resolve OCSP responder hostname */
900
901         temp.name = ctx->host;
902
903         resolve = ngx_resolve_start(ctx->resolver, &temp);
904         if (resolve == NULL) {
905             ngx_ssl_ocsp_error(ctx);
906             return;
907         }
908
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);
912             goto connect;
913         }
914
915         resolve->name = ctx->host;
916         resolve->handler = ngx_ssl_ocsp_resolve_handler;
917         resolve->data = ctx;
918         resolve->timeout = ctx->resolver_timeout;
919
920         if (ngx_resolve_name(resolve) != NGX_OK) {
921             ngx_ssl_ocsp_error(ctx);
922             return;
923         }
924
925         return;
926     }
927
928 connect:
929
930     ngx_ssl_ocsp_connect(ctx);
931 }
932
933
934 static void
935 ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve)
936 {
937     ngx_ssl_ocsp_ctx_t *ctx = resolve->data;
938
939     u_char           *p;
940     size_t            len;
941     socklen_t         socklen;
942     ngx_uint_t        i;
943     struct sockaddr  *sockaddr;
944
945     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
946                    "ssl ocsp resolve handler");
947
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));
953         goto failed;
954     }
955
956 #if (NGX_DEBUG)
957     {
958     u_char     text[NGX_SOCKADDR_STRLEN];
959     ngx_str_t  addr;
960
961     addr.data = text;
962
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);
967
968         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
969                        "name was resolved to %V", &addr);
970
971     }
972     }
973 #endif
974
975     ctx->naddrs = resolve->naddrs;
976     ctx->addrs = ngx_pcalloc(ctx->pool, ctx->naddrs * sizeof(ngx_addr_t));
977
978     if (ctx->addrs == NULL) {
979         goto failed;
980     }
981
982     for (i = 0; i < resolve->naddrs; i++) {
983
984         socklen = resolve->addrs[i].socklen;
985
986         sockaddr = ngx_palloc(ctx->pool, socklen);
987         if (sockaddr == NULL) {
988             goto failed;
989         }
990
991         ngx_memcpy(sockaddr, resolve->addrs[i].sockaddr, socklen);
992         ngx_inet_set_port(sockaddr, ctx->port);
993
994         ctx->addrs[i].sockaddr = sockaddr;
995         ctx->addrs[i].socklen = socklen;
996
997         p = ngx_pnalloc(ctx->pool, NGX_SOCKADDR_STRLEN);
998         if (p == NULL) {
999             goto failed;
1000         }
1001
1002         len = ngx_sock_ntop(sockaddr, socklen, p, NGX_SOCKADDR_STRLEN, 1);
1003
1004         ctx->addrs[i].name.len = len;
1005         ctx->addrs[i].name.data = p;
1006     }
1007
1008     ngx_resolve_name_done(resolve);
1009
1010     ngx_ssl_ocsp_connect(ctx);
1011     return;
1012
1013 failed:
1014
1015     ngx_resolve_name_done(resolve);
1016     ngx_ssl_ocsp_error(ctx);
1017 }
1018
1019
1020 static void
1021 ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx)
1022 {
1023     ngx_int_t  rc;
1024
1025     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1026                    "ssl ocsp connect");
1027
1028     /* TODO: use all ip addresses */
1029
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;
1036
1037     rc = ngx_event_connect_peer(&ctx->peer);
1038
1039     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1040                    "ssl ocsp connect peer done");
1041
1042     if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
1043         ngx_ssl_ocsp_error(ctx);
1044         return;
1045     }
1046
1047     ctx->peer.connection->data = ctx;
1048     ctx->peer.connection->pool = ctx->pool;
1049
1050     ctx->peer.connection->read->handler = ngx_ssl_ocsp_read_handler;
1051     ctx->peer.connection->write->handler = ngx_ssl_ocsp_write_handler;
1052
1053     ctx->process = ngx_ssl_ocsp_process_status_line;
1054
1055     ngx_add_timer(ctx->peer.connection->read, ctx->timeout);
1056     ngx_add_timer(ctx->peer.connection->write, ctx->timeout);
1057
1058     if (rc == NGX_OK) {
1059         ngx_ssl_ocsp_write_handler(ctx->peer.connection->write);
1060         return;
1061     }
1062 }
1063
1064
1065 static void
1066 ngx_ssl_ocsp_write_handler(ngx_event_t *wev)
1067 {
1068     ssize_t              n, size;
1069     ngx_connection_t    *c;
1070     ngx_ssl_ocsp_ctx_t  *ctx;
1071
1072     c = wev->data;
1073     ctx = c->data;
1074
1075     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, wev->log, 0,
1076                    "ssl ocsp write handler");
1077
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);
1082         return;
1083     }
1084
1085     size = ctx->request->last - ctx->request->pos;
1086
1087     n = ngx_send(c, ctx->request->pos, size);
1088
1089     if (n == NGX_ERROR) {
1090         ngx_ssl_ocsp_error(ctx);
1091         return;
1092     }
1093
1094     if (n > 0) {
1095         ctx->request->pos += n;
1096
1097         if (n == size) {
1098             wev->handler = ngx_ssl_ocsp_dummy_handler;
1099
1100             if (wev->timer_set) {
1101                 ngx_del_timer(wev);
1102             }
1103
1104             if (ngx_handle_write_event(wev, 0) != NGX_OK) {
1105                 ngx_ssl_ocsp_error(ctx);
1106             }
1107
1108             return;
1109         }
1110     }
1111
1112     if (!wev->timer_set) {
1113         ngx_add_timer(wev, ctx->timeout);
1114     }
1115 }
1116
1117
1118 static void
1119 ngx_ssl_ocsp_read_handler(ngx_event_t *rev)
1120 {
1121     ssize_t              n, size;
1122     ngx_int_t            rc;
1123     ngx_connection_t    *c;
1124     ngx_ssl_ocsp_ctx_t  *ctx;
1125
1126     c = rev->data;
1127     ctx = c->data;
1128
1129     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, rev->log, 0,
1130                    "ssl ocsp read handler");
1131
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);
1136         return;
1137     }
1138
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);
1143             return;
1144         }
1145     }
1146
1147     for ( ;; ) {
1148
1149         size = ctx->response->end - ctx->response->last;
1150
1151         n = ngx_recv(c, ctx->response->last, size);
1152
1153         if (n > 0) {
1154             ctx->response->last += n;
1155
1156             rc = ctx->process(ctx);
1157
1158             if (rc == NGX_ERROR) {
1159                 ngx_ssl_ocsp_error(ctx);
1160                 return;
1161             }
1162
1163             continue;
1164         }
1165
1166         if (n == NGX_AGAIN) {
1167
1168             if (ngx_handle_read_event(rev, 0) != NGX_OK) {
1169                 ngx_ssl_ocsp_error(ctx);
1170             }
1171
1172             return;
1173         }
1174
1175         break;
1176     }
1177
1178     ctx->done = 1;
1179
1180     rc = ctx->process(ctx);
1181
1182     if (rc == NGX_DONE) {
1183         /* ctx->handler() was called */
1184         return;
1185     }
1186
1187     ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1188                   "OCSP responder prematurely closed connection");
1189
1190     ngx_ssl_ocsp_error(ctx);
1191 }
1192
1193
1194 static void
1195 ngx_ssl_ocsp_dummy_handler(ngx_event_t *ev)
1196 {
1197     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0,
1198                    "ssl ocsp dummy handler");
1199 }
1200
1201
1202 static ngx_int_t
1203 ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx)
1204 {
1205     int            len;
1206     u_char        *p;
1207     uintptr_t      escape;
1208     ngx_str_t      binary, base64;
1209     ngx_buf_t     *b;
1210     OCSP_CERTID   *id;
1211     OCSP_REQUEST  *ocsp;
1212
1213     ocsp = OCSP_REQUEST_new();
1214     if (ocsp == NULL) {
1215         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1216                       "OCSP_REQUEST_new() failed");
1217         return NGX_ERROR;
1218     }
1219
1220     id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
1221     if (id == NULL) {
1222         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1223                       "OCSP_cert_to_id() failed");
1224         goto failed;
1225     }
1226
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);
1231         goto failed;
1232     }
1233
1234     len = i2d_OCSP_REQUEST(ocsp, NULL);
1235     if (len <= 0) {
1236         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1237                       "i2d_OCSP_REQUEST() failed");
1238         goto failed;
1239     }
1240
1241     binary.len = len;
1242     binary.data = ngx_palloc(ctx->pool, len);
1243     if (binary.data == NULL) {
1244         goto failed;
1245     }
1246
1247     p = binary.data;
1248     len = i2d_OCSP_REQUEST(ocsp, &p);
1249     if (len <= 0) {
1250         ngx_ssl_error(NGX_LOG_EMERG, ctx->log, 0,
1251                       "i2d_OCSP_REQUEST() failed");
1252         goto failed;
1253     }
1254
1255     base64.len = ngx_base64_encoded_length(binary.len);
1256     base64.data = ngx_palloc(ctx->pool, base64.len);
1257     if (base64.data == NULL) {
1258         goto failed;
1259     }
1260
1261     ngx_encode_base64(&base64, &binary);
1262
1263     escape = ngx_escape_uri(NULL, base64.data, base64.len,
1264                             NGX_ESCAPE_URI_COMPONENT);
1265
1266     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1267                    "ssl ocsp request length %z, escape %d",
1268                    base64.len, (int) escape);
1269
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
1273           + sizeof(CRLF) - 1;
1274
1275     b = ngx_create_temp_buf(ctx->pool, len);
1276     if (b == NULL) {
1277         goto failed;
1278     }
1279
1280     p = b->last;
1281
1282     p = ngx_cpymem(p, "GET ", sizeof("GET ") - 1);
1283     p = ngx_cpymem(p, ctx->uri.data, ctx->uri.len);
1284
1285     if (ctx->uri.data[ctx->uri.len - 1] != '/') {
1286         *p++ = '/';
1287     }
1288
1289     if (escape == 0) {
1290         p = ngx_cpymem(p, base64.data, base64.len);
1291
1292     } else {
1293         p = (u_char *) ngx_escape_uri(p, base64.data, base64.len,
1294                                       NGX_ESCAPE_URI_COMPONENT);
1295     }
1296
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;
1301
1302     /* add "\r\n" at the header end */
1303     *p++ = CR; *p++ = LF;
1304
1305     b->last = p;
1306     ctx->request = b;
1307
1308     OCSP_REQUEST_free(ocsp);
1309
1310     return NGX_OK;
1311
1312 failed:
1313
1314     OCSP_REQUEST_free(ocsp);
1315
1316     return NGX_ERROR;
1317 }
1318
1319
1320 static ngx_int_t
1321 ngx_ssl_ocsp_process_status_line(ngx_ssl_ocsp_ctx_t *ctx)
1322 {
1323     ngx_int_t  rc;
1324
1325     rc = ngx_ssl_ocsp_parse_status_line(ctx);
1326
1327     if (rc == NGX_OK) {
1328         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1329                        "ssl ocsp status %ui \"%*s\"",
1330                        ctx->code,
1331                        ctx->header_end - ctx->header_start,
1332                        ctx->header_start);
1333
1334         ctx->process = ngx_ssl_ocsp_process_headers;
1335         return ctx->process(ctx);
1336     }
1337
1338     if (rc == NGX_AGAIN) {
1339         return NGX_AGAIN;
1340     }
1341
1342     /* rc == NGX_ERROR */
1343
1344     ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1345                   "OCSP responder sent invalid response");
1346
1347     return NGX_ERROR;
1348 }
1349
1350
1351 static ngx_int_t
1352 ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t *ctx)
1353 {
1354     u_char      ch;
1355     u_char     *p;
1356     ngx_buf_t  *b;
1357     enum {
1358         sw_start = 0,
1359         sw_H,
1360         sw_HT,
1361         sw_HTT,
1362         sw_HTTP,
1363         sw_first_major_digit,
1364         sw_major_digit,
1365         sw_first_minor_digit,
1366         sw_minor_digit,
1367         sw_status,
1368         sw_space_after_status,
1369         sw_status_text,
1370         sw_almost_done
1371     } state;
1372
1373     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1374                    "ssl ocsp process status line");
1375
1376     state = ctx->state;
1377     b = ctx->response;
1378
1379     for (p = b->pos; p < b->last; p++) {
1380         ch = *p;
1381
1382         switch (state) {
1383
1384         /* "HTTP/" */
1385         case sw_start:
1386             switch (ch) {
1387             case 'H':
1388                 state = sw_H;
1389                 break;
1390             default:
1391                 return NGX_ERROR;
1392             }
1393             break;
1394
1395         case sw_H:
1396             switch (ch) {
1397             case 'T':
1398                 state = sw_HT;
1399                 break;
1400             default:
1401                 return NGX_ERROR;
1402             }
1403             break;
1404
1405         case sw_HT:
1406             switch (ch) {
1407             case 'T':
1408                 state = sw_HTT;
1409                 break;
1410             default:
1411                 return NGX_ERROR;
1412             }
1413             break;
1414
1415         case sw_HTT:
1416             switch (ch) {
1417             case 'P':
1418                 state = sw_HTTP;
1419                 break;
1420             default:
1421                 return NGX_ERROR;
1422             }
1423             break;
1424
1425         case sw_HTTP:
1426             switch (ch) {
1427             case '/':
1428                 state = sw_first_major_digit;
1429                 break;
1430             default:
1431                 return NGX_ERROR;
1432             }
1433             break;
1434
1435         /* the first digit of major HTTP version */
1436         case sw_first_major_digit:
1437             if (ch < '1' || ch > '9') {
1438                 return NGX_ERROR;
1439             }
1440
1441             state = sw_major_digit;
1442             break;
1443
1444         /* the major HTTP version or dot */
1445         case sw_major_digit:
1446             if (ch == '.') {
1447                 state = sw_first_minor_digit;
1448                 break;
1449             }
1450
1451             if (ch < '0' || ch > '9') {
1452                 return NGX_ERROR;
1453             }
1454
1455             break;
1456
1457         /* the first digit of minor HTTP version */
1458         case sw_first_minor_digit:
1459             if (ch < '0' || ch > '9') {
1460                 return NGX_ERROR;
1461             }
1462
1463             state = sw_minor_digit;
1464             break;
1465
1466         /* the minor HTTP version or the end of the request line */
1467         case sw_minor_digit:
1468             if (ch == ' ') {
1469                 state = sw_status;
1470                 break;
1471             }
1472
1473             if (ch < '0' || ch > '9') {
1474                 return NGX_ERROR;
1475             }
1476
1477             break;
1478
1479         /* HTTP status code */
1480         case sw_status:
1481             if (ch == ' ') {
1482                 break;
1483             }
1484
1485             if (ch < '0' || ch > '9') {
1486                 return NGX_ERROR;
1487             }
1488
1489             ctx->code = ctx->code * 10 + ch - '0';
1490
1491             if (++ctx->count == 3) {
1492                 state = sw_space_after_status;
1493                 ctx->header_start = p - 2;
1494             }
1495
1496             break;
1497
1498         /* space or end of line */
1499         case sw_space_after_status:
1500             switch (ch) {
1501             case ' ':
1502                 state = sw_status_text;
1503                 break;
1504             case '.':                    /* IIS may send 403.1, 403.2, etc */
1505                 state = sw_status_text;
1506                 break;
1507             case CR:
1508                 state = sw_almost_done;
1509                 break;
1510             case LF:
1511                 ctx->header_end = p;
1512                 goto done;
1513             default:
1514                 return NGX_ERROR;
1515             }
1516             break;
1517
1518         /* any text until end of line */
1519         case sw_status_text:
1520             switch (ch) {
1521             case CR:
1522                 state = sw_almost_done;
1523                 break;
1524             case LF:
1525                 ctx->header_end = p;
1526                 goto done;
1527             }
1528             break;
1529
1530         /* end of status line */
1531         case sw_almost_done:
1532             switch (ch) {
1533             case LF:
1534                 ctx->header_end = p - 1;
1535                 goto done;
1536             default:
1537                 return NGX_ERROR;
1538             }
1539         }
1540     }
1541
1542     b->pos = p;
1543     ctx->state = state;
1544
1545     return NGX_AGAIN;
1546
1547 done:
1548
1549     b->pos = p + 1;
1550     ctx->state = sw_start;
1551
1552     return NGX_OK;
1553 }
1554
1555
1556 static ngx_int_t
1557 ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx)
1558 {
1559     size_t     len;
1560     ngx_int_t  rc;
1561
1562     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1563                    "ssl ocsp process headers");
1564
1565     for ( ;; ) {
1566         rc = ngx_ssl_ocsp_parse_header_line(ctx);
1567
1568         if (rc == NGX_OK) {
1569
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,
1575                            ctx->header_start);
1576
1577             len = ctx->header_name_end - ctx->header_name_start;
1578
1579             if (len == sizeof("Content-Type") - 1
1580                 && ngx_strncasecmp(ctx->header_name_start,
1581                                    (u_char *) "Content-Type",
1582                                    sizeof("Content-Type") - 1)
1583                    == 0)
1584             {
1585                 len = ctx->header_end - ctx->header_start;
1586
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)
1591                        != 0)
1592                 {
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,
1597                                   ctx->header_start);
1598                     return NGX_ERROR;
1599                 }
1600
1601                 continue;
1602             }
1603
1604             /* TODO: honor Content-Length */
1605
1606             continue;
1607         }
1608
1609         if (rc == NGX_DONE) {
1610             break;
1611         }
1612
1613         if (rc == NGX_AGAIN) {
1614             return NGX_AGAIN;
1615         }
1616
1617         /* rc == NGX_ERROR */
1618
1619         ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1620                       "OCSP responder sent invalid response");
1621
1622         return NGX_ERROR;
1623     }
1624
1625     ctx->process = ngx_ssl_ocsp_process_body;
1626     return ctx->process(ctx);
1627 }
1628
1629
1630 static ngx_int_t
1631 ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx)
1632 {
1633     u_char  c, ch, *p;
1634     enum {
1635         sw_start = 0,
1636         sw_name,
1637         sw_space_before_value,
1638         sw_value,
1639         sw_space_after_value,
1640         sw_almost_done,
1641         sw_header_almost_done
1642     } state;
1643
1644     state = ctx->state;
1645
1646     for (p = ctx->response->pos; p < ctx->response->last; p++) {
1647         ch = *p;
1648
1649 #if 0
1650         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1651                        "s:%d in:'%02Xd:%c'", state, ch, ch);
1652 #endif
1653
1654         switch (state) {
1655
1656         /* first char */
1657         case sw_start:
1658
1659             switch (ch) {
1660             case CR:
1661                 ctx->header_end = p;
1662                 state = sw_header_almost_done;
1663                 break;
1664             case LF:
1665                 ctx->header_end = p;
1666                 goto header_done;
1667             default:
1668                 state = sw_name;
1669                 ctx->header_name_start = p;
1670
1671                 c = (u_char) (ch | 0x20);
1672                 if (c >= 'a' && c <= 'z') {
1673                     break;
1674                 }
1675
1676                 if (ch >= '0' && ch <= '9') {
1677                     break;
1678                 }
1679
1680                 return NGX_ERROR;
1681             }
1682             break;
1683
1684         /* header name */
1685         case sw_name:
1686             c = (u_char) (ch | 0x20);
1687             if (c >= 'a' && c <= 'z') {
1688                 break;
1689             }
1690
1691             if (ch == ':') {
1692                 ctx->header_name_end = p;
1693                 state = sw_space_before_value;
1694                 break;
1695             }
1696
1697             if (ch == '-') {
1698                 break;
1699             }
1700
1701             if (ch >= '0' && ch <= '9') {
1702                 break;
1703             }
1704
1705             if (ch == CR) {
1706                 ctx->header_name_end = p;
1707                 ctx->header_start = p;
1708                 ctx->header_end = p;
1709                 state = sw_almost_done;
1710                 break;
1711             }
1712
1713             if (ch == LF) {
1714                 ctx->header_name_end = p;
1715                 ctx->header_start = p;
1716                 ctx->header_end = p;
1717                 goto done;
1718             }
1719
1720             return NGX_ERROR;
1721
1722         /* space* before header value */
1723         case sw_space_before_value:
1724             switch (ch) {
1725             case ' ':
1726                 break;
1727             case CR:
1728                 ctx->header_start = p;
1729                 ctx->header_end = p;
1730                 state = sw_almost_done;
1731                 break;
1732             case LF:
1733                 ctx->header_start = p;
1734                 ctx->header_end = p;
1735                 goto done;
1736             default:
1737                 ctx->header_start = p;
1738                 state = sw_value;
1739                 break;
1740             }
1741             break;
1742
1743         /* header value */
1744         case sw_value:
1745             switch (ch) {
1746             case ' ':
1747                 ctx->header_end = p;
1748                 state = sw_space_after_value;
1749                 break;
1750             case CR:
1751                 ctx->header_end = p;
1752                 state = sw_almost_done;
1753                 break;
1754             case LF:
1755                 ctx->header_end = p;
1756                 goto done;
1757             }
1758             break;
1759
1760         /* space* before end of header line */
1761         case sw_space_after_value:
1762             switch (ch) {
1763             case ' ':
1764                 break;
1765             case CR:
1766                 state = sw_almost_done;
1767                 break;
1768             case LF:
1769                 goto done;
1770             default:
1771                 state = sw_value;
1772                 break;
1773             }
1774             break;
1775
1776         /* end of header line */
1777         case sw_almost_done:
1778             switch (ch) {
1779             case LF:
1780                 goto done;
1781             default:
1782                 return NGX_ERROR;
1783             }
1784
1785         /* end of header */
1786         case sw_header_almost_done:
1787             switch (ch) {
1788             case LF:
1789                 goto header_done;
1790             default:
1791                 return NGX_ERROR;
1792             }
1793         }
1794     }
1795
1796     ctx->response->pos = p;
1797     ctx->state = state;
1798
1799     return NGX_AGAIN;
1800
1801 done:
1802
1803     ctx->response->pos = p + 1;
1804     ctx->state = sw_start;
1805
1806     return NGX_OK;
1807
1808 header_done:
1809
1810     ctx->response->pos = p + 1;
1811     ctx->state = sw_start;
1812
1813     return NGX_DONE;
1814 }
1815
1816
1817 static ngx_int_t
1818 ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx)
1819 {
1820     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1821                    "ssl ocsp process body");
1822
1823     if (ctx->done) {
1824         ctx->handler(ctx);
1825         return NGX_DONE;
1826     }
1827
1828     return NGX_AGAIN;
1829 }
1830
1831
1832 static u_char *
1833 ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len)
1834 {
1835     u_char              *p;
1836     ngx_ssl_ocsp_ctx_t  *ctx;
1837
1838     p = buf;
1839
1840     if (log->action) {
1841         p = ngx_snprintf(buf, len, " while %s", log->action);
1842         len -= p - buf;
1843         buf = p;
1844     }
1845
1846     ctx = log->data;
1847
1848     if (ctx) {
1849         p = ngx_snprintf(buf, len, ", responder: %V", &ctx->host);
1850         len -= p - buf;
1851         buf = p;
1852     }
1853
1854     if (ctx && ctx->peer.name) {
1855         p = ngx_snprintf(buf, len, ", peer: %V", ctx->peer.name);
1856         len -= p - buf;
1857         buf = p;
1858     }
1859
1860     if (ctx && ctx->name) {
1861         p = ngx_snprintf(buf, len, ", certificate: \"%s\"", ctx->name);
1862         len -= p - buf;
1863         buf = p;
1864     }
1865
1866     return p;
1867 }
1868
1869
1870 #else
1871
1872
1873 ngx_int_t
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)
1876 {
1877     ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
1878                   "\"ssl_stapling\" ignored, not supported");
1879
1880     return NGX_OK;
1881 }
1882
1883
1884 ngx_int_t
1885 ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
1886     ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)
1887 {
1888     return NGX_OK;
1889 }
1890
1891
1892 #endif