Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ngx_event_openssl_stapling.c
Go to the documentation of this file.
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 #ifdef 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  time_t valid;
35 
36  unsigned verify:1;
37  unsigned loading:1;
38 } ngx_ssl_stapling_t;
39 
40 
41 typedef struct ngx_ssl_ocsp_ctx_s ngx_ssl_ocsp_ctx_t;
42 
43 struct ngx_ssl_ocsp_ctx_s {
44  X509 *cert;
45  X509 *issuer;
46 
47  ngx_uint_t naddrs;
48 
49  ngx_addr_t *addrs;
50  ngx_str_t host;
51  ngx_str_t uri;
52  in_port_t port;
53 
54  ngx_resolver_t *resolver;
55  ngx_msec_t resolver_timeout;
56 
57  ngx_msec_t timeout;
58 
59  void (*handler)(ngx_ssl_ocsp_ctx_t *r);
60  void *data;
61 
62  ngx_buf_t *request;
63  ngx_buf_t *response;
65 
66  ngx_int_t (*process)(ngx_ssl_ocsp_ctx_t *r);
67 
68  ngx_uint_t state;
69 
70  ngx_uint_t code;
71  ngx_uint_t count;
72 
73  ngx_uint_t done;
74 
75  u_char *header_name_start;
76  u_char *header_name_end;
77  u_char *header_start;
78  u_char *header_end;
79 
80  ngx_pool_t *pool;
81  ngx_log_t *log;
82 };
83 
84 
85 static ngx_int_t ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl,
86  ngx_str_t *file);
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);
90 
91 static int ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn,
92  void *data);
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);
95 
96 static void ngx_ssl_stapling_cleanup(void *data);
97 
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);
106 
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);
113 
114 static u_char *ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len);
115 
116 
117 ngx_int_t
119  ngx_str_t *responder, ngx_uint_t verify)
120 {
121  ngx_int_t rc;
122  ngx_pool_cleanup_t *cln;
123  ngx_ssl_stapling_t *staple;
124 
125  staple = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_stapling_t));
126  if (staple == NULL) {
127  return NGX_ERROR;
128  }
129 
130  cln = ngx_pool_cleanup_add(cf->pool, 0);
131  if (cln == NULL) {
132  return NGX_ERROR;
133  }
134 
135  cln->handler = ngx_ssl_stapling_cleanup;
136  cln->data = staple;
137 
138  if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_stapling_index, staple)
139  == 0)
140  {
142  "SSL_CTX_set_ex_data() failed");
143  return NGX_ERROR;
144  }
145 
146  staple->ssl_ctx = ssl->ctx;
147  staple->timeout = 60000;
148  staple->verify = verify;
149 
150  if (file->len) {
151  /* use OCSP response from the file */
152 
153  if (ngx_ssl_stapling_file(cf, ssl, file) != NGX_OK) {
154  return NGX_ERROR;
155  }
156 
157  goto done;
158  }
159 
160  rc = ngx_ssl_stapling_issuer(cf, ssl);
161 
162  if (rc == NGX_DECLINED) {
163  return NGX_OK;
164  }
165 
166  if (rc != NGX_OK) {
167  return NGX_ERROR;
168  }
169 
170  rc = ngx_ssl_stapling_responder(cf, ssl, responder);
171 
172  if (rc == NGX_DECLINED) {
173  return NGX_OK;
174  }
175 
176  if (rc != NGX_OK) {
177  return NGX_ERROR;
178  }
179 
180 done:
181 
182  SSL_CTX_set_tlsext_status_cb(ssl->ctx, ngx_ssl_certificate_status_callback);
183  SSL_CTX_set_tlsext_status_arg(ssl->ctx, staple);
184 
185  return NGX_OK;
186 }
187 
188 
189 static ngx_int_t
190 ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file)
191 {
192  BIO *bio;
193  int len;
194  u_char *p, *buf;
195  OCSP_RESPONSE *response;
196  ngx_ssl_stapling_t *staple;
197 
198  staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index);
199 
200  if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) {
201  return NGX_ERROR;
202  }
203 
204  bio = BIO_new_file((char *) file->data, "r");
205  if (bio == NULL) {
207  "BIO_new_file(\"%s\") failed", file->data);
208  return NGX_ERROR;
209  }
210 
211  response = d2i_OCSP_RESPONSE_bio(bio, NULL);
212  if (response == NULL) {
214  "d2i_OCSP_RESPONSE_bio(\"%s\") failed", file->data);
215  BIO_free(bio);
216  return NGX_ERROR;
217  }
218 
219  len = i2d_OCSP_RESPONSE(response, NULL);
220  if (len <= 0) {
222  "i2d_OCSP_RESPONSE(\"%s\") failed", file->data);
223  goto failed;
224  }
225 
226  buf = ngx_alloc(len, ssl->log);
227  if (buf == NULL) {
228  goto failed;
229  }
230 
231  p = buf;
232  len = i2d_OCSP_RESPONSE(response, &p);
233  if (len <= 0) {
235  "i2d_OCSP_RESPONSE(\"%s\") failed", file->data);
236  ngx_free(buf);
237  goto failed;
238  }
239 
240  OCSP_RESPONSE_free(response);
241  BIO_free(bio);
242 
243  staple->staple.data = buf;
244  staple->staple.len = len;
245 
246  return NGX_OK;
247 
248 failed:
249 
250  OCSP_RESPONSE_free(response);
251  BIO_free(bio);
252 
253  return NGX_ERROR;
254 }
255 
256 
257 static ngx_int_t
258 ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl)
259 {
260  int i, n, rc;
261  X509 *cert, *issuer;
262  X509_STORE *store;
263  X509_STORE_CTX *store_ctx;
264  STACK_OF(X509) *chain;
265  ngx_ssl_stapling_t *staple;
266 
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);
269 
270 #if OPENSSL_VERSION_NUMBER >= 0x10001000L
271  SSL_CTX_get_extra_chain_certs(ssl->ctx, &chain);
272 #else
273  chain = ssl->ctx->extra_certs;
274 #endif
275 
276  n = sk_X509_num(chain);
277 
279  "SSL get issuer: %d extra certs", n);
280 
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);
285 
287  "SSL get issuer: found %p in extra certs", issuer);
288 
289  staple->cert = cert;
290  staple->issuer = issuer;
291 
292  return NGX_OK;
293  }
294  }
295 
296  store = SSL_CTX_get_cert_store(ssl->ctx);
297  if (store == NULL) {
299  "SSL_CTX_get_cert_store() failed");
300  return NGX_ERROR;
301  }
302 
303  store_ctx = X509_STORE_CTX_new();
304  if (store_ctx == NULL) {
306  "X509_STORE_CTX_new() failed");
307  return NGX_ERROR;
308  }
309 
310  if (X509_STORE_CTX_init(store_ctx, store, NULL, NULL) == 0) {
312  "X509_STORE_CTX_init() failed");
313  return NGX_ERROR;
314  }
315 
316  rc = X509_STORE_CTX_get1_issuer(&issuer, store_ctx, cert);
317 
318  if (rc == -1) {
320  "X509_STORE_CTX_get1_issuer() failed");
321  X509_STORE_CTX_free(store_ctx);
322  return NGX_ERROR;
323  }
324 
325  if (rc == 0) {
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);
329  return NGX_DECLINED;
330  }
331 
332  X509_STORE_CTX_free(store_ctx);
333 
335  "SSL get issuer: found %p in cert store", issuer);
336 
337  staple->cert = cert;
338  staple->issuer = issuer;
339 
340  return NGX_OK;
341 }
342 
343 
344 static ngx_int_t
345 ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *responder)
346 {
347  ngx_url_t u;
348  char *s;
349  ngx_ssl_stapling_t *staple;
350  STACK_OF(OPENSSL_STRING) *aia;
351 
352  staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index);
353 
354  if (responder->len == 0) {
355 
356  /* extract OCSP responder URL from certificate */
357 
358  aia = X509_get1_ocsp(staple->cert);
359  if (aia == NULL) {
360  ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
361  "\"ssl_stapling\" ignored, "
362  "no OCSP responder URL in the certificate");
363  return NGX_DECLINED;
364  }
365 
366 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
367  s = sk_OPENSSL_STRING_value(aia, 0);
368 #else
369  s = sk_value(aia, 0);
370 #endif
371  if (s == NULL) {
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);
376  return NGX_DECLINED;
377  }
378 
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);
383  return NGX_ERROR;
384  }
385 
386  ngx_memcpy(responder->data, s, responder->len);
387  X509_email_free(aia);
388  }
389 
390  ngx_memzero(&u, sizeof(ngx_url_t));
391 
392  u.url = *responder;
393  u.default_port = 80;
394  u.uri_part = 1;
395 
396  if (u.url.len > 7
397  && ngx_strncasecmp(u.url.data, (u_char *) "http://", 7) == 0)
398  {
399  u.url.len -= 7;
400  u.url.data += 7;
401 
402  } else {
403  ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
404  "\"ssl_stapling\" ignored, "
405  "invalid URL prefix in OCSP responder \"%V\"", &u.url);
406  return NGX_DECLINED;
407  }
408 
409  if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
410  if (u.err) {
411  ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
412  "\"ssl_stapling\" ignored, "
413  "%s in OCSP responder \"%V\"", u.err, &u.url);
414  return NGX_DECLINED;
415  }
416 
417  return NGX_ERROR;
418  }
419 
420  staple->addrs = u.addrs;
421  staple->host = u.host;
422  staple->uri = u.uri;
423  staple->port = u.port;
424 
425  if (staple->uri.len == 0) {
426  ngx_str_set(&staple->uri, "/");
427  }
428 
429  return NGX_OK;
430 }
431 
432 
433 ngx_int_t
435  ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)
436 {
437  ngx_ssl_stapling_t *staple;
438 
439  staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index);
440 
441  staple->resolver = resolver;
442  staple->resolver_timeout = resolver_timeout;
443 
444  return NGX_OK;
445 }
446 
447 
448 static int
449 ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn, void *data)
450 {
451  int rc;
452  u_char *p;
453  ngx_connection_t *c;
454  ngx_ssl_stapling_t *staple;
455 
456  c = ngx_ssl_get_connection(ssl_conn);
457 
459  "SSL certificate status callback");
460 
461  staple = data;
462  rc = SSL_TLSEXT_ERR_NOACK;
463 
464  if (staple->staple.len) {
465  /* we have to copy ocsp response as OpenSSL will free it by itself */
466 
467  p = OPENSSL_malloc(staple->staple.len);
468  if (p == NULL) {
469  ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "OPENSSL_malloc() failed");
470  return SSL_TLSEXT_ERR_NOACK;
471  }
472 
473  ngx_memcpy(p, staple->staple.data, staple->staple.len);
474 
475  SSL_set_tlsext_status_ocsp_resp(ssl_conn, p, staple->staple.len);
476 
477  rc = SSL_TLSEXT_ERR_OK;
478  }
479 
480  ngx_ssl_stapling_update(staple);
481 
482  return rc;
483 }
484 
485 
486 static void
487 ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple)
488 {
489  ngx_ssl_ocsp_ctx_t *ctx;
490 
491  if (staple->host.len == 0
492  || staple->loading || staple->valid >= ngx_time())
493  {
494  return;
495  }
496 
497  staple->loading = 1;
498 
499  ctx = ngx_ssl_ocsp_start();
500  if (ctx == NULL) {
501  return;
502  }
503 
504  ctx->cert = staple->cert;
505  ctx->issuer = staple->issuer;
506 
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;
512 
513  ctx->resolver = staple->resolver;
514  ctx->resolver_timeout = staple->resolver_timeout;
515 
516  ctx->handler = ngx_ssl_stapling_ocsp_handler;
517  ctx->data = staple;
518 
519  ngx_ssl_ocsp_request(ctx);
520 
521  return;
522 }
523 
524 
525 static void
526 ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
527 {
528 #if OPENSSL_VERSION_NUMBER >= 0x0090707fL
529  const
530 #endif
531  u_char *p;
532  int n;
533  size_t len;
534  ngx_str_t response;
535  X509_STORE *store;
536  STACK_OF(X509) *chain;
537  OCSP_CERTID *id;
538  OCSP_RESPONSE *ocsp;
539  OCSP_BASICRESP *basic;
540  ngx_ssl_stapling_t *staple;
541  ASN1_GENERALIZEDTIME *thisupdate, *nextupdate;
542 
543  staple = ctx->data;
544  ocsp = NULL;
545  basic = NULL;
546  id = NULL;
547 
548  if (ctx->code != 200) {
549  goto error;
550  }
551 
552  /* check the response */
553 
554  len = ctx->response->last - ctx->response->pos;
555  p = ctx->response->pos;
556 
557  ocsp = d2i_OCSP_RESPONSE(NULL, &p, len);
558  if (ocsp == NULL) {
559  ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
560  "d2i_OCSP_RESPONSE() failed");
561  goto error;
562  }
563 
564  n = OCSP_response_status(ocsp);
565 
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));
570  goto error;
571  }
572 
573  basic = OCSP_response_get1_basic(ocsp);
574  if (basic == NULL) {
575  ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
576  "OCSP_response_get1_basic() failed");
577  goto error;
578  }
579 
580  store = SSL_CTX_get_cert_store(staple->ssl_ctx);
581  if (store == NULL) {
582  ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
583  "SSL_CTX_get_cert_store() failed");
584  goto error;
585  }
586 
587 #if OPENSSL_VERSION_NUMBER >= 0x10001000L
588  SSL_CTX_get_extra_chain_certs(staple->ssl_ctx, &chain);
589 #else
590  chain = staple->ssl_ctx->extra_certs;
591 #endif
592 
593  if (OCSP_basic_verify(basic, chain, store,
594  staple->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY)
595  != 1)
596  {
597  ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
598  "OCSP_basic_verify() failed");
599  goto error;
600  }
601 
602  id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
603  if (id == NULL) {
604  ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
605  "OCSP_cert_to_id() failed");
606  goto error;
607  }
608 
609  if (OCSP_resp_find_status(basic, id, &n, NULL, NULL,
610  &thisupdate, &nextupdate)
611  != 1)
612  {
613  ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
614  "certificate status not found in the OCSP response");
615  goto error;
616  }
617 
618  if (n != V_OCSP_CERTSTATUS_GOOD) {
619  ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
620  "certificate status \"%s\" in the OCSP response",
621  OCSP_cert_status_str(n));
622  goto error;
623  }
624 
625  if (OCSP_check_validity(thisupdate, nextupdate, 300, -1) != 1) {
626  ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
627  "OCSP_check_validity() failed");
628  goto error;
629  }
630 
631  OCSP_CERTID_free(id);
632  OCSP_BASICRESP_free(basic);
633  OCSP_RESPONSE_free(ocsp);
634 
635  /* copy the response to memory not in ctx->pool */
636 
637  response.len = len;
638  response.data = ngx_alloc(response.len, ctx->log);
639 
640  if (response.data == NULL) {
641  goto done;
642  }
643 
644  ngx_memcpy(response.data, ctx->response->pos, response.len);
645 
646  ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
647  "ssl ocsp response, %s, %uz",
648  OCSP_cert_status_str(n), response.len);
649 
650  if (staple->staple.data) {
651  ngx_free(staple->staple.data);
652  }
653 
654  staple->staple = response;
655 
656 done:
657 
658  staple->loading = 0;
659  staple->valid = ngx_time() + 3600; /* ssl_stapling_valid */
660 
661  ngx_ssl_ocsp_done(ctx);
662  return;
663 
664 error:
665 
666  staple->loading = 0;
667  staple->valid = ngx_time() + 300; /* ssl_stapling_err_valid */
668 
669  if (id) {
670  OCSP_CERTID_free(id);
671  }
672 
673  if (basic) {
674  OCSP_BASICRESP_free(basic);
675  }
676 
677  if (ocsp) {
678  OCSP_RESPONSE_free(ocsp);
679  }
680 
681  ngx_ssl_ocsp_done(ctx);
682 }
683 
684 
685 static void
686 ngx_ssl_stapling_cleanup(void *data)
687 {
688  ngx_ssl_stapling_t *staple = data;
689 
690  if (staple->issuer) {
691  X509_free(staple->issuer);
692  }
693 
694  if (staple->staple.data) {
695  ngx_free(staple->staple.data);
696  }
697 }
698 
699 
700 static ngx_ssl_ocsp_ctx_t *
701 ngx_ssl_ocsp_start(void)
702 {
703  ngx_log_t *log;
704  ngx_pool_t *pool;
705  ngx_ssl_ocsp_ctx_t *ctx;
706 
707  pool = ngx_create_pool(2048, ngx_cycle->log);
708  if (pool == NULL) {
709  return NULL;
710  }
711 
712  ctx = ngx_pcalloc(pool, sizeof(ngx_ssl_ocsp_ctx_t));
713  if (ctx == NULL) {
714  ngx_destroy_pool(pool);
715  return NULL;
716  }
717 
718  log = ngx_palloc(pool, sizeof(ngx_log_t));
719  if (log == NULL) {
720  ngx_destroy_pool(pool);
721  return NULL;
722  }
723 
724  ctx->pool = pool;
725 
726  *log = *ctx->pool->log;
727 
728  ctx->pool->log = log;
729  ctx->log = log;
730 
731  log->handler = ngx_ssl_ocsp_log_error;
732  log->data = ctx;
733  log->action = "requesting certificate status";
734 
735  return ctx;
736 }
737 
738 
739 static void
740 ngx_ssl_ocsp_done(ngx_ssl_ocsp_ctx_t *ctx)
741 {
742  ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
743  "ssl ocsp done");
744 
745  if (ctx->peer.connection) {
746  ngx_close_connection(ctx->peer.connection);
747  }
748 
749  ngx_destroy_pool(ctx->pool);
750 }
751 
752 
753 static void
754 ngx_ssl_ocsp_error(ngx_ssl_ocsp_ctx_t *ctx)
755 {
756  ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
757  "ssl ocsp error");
758 
759  ctx->code = 0;
760  ctx->handler(ctx);
761 }
762 
763 
764 static void
765 ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx)
766 {
767  ngx_resolver_ctx_t *resolve, temp;
768 
769  ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
770  "ssl ocsp request");
771 
772  if (ngx_ssl_ocsp_create_request(ctx) != NGX_OK) {
773  ngx_ssl_ocsp_error(ctx);
774  return;
775  }
776 
777  if (ctx->resolver) {
778  /* resolve OCSP responder hostname */
779 
780  temp.name = ctx->host;
781 
782  resolve = ngx_resolve_start(ctx->resolver, &temp);
783  if (resolve == NULL) {
784  ngx_ssl_ocsp_error(ctx);
785  return;
786  }
787 
788  if (resolve == NGX_NO_RESOLVER) {
789  ngx_log_error(NGX_LOG_WARN, ctx->log, 0,
790  "no resolver defined to resolve %V", &ctx->host);
791  goto connect;
792  }
793 
794  resolve->name = ctx->host;
795  resolve->type = NGX_RESOLVE_A;
796  resolve->handler = ngx_ssl_ocsp_resolve_handler;
797  resolve->data = ctx;
798  resolve->timeout = ctx->resolver_timeout;
799 
800  if (ngx_resolve_name(resolve) != NGX_OK) {
801  ngx_ssl_ocsp_error(ctx);
802  return;
803  }
804 
805  return;
806  }
807 
808 connect:
809 
810  ngx_ssl_ocsp_connect(ctx);
811 }
812 
813 
814 static void
815 ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve)
816 {
817  ngx_ssl_ocsp_ctx_t *ctx = resolve->data;
818 
819  u_char *p;
820  size_t len;
821  in_port_t port;
822  ngx_uint_t i;
823  struct sockaddr_in *sin;
824 
825  ngx_log_debug0(NGX_LOG_ALERT, ctx->log, 0,
826  "ssl ocsp resolve handler");
827 
828  if (resolve->state) {
829  ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
830  "%V could not be resolved (%i: %s)",
831  &resolve->name, resolve->state,
832  ngx_resolver_strerror(resolve->state));
833  goto failed;
834  }
835 
836 #if (NGX_DEBUG)
837  {
838  in_addr_t addr;
839 
840  for (i = 0; i < resolve->naddrs; i++) {
841  addr = ntohl(resolve->addrs[i]);
842 
843  ngx_log_debug4(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
844  "name was resolved to %ud.%ud.%ud.%ud",
845  (addr >> 24) & 0xff, (addr >> 16) & 0xff,
846  (addr >> 8) & 0xff, addr & 0xff);
847  }
848  }
849 #endif
850 
851  ctx->naddrs = resolve->naddrs;
852  ctx->addrs = ngx_pcalloc(ctx->pool, ctx->naddrs * sizeof(ngx_addr_t));
853 
854  if (ctx->addrs == NULL) {
855  goto failed;
856  }
857 
858  port = htons(ctx->port);
859 
860  for (i = 0; i < resolve->naddrs; i++) {
861 
862  sin = ngx_pcalloc(ctx->pool, sizeof(struct sockaddr_in));
863  if (sin == NULL) {
864  goto failed;
865  }
866 
867  sin->sin_family = AF_INET;
868  sin->sin_port = port;
869  sin->sin_addr.s_addr = resolve->addrs[i];
870 
871  ctx->addrs[i].sockaddr = (struct sockaddr *) sin;
872  ctx->addrs[i].socklen = sizeof(struct sockaddr_in);
873 
874  len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
875 
876  p = ngx_pnalloc(ctx->pool, len);
877  if (p == NULL) {
878  goto failed;
879  }
880 
881  len = ngx_sock_ntop((struct sockaddr *) sin, p, len, 1);
882 
883  ctx->addrs[i].name.len = len;
884  ctx->addrs[i].name.data = p;
885  }
886 
887  ngx_resolve_name_done(resolve);
888 
889  ngx_ssl_ocsp_connect(ctx);
890  return;
891 
892 failed:
893 
894  ngx_resolve_name_done(resolve);
895  ngx_ssl_ocsp_error(ctx);
896 }
897 
898 
899 static void
900 ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx)
901 {
902  ngx_int_t rc;
903 
904  ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
905  "ssl ocsp connect");
906 
907  /* TODO: use all ip addresses */
908 
909  ctx->peer.sockaddr = ctx->addrs[0].sockaddr;
910  ctx->peer.socklen = ctx->addrs[0].socklen;
911  ctx->peer.name = &ctx->addrs[0].name;
912  ctx->peer.get = ngx_event_get_peer;
913  ctx->peer.log = ctx->log;
914  ctx->peer.log_error = NGX_ERROR_ERR;
915 
916  rc = ngx_event_connect_peer(&ctx->peer);
917 
918  ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
919  "ssl ocsp connect peer done");
920 
921  if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
922  ngx_ssl_ocsp_error(ctx);
923  return;
924  }
925 
926  ctx->peer.connection->data = ctx;
927  ctx->peer.connection->pool = ctx->pool;
928 
929  ctx->peer.connection->read->handler = ngx_ssl_ocsp_read_handler;
930  ctx->peer.connection->write->handler = ngx_ssl_ocsp_write_handler;
931 
932  ctx->process = ngx_ssl_ocsp_process_status_line;
933 
934  ngx_add_timer(ctx->peer.connection->read, ctx->timeout);
935  ngx_add_timer(ctx->peer.connection->write, ctx->timeout);
936 
937  if (rc == NGX_OK) {
938  ngx_ssl_ocsp_write_handler(ctx->peer.connection->write);
939  return;
940  }
941 }
942 
943 
944 static void
945 ngx_ssl_ocsp_write_handler(ngx_event_t *wev)
946 {
947  ssize_t n, size;
948  ngx_connection_t *c;
949  ngx_ssl_ocsp_ctx_t *ctx;
950 
951  c = wev->data;
952  ctx = c->data;
953 
955  "ssl ocsp write handler");
956 
957  if (wev->timedout) {
959  "OCSP responder timed out");
960  ngx_ssl_ocsp_error(ctx);
961  return;
962  }
963 
964  size = ctx->request->last - ctx->request->pos;
965 
966  n = ngx_send(c, ctx->request->pos, size);
967 
968  if (n == NGX_ERROR) {
969  ngx_ssl_ocsp_error(ctx);
970  return;
971  }
972 
973  if (n > 0) {
974  ctx->request->pos += n;
975 
976  if (n == size) {
977  wev->handler = ngx_ssl_ocsp_dummy_handler;
978 
979  if (wev->timer_set) {
980  ngx_del_timer(wev);
981  }
982 
983  if (ngx_handle_write_event(wev, 0) != NGX_OK) {
984  ngx_ssl_ocsp_error(ctx);
985  }
986 
987  return;
988  }
989  }
990 
991  if (!wev->timer_set) {
992  ngx_add_timer(wev, ctx->timeout);
993  }
994 }
995 
996 
997 static void
998 ngx_ssl_ocsp_read_handler(ngx_event_t *rev)
999 {
1000  ssize_t n, size;
1001  ngx_int_t rc;
1002  ngx_ssl_ocsp_ctx_t *ctx;
1003  ngx_connection_t *c;
1004 
1005  c = rev->data;
1006  ctx = c->data;
1007 
1009  "ssl ocsp read handler");
1010 
1011  if (rev->timedout) {
1013  "OCSP responder timed out");
1014  ngx_ssl_ocsp_error(ctx);
1015  return;
1016  }
1017 
1018  if (ctx->response == NULL) {
1019  ctx->response = ngx_create_temp_buf(ctx->pool, 16384);
1020  if (ctx->response == NULL) {
1021  ngx_ssl_ocsp_error(ctx);
1022  return;
1023  }
1024  }
1025 
1026  for ( ;; ) {
1027 
1028  size = ctx->response->end - ctx->response->last;
1029 
1030  n = ngx_recv(c, ctx->response->last, size);
1031 
1032  if (n > 0) {
1033  ctx->response->last += n;
1034 
1035  rc = ctx->process(ctx);
1036 
1037  if (rc == NGX_ERROR) {
1038  ngx_ssl_ocsp_error(ctx);
1039  return;
1040  }
1041 
1042  continue;
1043  }
1044 
1045  if (n == NGX_AGAIN) {
1046 
1047  if (ngx_handle_read_event(rev, 0) != NGX_OK) {
1048  ngx_ssl_ocsp_error(ctx);
1049  }
1050 
1051  return;
1052  }
1053 
1054  break;
1055  }
1056 
1057  ctx->done = 1;
1058 
1059  rc = ctx->process(ctx);
1060 
1061  if (rc == NGX_DONE) {
1062  /* ctx->handler() was called */
1063  return;
1064  }
1065 
1066  ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1067  "OCSP responder prematurely closed connection");
1068 
1069  ngx_ssl_ocsp_error(ctx);
1070 }
1071 
1072 
1073 static void
1074 ngx_ssl_ocsp_dummy_handler(ngx_event_t *ev)
1075 {
1077  "ssl ocsp dummy handler");
1078 }
1079 
1080 
1081 static ngx_int_t
1082 ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx)
1083 {
1084  int len;
1085  u_char *p;
1086  uintptr_t escape;
1087  ngx_str_t binary, base64;
1088  ngx_buf_t *b;
1089  OCSP_CERTID *id;
1090  OCSP_REQUEST *ocsp;
1091 
1092  ocsp = OCSP_REQUEST_new();
1093  if (ocsp == NULL) {
1094  ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1095  "OCSP_REQUEST_new() failed");
1096  return NGX_ERROR;
1097  }
1098 
1099  id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
1100  if (id == NULL) {
1101  ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1102  "OCSP_cert_to_id() failed");
1103  goto failed;
1104  }
1105 
1106  if (OCSP_request_add0_id(ocsp, id) == NULL) {
1107  ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1108  "OCSP_request_add0_id() failed");
1109  goto failed;
1110  }
1111 
1112  len = i2d_OCSP_REQUEST(ocsp, NULL);
1113  if (len <= 0) {
1114  ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1115  "i2d_OCSP_REQUEST() failed");
1116  goto failed;
1117  }
1118 
1119  binary.len = len;
1120  binary.data = ngx_palloc(ctx->pool, len);
1121  if (binary.data == NULL) {
1122  goto failed;
1123  }
1124 
1125  p = binary.data;
1126  len = i2d_OCSP_REQUEST(ocsp, &p);
1127  if (len <= 0) {
1128  ngx_ssl_error(NGX_LOG_EMERG, ctx->log, 0,
1129  "i2d_OCSP_REQUEST() failed");
1130  goto failed;
1131  }
1132 
1133  base64.len = ngx_base64_encoded_length(binary.len);
1134  base64.data = ngx_palloc(ctx->pool, base64.len);
1135  if (base64.data == NULL) {
1136  goto failed;
1137  }
1138 
1139  ngx_encode_base64(&base64, &binary);
1140 
1141  escape = ngx_escape_uri(NULL, base64.data, base64.len,
1143 
1144  ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1145  "ssl ocsp request length %z, escape %d",
1146  base64.len, escape);
1147 
1148  len = sizeof("GET ") - 1 + ctx->uri.len + sizeof("/") - 1
1149  + base64.len + 2 * escape + sizeof(" HTTP/1.0" CRLF) - 1
1150  + sizeof("Host: ") - 1 + ctx->host.len + sizeof(CRLF) - 1
1151  + sizeof(CRLF) - 1;
1152 
1153  b = ngx_create_temp_buf(ctx->pool, len);
1154  if (b == NULL) {
1155  goto failed;
1156  }
1157 
1158  p = b->last;
1159 
1160  p = ngx_cpymem(p, "GET ", sizeof("GET ") - 1);
1161  p = ngx_cpymem(p, ctx->uri.data, ctx->uri.len);
1162 
1163  if (ctx->uri.data[ctx->uri.len - 1] != '/') {
1164  *p++ = '/';
1165  }
1166 
1167  if (escape == 0) {
1168  p = ngx_cpymem(p, base64.data, base64.len);
1169 
1170  } else {
1171  p = (u_char *) ngx_escape_uri(p, base64.data, base64.len,
1173  }
1174 
1175  p = ngx_cpymem(p, " HTTP/1.0" CRLF, sizeof(" HTTP/1.0" CRLF) - 1);
1176  p = ngx_cpymem(p, "Host: ", sizeof("Host: ") - 1);
1177  p = ngx_cpymem(p, ctx->host.data, ctx->host.len);
1178  *p++ = CR; *p++ = LF;
1179 
1180  /* add "\r\n" at the header end */
1181  *p++ = CR; *p++ = LF;
1182 
1183  b->last = p;
1184  ctx->request = b;
1185 
1186  return NGX_OK;
1187 
1188 failed:
1189 
1190  OCSP_REQUEST_free(ocsp);
1191 
1192  return NGX_ERROR;
1193 }
1194 
1195 
1196 static ngx_int_t
1197 ngx_ssl_ocsp_process_status_line(ngx_ssl_ocsp_ctx_t *ctx)
1198 {
1199  ngx_int_t rc;
1200 
1201  rc = ngx_ssl_ocsp_parse_status_line(ctx);
1202 
1203  if (rc == NGX_OK) {
1204 #if 0
1205  ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1206  "ssl ocsp status line \"%*s\"",
1207  ctx->response->pos - ctx->response->start,
1208  ctx->response->start);
1209 #endif
1210 
1211  ctx->process = ngx_ssl_ocsp_process_headers;
1212  return ctx->process(ctx);
1213  }
1214 
1215  if (rc == NGX_AGAIN) {
1216  return NGX_AGAIN;
1217  }
1218 
1219  /* rc == NGX_ERROR */
1220 
1221  ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1222  "OCSP responder sent invalid response");
1223 
1224  return NGX_ERROR;
1225 }
1226 
1227 
1228 static ngx_int_t
1229 ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t *ctx)
1230 {
1231  u_char ch;
1232  u_char *p;
1233  ngx_buf_t *b;
1234  enum {
1235  sw_start = 0,
1236  sw_H,
1237  sw_HT,
1238  sw_HTT,
1239  sw_HTTP,
1240  sw_first_major_digit,
1241  sw_major_digit,
1242  sw_first_minor_digit,
1243  sw_minor_digit,
1244  sw_status,
1245  sw_space_after_status,
1246  sw_status_text,
1247  sw_almost_done
1248  } state;
1249 
1250  ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1251  "ssl ocsp process status line");
1252 
1253  state = ctx->state;
1254  b = ctx->response;
1255 
1256  for (p = b->pos; p < b->last; p++) {
1257  ch = *p;
1258 
1259  switch (state) {
1260 
1261  /* "HTTP/" */
1262  case sw_start:
1263  switch (ch) {
1264  case 'H':
1265  state = sw_H;
1266  break;
1267  default:
1268  return NGX_ERROR;
1269  }
1270  break;
1271 
1272  case sw_H:
1273  switch (ch) {
1274  case 'T':
1275  state = sw_HT;
1276  break;
1277  default:
1278  return NGX_ERROR;
1279  }
1280  break;
1281 
1282  case sw_HT:
1283  switch (ch) {
1284  case 'T':
1285  state = sw_HTT;
1286  break;
1287  default:
1288  return NGX_ERROR;
1289  }
1290  break;
1291 
1292  case sw_HTT:
1293  switch (ch) {
1294  case 'P':
1295  state = sw_HTTP;
1296  break;
1297  default:
1298  return NGX_ERROR;
1299  }
1300  break;
1301 
1302  case sw_HTTP:
1303  switch (ch) {
1304  case '/':
1305  state = sw_first_major_digit;
1306  break;
1307  default:
1308  return NGX_ERROR;
1309  }
1310  break;
1311 
1312  /* the first digit of major HTTP version */
1313  case sw_first_major_digit:
1314  if (ch < '1' || ch > '9') {
1315  return NGX_ERROR;
1316  }
1317 
1318  state = sw_major_digit;
1319  break;
1320 
1321  /* the major HTTP version or dot */
1322  case sw_major_digit:
1323  if (ch == '.') {
1324  state = sw_first_minor_digit;
1325  break;
1326  }
1327 
1328  if (ch < '0' || ch > '9') {
1329  return NGX_ERROR;
1330  }
1331 
1332  break;
1333 
1334  /* the first digit of minor HTTP version */
1335  case sw_first_minor_digit:
1336  if (ch < '0' || ch > '9') {
1337  return NGX_ERROR;
1338  }
1339 
1340  state = sw_minor_digit;
1341  break;
1342 
1343  /* the minor HTTP version or the end of the request line */
1344  case sw_minor_digit:
1345  if (ch == ' ') {
1346  state = sw_status;
1347  break;
1348  }
1349 
1350  if (ch < '0' || ch > '9') {
1351  return NGX_ERROR;
1352  }
1353 
1354  break;
1355 
1356  /* HTTP status code */
1357  case sw_status:
1358  if (ch == ' ') {
1359  break;
1360  }
1361 
1362  if (ch < '0' || ch > '9') {
1363  return NGX_ERROR;
1364  }
1365 
1366  ctx->code = ctx->code * 10 + ch - '0';
1367 
1368  if (++ctx->count == 3) {
1369  state = sw_space_after_status;
1370  }
1371 
1372  break;
1373 
1374  /* space or end of line */
1375  case sw_space_after_status:
1376  switch (ch) {
1377  case ' ':
1378  state = sw_status_text;
1379  break;
1380  case '.': /* IIS may send 403.1, 403.2, etc */
1381  state = sw_status_text;
1382  break;
1383  case CR:
1384  state = sw_almost_done;
1385  break;
1386  case LF:
1387  goto done;
1388  default:
1389  return NGX_ERROR;
1390  }
1391  break;
1392 
1393  /* any text until end of line */
1394  case sw_status_text:
1395  switch (ch) {
1396  case CR:
1397  state = sw_almost_done;
1398  break;
1399  case LF:
1400  goto done;
1401  }
1402  break;
1403 
1404  /* end of status line */
1405  case sw_almost_done:
1406  switch (ch) {
1407  case LF:
1408  goto done;
1409  default:
1410  return NGX_ERROR;
1411  }
1412  }
1413  }
1414 
1415  b->pos = p;
1416  ctx->state = state;
1417 
1418  return NGX_AGAIN;
1419 
1420 done:
1421 
1422  b->pos = p + 1;
1423  ctx->state = sw_start;
1424 
1425  return NGX_OK;
1426 }
1427 
1428 
1429 static ngx_int_t
1430 ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx)
1431 {
1432  size_t len;
1433  ngx_int_t rc;
1434 
1435  ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1436  "ssl ocsp process headers");
1437 
1438  for ( ;; ) {
1439  rc = ngx_ssl_ocsp_parse_header_line(ctx);
1440 
1441  if (rc == NGX_OK) {
1442 
1443  ngx_log_debug4(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1444  "ssl ocsp header \"%*s: %*s\"",
1445  ctx->header_name_end - ctx->header_name_start,
1446  ctx->header_name_start,
1447  ctx->header_end - ctx->header_start,
1448  ctx->header_start);
1449 
1450  len = ctx->header_name_end - ctx->header_name_start;
1451 
1452  if (len == sizeof("Content-Type") - 1
1453  && ngx_strncasecmp(ctx->header_name_start,
1454  (u_char *) "Content-Type",
1455  sizeof("Content-Type") - 1)
1456  == 0)
1457  {
1458  len = ctx->header_end - ctx->header_start;
1459 
1460  if (len != sizeof("application/ocsp-response") - 1
1461  || ngx_strncasecmp(ctx->header_start,
1462  (u_char *) "application/ocsp-response",
1463  sizeof("application/ocsp-response") - 1)
1464  != 0)
1465  {
1466  ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1467  "OCSP responder sent invalid "
1468  "\"Content-Type\" header: \"%*s\"",
1469  ctx->header_end - ctx->header_start,
1470  ctx->header_start);
1471  return NGX_ERROR;
1472  }
1473 
1474  continue;
1475  }
1476 
1477  /* TODO: honor Content-Length */
1478 
1479  continue;
1480  }
1481 
1482  if (rc == NGX_DONE) {
1483  break;
1484  }
1485 
1486  if (rc == NGX_AGAIN) {
1487  return NGX_AGAIN;
1488  }
1489 
1490  /* rc == NGX_ERROR */
1491 
1492  ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1493  "OCSP responder sent invalid response");
1494 
1495  return NGX_ERROR;
1496  }
1497 
1498  ctx->process = ngx_ssl_ocsp_process_body;
1499  return ctx->process(ctx);
1500 }
1501 
1502 static ngx_int_t
1503 ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx)
1504 {
1505  u_char c, ch, *p;
1506  enum {
1507  sw_start = 0,
1508  sw_name,
1509  sw_space_before_value,
1510  sw_value,
1511  sw_space_after_value,
1512  sw_almost_done,
1513  sw_header_almost_done
1514  } state;
1515 
1516  state = ctx->state;
1517 
1518  for (p = ctx->response->pos; p < ctx->response->last; p++) {
1519  ch = *p;
1520 
1521 #if 0
1522  ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1523  "s:%d in:'%02Xd:%c'", state, ch, ch);
1524 #endif
1525 
1526  switch (state) {
1527 
1528  /* first char */
1529  case sw_start:
1530 
1531  switch (ch) {
1532  case CR:
1533  ctx->header_end = p;
1534  state = sw_header_almost_done;
1535  break;
1536  case LF:
1537  ctx->header_end = p;
1538  goto header_done;
1539  default:
1540  state = sw_name;
1541  ctx->header_name_start = p;
1542 
1543  c = (u_char) (ch | 0x20);
1544  if (c >= 'a' && c <= 'z') {
1545  break;
1546  }
1547 
1548  if (ch >= '0' && ch <= '9') {
1549  break;
1550  }
1551 
1552  return NGX_ERROR;
1553  }
1554  break;
1555 
1556  /* header name */
1557  case sw_name:
1558  c = (u_char) (ch | 0x20);
1559  if (c >= 'a' && c <= 'z') {
1560  break;
1561  }
1562 
1563  if (ch == ':') {
1564  ctx->header_name_end = p;
1565  state = sw_space_before_value;
1566  break;
1567  }
1568 
1569  if (ch == '-') {
1570  break;
1571  }
1572 
1573  if (ch >= '0' && ch <= '9') {
1574  break;
1575  }
1576 
1577  if (ch == CR) {
1578  ctx->header_name_end = p;
1579  ctx->header_start = p;
1580  ctx->header_end = p;
1581  state = sw_almost_done;
1582  break;
1583  }
1584 
1585  if (ch == LF) {
1586  ctx->header_name_end = p;
1587  ctx->header_start = p;
1588  ctx->header_end = p;
1589  goto done;
1590  }
1591 
1592  return NGX_ERROR;
1593 
1594  /* space* before header value */
1595  case sw_space_before_value:
1596  switch (ch) {
1597  case ' ':
1598  break;
1599  case CR:
1600  ctx->header_start = p;
1601  ctx->header_end = p;
1602  state = sw_almost_done;
1603  break;
1604  case LF:
1605  ctx->header_start = p;
1606  ctx->header_end = p;
1607  goto done;
1608  default:
1609  ctx->header_start = p;
1610  state = sw_value;
1611  break;
1612  }
1613  break;
1614 
1615  /* header value */
1616  case sw_value:
1617  switch (ch) {
1618  case ' ':
1619  ctx->header_end = p;
1620  state = sw_space_after_value;
1621  break;
1622  case CR:
1623  ctx->header_end = p;
1624  state = sw_almost_done;
1625  break;
1626  case LF:
1627  ctx->header_end = p;
1628  goto done;
1629  }
1630  break;
1631 
1632  /* space* before end of header line */
1633  case sw_space_after_value:
1634  switch (ch) {
1635  case ' ':
1636  break;
1637  case CR:
1638  state = sw_almost_done;
1639  break;
1640  case LF:
1641  goto done;
1642  default:
1643  state = sw_value;
1644  break;
1645  }
1646  break;
1647 
1648  /* end of header line */
1649  case sw_almost_done:
1650  switch (ch) {
1651  case LF:
1652  goto done;
1653  default:
1654  return NGX_ERROR;
1655  }
1656 
1657  /* end of header */
1658  case sw_header_almost_done:
1659  switch (ch) {
1660  case LF:
1661  goto header_done;
1662  default:
1663  return NGX_ERROR;
1664  }
1665  }
1666  }
1667 
1668  ctx->response->pos = p;
1669  ctx->state = state;
1670 
1671  return NGX_AGAIN;
1672 
1673 done:
1674 
1675  ctx->response->pos = p + 1;
1676  ctx->state = sw_start;
1677 
1678  return NGX_OK;
1679 
1680 header_done:
1681 
1682  ctx->response->pos = p + 1;
1683  ctx->state = sw_start;
1684 
1685  return NGX_DONE;
1686 }
1687 
1688 
1689 static ngx_int_t
1690 ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx)
1691 {
1692  ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1693  "ssl ocsp process body");
1694 
1695  if (ctx->done) {
1696  ctx->handler(ctx);
1697  return NGX_DONE;
1698  }
1699 
1700  return NGX_AGAIN;
1701 }
1702 
1703 
1704 static u_char *
1705 ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len)
1706 {
1707  u_char *p;
1708  ngx_ssl_ocsp_ctx_t *ctx;
1709 
1710  p = buf;
1711 
1712  if (log->action) {
1713  p = ngx_snprintf(buf, len, " while %s", log->action);
1714  len -= p - buf;
1715  }
1716 
1717  ctx = log->data;
1718 
1719  if (ctx) {
1720  p = ngx_snprintf(p, len, ", responder: %V", &ctx->host);
1721  }
1722 
1723  return p;
1724 }
1725 
1726 
1727 #else
1728 
1729 
1730 ngx_int_t
1732  ngx_str_t *responder, ngx_uint_t verify)
1733 {
1734  ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
1735  "\"ssl_stapling\" ignored, not supported");
1736 
1737  return NGX_OK;
1738 }
1739 
1740 ngx_int_t
1742  ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)
1743 {
1744  return NGX_OK;
1745 }
1746 
1747 
1748 #endif