comparison src/event/ngx_event_openssl_stapling.c @ 4875:386a06a22c40

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