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
ngx_ssl_stapling(ngx_conf_t * cf,ngx_ssl_t * ssl,ngx_str_t * file,ngx_str_t * responder,ngx_uint_t verify)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
ngx_ssl_stapling_certificate(ngx_conf_t * cf,ngx_ssl_t * ssl,X509 * cert,ngx_str_t * file,ngx_str_t * responder,ngx_uint_t verify)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
ngx_ssl_stapling_file(ngx_conf_t * cf,ngx_ssl_t * ssl,ngx_ssl_stapling_t * staple,ngx_str_t * file)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, "rb");
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
ngx_ssl_stapling_issuer(ngx_conf_t * cf,ngx_ssl_t * ssl,ngx_ssl_stapling_t * staple)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
ngx_ssl_stapling_responder(ngx_conf_t * cf,ngx_ssl_t * ssl,ngx_ssl_stapling_t * staple,ngx_str_t * responder)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
ngx_ssl_stapling_resolver(ngx_conf_t * cf,ngx_ssl_t * ssl,ngx_resolver_t * resolver,ngx_msec_t resolver_timeout)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
ngx_ssl_certificate_status_callback(ngx_ssl_conn_t * ssl_conn,void * data)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
515 if (cert == NULL) {
516 return rc;
517 }
518
519 staple = X509_get_ex_data(cert, ngx_ssl_stapling_index);
520
521 if (staple == NULL) {
522 return rc;
523 }
524
525 if (staple->staple.len
526 && staple->valid >= ngx_time())
527 {
528 /* we have to copy ocsp response as OpenSSL will free it by itself */
529
530 p = OPENSSL_malloc(staple->staple.len);
531 if (p == NULL) {
532 ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "OPENSSL_malloc() failed");
533 return SSL_TLSEXT_ERR_NOACK;
534 }
535
536 ngx_memcpy(p, staple->staple.data, staple->staple.len);
537
538 SSL_set_tlsext_status_ocsp_resp(ssl_conn, p, staple->staple.len);
539
540 rc = SSL_TLSEXT_ERR_OK;
541 }
542
543 ngx_ssl_stapling_update(staple);
544
545 return rc;
546 }
547
548
549 static void
ngx_ssl_stapling_update(ngx_ssl_stapling_t * staple)550 ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple)
551 {
552 ngx_ssl_ocsp_ctx_t *ctx;
553
554 if (staple->host.len == 0
555 || staple->loading || staple->refresh >= ngx_time())
556 {
557 return;
558 }
559
560 staple->loading = 1;
561
562 ctx = ngx_ssl_ocsp_start();
563 if (ctx == NULL) {
564 return;
565 }
566
567 ctx->cert = staple->cert;
568 ctx->issuer = staple->issuer;
569 ctx->name = staple->name;
570
571 ctx->addrs = staple->addrs;
572 ctx->host = staple->host;
573 ctx->uri = staple->uri;
574 ctx->port = staple->port;
575 ctx->timeout = staple->timeout;
576
577 ctx->resolver = staple->resolver;
578 ctx->resolver_timeout = staple->resolver_timeout;
579
580 ctx->handler = ngx_ssl_stapling_ocsp_handler;
581 ctx->data = staple;
582
583 ngx_ssl_ocsp_request(ctx);
584
585 return;
586 }
587
588
589 static void
ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t * ctx)590 ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
591 {
592 #if OPENSSL_VERSION_NUMBER >= 0x0090707fL
593 const
594 #endif
595 u_char *p;
596 int n;
597 size_t len;
598 time_t now, valid;
599 ngx_str_t response;
600 X509_STORE *store;
601 STACK_OF(X509) *chain;
602 OCSP_CERTID *id;
603 OCSP_RESPONSE *ocsp;
604 OCSP_BASICRESP *basic;
605 ngx_ssl_stapling_t *staple;
606 ASN1_GENERALIZEDTIME *thisupdate, *nextupdate;
607
608 staple = ctx->data;
609 now = ngx_time();
610 ocsp = NULL;
611 basic = NULL;
612 id = NULL;
613
614 if (ctx->code != 200) {
615 goto error;
616 }
617
618 /* check the response */
619
620 len = ctx->response->last - ctx->response->pos;
621 p = ctx->response->pos;
622
623 ocsp = d2i_OCSP_RESPONSE(NULL, &p, len);
624 if (ocsp == NULL) {
625 ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
626 "d2i_OCSP_RESPONSE() failed");
627 goto error;
628 }
629
630 n = OCSP_response_status(ocsp);
631
632 if (n != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
633 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
634 "OCSP response not successful (%d: %s)",
635 n, OCSP_response_status_str(n));
636 goto error;
637 }
638
639 basic = OCSP_response_get1_basic(ocsp);
640 if (basic == NULL) {
641 ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
642 "OCSP_response_get1_basic() failed");
643 goto error;
644 }
645
646 store = SSL_CTX_get_cert_store(staple->ssl_ctx);
647 if (store == NULL) {
648 ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
649 "SSL_CTX_get_cert_store() failed");
650 goto error;
651 }
652
653 #ifdef SSL_CTRL_SELECT_CURRENT_CERT
654 /* OpenSSL 1.0.2+ */
655 SSL_CTX_select_current_cert(staple->ssl_ctx, ctx->cert);
656 #endif
657
658 #ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
659 /* OpenSSL 1.0.1+ */
660 SSL_CTX_get_extra_chain_certs(staple->ssl_ctx, &chain);
661 #else
662 chain = staple->ssl_ctx->extra_certs;
663 #endif
664
665 if (OCSP_basic_verify(basic, chain, store,
666 staple->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY)
667 != 1)
668 {
669 ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
670 "OCSP_basic_verify() failed");
671 goto error;
672 }
673
674 id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
675 if (id == NULL) {
676 ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
677 "OCSP_cert_to_id() failed");
678 goto error;
679 }
680
681 if (OCSP_resp_find_status(basic, id, &n, NULL, NULL,
682 &thisupdate, &nextupdate)
683 != 1)
684 {
685 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
686 "certificate status not found in the OCSP response");
687 goto error;
688 }
689
690 if (n != V_OCSP_CERTSTATUS_GOOD) {
691 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
692 "certificate status \"%s\" in the OCSP response",
693 OCSP_cert_status_str(n));
694 goto error;
695 }
696
697 if (OCSP_check_validity(thisupdate, nextupdate, 300, -1) != 1) {
698 ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
699 "OCSP_check_validity() failed");
700 goto error;
701 }
702
703 if (nextupdate) {
704 valid = ngx_ssl_stapling_time(nextupdate);
705 if (valid == (time_t) NGX_ERROR) {
706 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
707 "invalid nextUpdate time in certificate status");
708 goto error;
709 }
710
711 } else {
712 valid = NGX_MAX_TIME_T_VALUE;
713 }
714
715 OCSP_CERTID_free(id);
716 OCSP_BASICRESP_free(basic);
717 OCSP_RESPONSE_free(ocsp);
718
719 id = NULL;
720 basic = NULL;
721 ocsp = NULL;
722
723 /* copy the response to memory not in ctx->pool */
724
725 response.len = len;
726 response.data = ngx_alloc(response.len, ctx->log);
727
728 if (response.data == NULL) {
729 goto error;
730 }
731
732 ngx_memcpy(response.data, ctx->response->pos, response.len);
733
734 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
735 "ssl ocsp response, %s, %uz",
736 OCSP_cert_status_str(n), response.len);
737
738 if (staple->staple.data) {
739 ngx_free(staple->staple.data);
740 }
741
742 staple->staple = response;
743 staple->valid = valid;
744
745 /*
746 * refresh before the response expires,
747 * but not earlier than in 5 minutes, and at least in an hour
748 */
749
750 staple->loading = 0;
751 staple->refresh = ngx_max(ngx_min(valid - 300, now + 3600), now + 300);
752
753 ngx_ssl_ocsp_done(ctx);
754 return;
755
756 error:
757
758 staple->loading = 0;
759 staple->refresh = now + 300;
760
761 if (id) {
762 OCSP_CERTID_free(id);
763 }
764
765 if (basic) {
766 OCSP_BASICRESP_free(basic);
767 }
768
769 if (ocsp) {
770 OCSP_RESPONSE_free(ocsp);
771 }
772
773 ngx_ssl_ocsp_done(ctx);
774 }
775
776
777 static time_t
ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME * asn1time)778 ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time)
779 {
780 BIO *bio;
781 char *value;
782 size_t len;
783 time_t time;
784
785 /*
786 * OpenSSL doesn't provide a way to convert ASN1_GENERALIZEDTIME
787 * into time_t. To do this, we use ASN1_GENERALIZEDTIME_print(),
788 * which uses the "MMM DD HH:MM:SS YYYY [GMT]" format (e.g.,
789 * "Feb 3 00:55:52 2015 GMT"), and parse the result.
790 */
791
792 bio = BIO_new(BIO_s_mem());
793 if (bio == NULL) {
794 return NGX_ERROR;
795 }
796
797 /* fake weekday prepended to match C asctime() format */
798
799 BIO_write(bio, "Tue ", sizeof("Tue ") - 1);
800 ASN1_GENERALIZEDTIME_print(bio, asn1time);
801 len = BIO_get_mem_data(bio, &value);
802
803 time = ngx_parse_http_time((u_char *) value, len);
804
805 BIO_free(bio);
806
807 return time;
808 }
809
810
811 static void
ngx_ssl_stapling_cleanup(void * data)812 ngx_ssl_stapling_cleanup(void *data)
813 {
814 ngx_ssl_stapling_t *staple = data;
815
816 if (staple->issuer) {
817 X509_free(staple->issuer);
818 }
819
820 if (staple->staple.data) {
821 ngx_free(staple->staple.data);
822 }
823 }
824
825
826 static ngx_ssl_ocsp_ctx_t *
ngx_ssl_ocsp_start(void)827 ngx_ssl_ocsp_start(void)
828 {
829 ngx_log_t *log;
830 ngx_pool_t *pool;
831 ngx_ssl_ocsp_ctx_t *ctx;
832
833 pool = ngx_create_pool(2048, ngx_cycle->log);
834 if (pool == NULL) {
835 return NULL;
836 }
837
838 ctx = ngx_pcalloc(pool, sizeof(ngx_ssl_ocsp_ctx_t));
839 if (ctx == NULL) {
840 ngx_destroy_pool(pool);
841 return NULL;
842 }
843
844 log = ngx_palloc(pool, sizeof(ngx_log_t));
845 if (log == NULL) {
846 ngx_destroy_pool(pool);
847 return NULL;
848 }
849
850 ctx->pool = pool;
851
852 *log = *ctx->pool->log;
853
854 ctx->pool->log = log;
855 ctx->log = log;
856
857 log->handler = ngx_ssl_ocsp_log_error;
858 log->data = ctx;
859 log->action = "requesting certificate status";
860
861 return ctx;
862 }
863
864
865 static void
ngx_ssl_ocsp_done(ngx_ssl_ocsp_ctx_t * ctx)866 ngx_ssl_ocsp_done(ngx_ssl_ocsp_ctx_t *ctx)
867 {
868 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
869 "ssl ocsp done");
870
871 if (ctx->peer.connection) {
872 ngx_close_connection(ctx->peer.connection);
873 }
874
875 ngx_destroy_pool(ctx->pool);
876 }
877
878
879 static void
ngx_ssl_ocsp_error(ngx_ssl_ocsp_ctx_t * ctx)880 ngx_ssl_ocsp_error(ngx_ssl_ocsp_ctx_t *ctx)
881 {
882 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
883 "ssl ocsp error");
884
885 ctx->code = 0;
886 ctx->handler(ctx);
887 }
888
889
890 static void
ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t * ctx)891 ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx)
892 {
893 ngx_resolver_ctx_t *resolve, temp;
894
895 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
896 "ssl ocsp request");
897
898 if (ngx_ssl_ocsp_create_request(ctx) != NGX_OK) {
899 ngx_ssl_ocsp_error(ctx);
900 return;
901 }
902
903 if (ctx->resolver) {
904 /* resolve OCSP responder hostname */
905
906 temp.name = ctx->host;
907
908 resolve = ngx_resolve_start(ctx->resolver, &temp);
909 if (resolve == NULL) {
910 ngx_ssl_ocsp_error(ctx);
911 return;
912 }
913
914 if (resolve == NGX_NO_RESOLVER) {
915 ngx_log_error(NGX_LOG_WARN, ctx->log, 0,
916 "no resolver defined to resolve %V", &ctx->host);
917 goto connect;
918 }
919
920 resolve->name = ctx->host;
921 resolve->handler = ngx_ssl_ocsp_resolve_handler;
922 resolve->data = ctx;
923 resolve->timeout = ctx->resolver_timeout;
924
925 if (ngx_resolve_name(resolve) != NGX_OK) {
926 ngx_ssl_ocsp_error(ctx);
927 return;
928 }
929
930 return;
931 }
932
933 connect:
934
935 ngx_ssl_ocsp_connect(ctx);
936 }
937
938
939 static void
ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t * resolve)940 ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve)
941 {
942 ngx_ssl_ocsp_ctx_t *ctx = resolve->data;
943
944 u_char *p;
945 size_t len;
946 socklen_t socklen;
947 ngx_uint_t i;
948 struct sockaddr *sockaddr;
949
950 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
951 "ssl ocsp resolve handler");
952
953 if (resolve->state) {
954 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
955 "%V could not be resolved (%i: %s)",
956 &resolve->name, resolve->state,
957 ngx_resolver_strerror(resolve->state));
958 goto failed;
959 }
960
961 #if (NGX_DEBUG)
962 {
963 u_char text[NGX_SOCKADDR_STRLEN];
964 ngx_str_t addr;
965
966 addr.data = text;
967
968 for (i = 0; i < resolve->naddrs; i++) {
969 addr.len = ngx_sock_ntop(resolve->addrs[i].sockaddr,
970 resolve->addrs[i].socklen,
971 text, NGX_SOCKADDR_STRLEN, 0);
972
973 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
974 "name was resolved to %V", &addr);
975
976 }
977 }
978 #endif
979
980 ctx->naddrs = resolve->naddrs;
981 ctx->addrs = ngx_pcalloc(ctx->pool, ctx->naddrs * sizeof(ngx_addr_t));
982
983 if (ctx->addrs == NULL) {
984 goto failed;
985 }
986
987 for (i = 0; i < resolve->naddrs; i++) {
988
989 socklen = resolve->addrs[i].socklen;
990
991 sockaddr = ngx_palloc(ctx->pool, socklen);
992 if (sockaddr == NULL) {
993 goto failed;
994 }
995
996 ngx_memcpy(sockaddr, resolve->addrs[i].sockaddr, socklen);
997 ngx_inet_set_port(sockaddr, ctx->port);
998
999 ctx->addrs[i].sockaddr = sockaddr;
1000 ctx->addrs[i].socklen = socklen;
1001
1002 p = ngx_pnalloc(ctx->pool, NGX_SOCKADDR_STRLEN);
1003 if (p == NULL) {
1004 goto failed;
1005 }
1006
1007 len = ngx_sock_ntop(sockaddr, socklen, p, NGX_SOCKADDR_STRLEN, 1);
1008
1009 ctx->addrs[i].name.len = len;
1010 ctx->addrs[i].name.data = p;
1011 }
1012
1013 ngx_resolve_name_done(resolve);
1014
1015 ngx_ssl_ocsp_connect(ctx);
1016 return;
1017
1018 failed:
1019
1020 ngx_resolve_name_done(resolve);
1021 ngx_ssl_ocsp_error(ctx);
1022 }
1023
1024
1025 static void
ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t * ctx)1026 ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx)
1027 {
1028 ngx_int_t rc;
1029
1030 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1031 "ssl ocsp connect");
1032
1033 /* TODO: use all ip addresses */
1034
1035 ctx->peer.sockaddr = ctx->addrs[0].sockaddr;
1036 ctx->peer.socklen = ctx->addrs[0].socklen;
1037 ctx->peer.name = &ctx->addrs[0].name;
1038 ctx->peer.get = ngx_event_get_peer;
1039 ctx->peer.log = ctx->log;
1040 ctx->peer.log_error = NGX_ERROR_ERR;
1041
1042 rc = ngx_event_connect_peer(&ctx->peer);
1043
1044 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1045 "ssl ocsp connect peer done");
1046
1047 if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
1048 ngx_ssl_ocsp_error(ctx);
1049 return;
1050 }
1051
1052 ctx->peer.connection->data = ctx;
1053 ctx->peer.connection->pool = ctx->pool;
1054
1055 ctx->peer.connection->read->handler = ngx_ssl_ocsp_read_handler;
1056 ctx->peer.connection->write->handler = ngx_ssl_ocsp_write_handler;
1057
1058 ctx->process = ngx_ssl_ocsp_process_status_line;
1059
1060 ngx_add_timer(ctx->peer.connection->read, ctx->timeout);
1061 ngx_add_timer(ctx->peer.connection->write, ctx->timeout);
1062
1063 if (rc == NGX_OK) {
1064 ngx_ssl_ocsp_write_handler(ctx->peer.connection->write);
1065 return;
1066 }
1067 }
1068
1069
1070 static void
ngx_ssl_ocsp_write_handler(ngx_event_t * wev)1071 ngx_ssl_ocsp_write_handler(ngx_event_t *wev)
1072 {
1073 ssize_t n, size;
1074 ngx_connection_t *c;
1075 ngx_ssl_ocsp_ctx_t *ctx;
1076
1077 c = wev->data;
1078 ctx = c->data;
1079
1080 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, wev->log, 0,
1081 "ssl ocsp write handler");
1082
1083 if (wev->timedout) {
1084 ngx_log_error(NGX_LOG_ERR, wev->log, NGX_ETIMEDOUT,
1085 "OCSP responder timed out");
1086 ngx_ssl_ocsp_error(ctx);
1087 return;
1088 }
1089
1090 size = ctx->request->last - ctx->request->pos;
1091
1092 n = ngx_send(c, ctx->request->pos, size);
1093
1094 if (n == NGX_ERROR) {
1095 ngx_ssl_ocsp_error(ctx);
1096 return;
1097 }
1098
1099 if (n > 0) {
1100 ctx->request->pos += n;
1101
1102 if (n == size) {
1103 wev->handler = ngx_ssl_ocsp_dummy_handler;
1104
1105 if (wev->timer_set) {
1106 ngx_del_timer(wev);
1107 }
1108
1109 if (ngx_handle_write_event(wev, 0) != NGX_OK) {
1110 ngx_ssl_ocsp_error(ctx);
1111 }
1112
1113 return;
1114 }
1115 }
1116
1117 if (!wev->timer_set) {
1118 ngx_add_timer(wev, ctx->timeout);
1119 }
1120 }
1121
1122
1123 static void
ngx_ssl_ocsp_read_handler(ngx_event_t * rev)1124 ngx_ssl_ocsp_read_handler(ngx_event_t *rev)
1125 {
1126 ssize_t n, size;
1127 ngx_int_t rc;
1128 ngx_connection_t *c;
1129 ngx_ssl_ocsp_ctx_t *ctx;
1130
1131 c = rev->data;
1132 ctx = c->data;
1133
1134 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, rev->log, 0,
1135 "ssl ocsp read handler");
1136
1137 if (rev->timedout) {
1138 ngx_log_error(NGX_LOG_ERR, rev->log, NGX_ETIMEDOUT,
1139 "OCSP responder timed out");
1140 ngx_ssl_ocsp_error(ctx);
1141 return;
1142 }
1143
1144 if (ctx->response == NULL) {
1145 ctx->response = ngx_create_temp_buf(ctx->pool, 16384);
1146 if (ctx->response == NULL) {
1147 ngx_ssl_ocsp_error(ctx);
1148 return;
1149 }
1150 }
1151
1152 for ( ;; ) {
1153
1154 size = ctx->response->end - ctx->response->last;
1155
1156 n = ngx_recv(c, ctx->response->last, size);
1157
1158 if (n > 0) {
1159 ctx->response->last += n;
1160
1161 rc = ctx->process(ctx);
1162
1163 if (rc == NGX_ERROR) {
1164 ngx_ssl_ocsp_error(ctx);
1165 return;
1166 }
1167
1168 continue;
1169 }
1170
1171 if (n == NGX_AGAIN) {
1172
1173 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
1174 ngx_ssl_ocsp_error(ctx);
1175 }
1176
1177 return;
1178 }
1179
1180 break;
1181 }
1182
1183 ctx->done = 1;
1184
1185 rc = ctx->process(ctx);
1186
1187 if (rc == NGX_DONE) {
1188 /* ctx->handler() was called */
1189 return;
1190 }
1191
1192 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1193 "OCSP responder prematurely closed connection");
1194
1195 ngx_ssl_ocsp_error(ctx);
1196 }
1197
1198
1199 static void
ngx_ssl_ocsp_dummy_handler(ngx_event_t * ev)1200 ngx_ssl_ocsp_dummy_handler(ngx_event_t *ev)
1201 {
1202 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0,
1203 "ssl ocsp dummy handler");
1204 }
1205
1206
1207 static ngx_int_t
ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t * ctx)1208 ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx)
1209 {
1210 int len;
1211 u_char *p;
1212 uintptr_t escape;
1213 ngx_str_t binary, base64;
1214 ngx_buf_t *b;
1215 OCSP_CERTID *id;
1216 OCSP_REQUEST *ocsp;
1217
1218 ocsp = OCSP_REQUEST_new();
1219 if (ocsp == NULL) {
1220 ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1221 "OCSP_REQUEST_new() failed");
1222 return NGX_ERROR;
1223 }
1224
1225 id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
1226 if (id == NULL) {
1227 ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1228 "OCSP_cert_to_id() failed");
1229 goto failed;
1230 }
1231
1232 if (OCSP_request_add0_id(ocsp, id) == NULL) {
1233 ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1234 "OCSP_request_add0_id() failed");
1235 OCSP_CERTID_free(id);
1236 goto failed;
1237 }
1238
1239 len = i2d_OCSP_REQUEST(ocsp, NULL);
1240 if (len <= 0) {
1241 ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1242 "i2d_OCSP_REQUEST() failed");
1243 goto failed;
1244 }
1245
1246 binary.len = len;
1247 binary.data = ngx_palloc(ctx->pool, len);
1248 if (binary.data == NULL) {
1249 goto failed;
1250 }
1251
1252 p = binary.data;
1253 len = i2d_OCSP_REQUEST(ocsp, &p);
1254 if (len <= 0) {
1255 ngx_ssl_error(NGX_LOG_EMERG, ctx->log, 0,
1256 "i2d_OCSP_REQUEST() failed");
1257 goto failed;
1258 }
1259
1260 base64.len = ngx_base64_encoded_length(binary.len);
1261 base64.data = ngx_palloc(ctx->pool, base64.len);
1262 if (base64.data == NULL) {
1263 goto failed;
1264 }
1265
1266 ngx_encode_base64(&base64, &binary);
1267
1268 escape = ngx_escape_uri(NULL, base64.data, base64.len,
1269 NGX_ESCAPE_URI_COMPONENT);
1270
1271 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1272 "ssl ocsp request length %z, escape %d",
1273 base64.len, (int) escape);
1274
1275 len = sizeof("GET ") - 1 + ctx->uri.len + sizeof("/") - 1
1276 + base64.len + 2 * escape + sizeof(" HTTP/1.0" CRLF) - 1
1277 + sizeof("Host: ") - 1 + ctx->host.len + sizeof(CRLF) - 1
1278 + sizeof(CRLF) - 1;
1279
1280 b = ngx_create_temp_buf(ctx->pool, len);
1281 if (b == NULL) {
1282 goto failed;
1283 }
1284
1285 p = b->last;
1286
1287 p = ngx_cpymem(p, "GET ", sizeof("GET ") - 1);
1288 p = ngx_cpymem(p, ctx->uri.data, ctx->uri.len);
1289
1290 if (ctx->uri.data[ctx->uri.len - 1] != '/') {
1291 *p++ = '/';
1292 }
1293
1294 if (escape == 0) {
1295 p = ngx_cpymem(p, base64.data, base64.len);
1296
1297 } else {
1298 p = (u_char *) ngx_escape_uri(p, base64.data, base64.len,
1299 NGX_ESCAPE_URI_COMPONENT);
1300 }
1301
1302 p = ngx_cpymem(p, " HTTP/1.0" CRLF, sizeof(" HTTP/1.0" CRLF) - 1);
1303 p = ngx_cpymem(p, "Host: ", sizeof("Host: ") - 1);
1304 p = ngx_cpymem(p, ctx->host.data, ctx->host.len);
1305 *p++ = CR; *p++ = LF;
1306
1307 /* add "\r\n" at the header end */
1308 *p++ = CR; *p++ = LF;
1309
1310 b->last = p;
1311 ctx->request = b;
1312
1313 OCSP_REQUEST_free(ocsp);
1314
1315 return NGX_OK;
1316
1317 failed:
1318
1319 OCSP_REQUEST_free(ocsp);
1320
1321 return NGX_ERROR;
1322 }
1323
1324
1325 static ngx_int_t
ngx_ssl_ocsp_process_status_line(ngx_ssl_ocsp_ctx_t * ctx)1326 ngx_ssl_ocsp_process_status_line(ngx_ssl_ocsp_ctx_t *ctx)
1327 {
1328 ngx_int_t rc;
1329
1330 rc = ngx_ssl_ocsp_parse_status_line(ctx);
1331
1332 if (rc == NGX_OK) {
1333 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1334 "ssl ocsp status %ui \"%*s\"",
1335 ctx->code,
1336 ctx->header_end - ctx->header_start,
1337 ctx->header_start);
1338
1339 ctx->process = ngx_ssl_ocsp_process_headers;
1340 return ctx->process(ctx);
1341 }
1342
1343 if (rc == NGX_AGAIN) {
1344 return NGX_AGAIN;
1345 }
1346
1347 /* rc == NGX_ERROR */
1348
1349 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1350 "OCSP responder sent invalid response");
1351
1352 return NGX_ERROR;
1353 }
1354
1355
1356 static ngx_int_t
ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t * ctx)1357 ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t *ctx)
1358 {
1359 u_char ch;
1360 u_char *p;
1361 ngx_buf_t *b;
1362 enum {
1363 sw_start = 0,
1364 sw_H,
1365 sw_HT,
1366 sw_HTT,
1367 sw_HTTP,
1368 sw_first_major_digit,
1369 sw_major_digit,
1370 sw_first_minor_digit,
1371 sw_minor_digit,
1372 sw_status,
1373 sw_space_after_status,
1374 sw_status_text,
1375 sw_almost_done
1376 } state;
1377
1378 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1379 "ssl ocsp process status line");
1380
1381 state = ctx->state;
1382 b = ctx->response;
1383
1384 for (p = b->pos; p < b->last; p++) {
1385 ch = *p;
1386
1387 switch (state) {
1388
1389 /* "HTTP/" */
1390 case sw_start:
1391 switch (ch) {
1392 case 'H':
1393 state = sw_H;
1394 break;
1395 default:
1396 return NGX_ERROR;
1397 }
1398 break;
1399
1400 case sw_H:
1401 switch (ch) {
1402 case 'T':
1403 state = sw_HT;
1404 break;
1405 default:
1406 return NGX_ERROR;
1407 }
1408 break;
1409
1410 case sw_HT:
1411 switch (ch) {
1412 case 'T':
1413 state = sw_HTT;
1414 break;
1415 default:
1416 return NGX_ERROR;
1417 }
1418 break;
1419
1420 case sw_HTT:
1421 switch (ch) {
1422 case 'P':
1423 state = sw_HTTP;
1424 break;
1425 default:
1426 return NGX_ERROR;
1427 }
1428 break;
1429
1430 case sw_HTTP:
1431 switch (ch) {
1432 case '/':
1433 state = sw_first_major_digit;
1434 break;
1435 default:
1436 return NGX_ERROR;
1437 }
1438 break;
1439
1440 /* the first digit of major HTTP version */
1441 case sw_first_major_digit:
1442 if (ch < '1' || ch > '9') {
1443 return NGX_ERROR;
1444 }
1445
1446 state = sw_major_digit;
1447 break;
1448
1449 /* the major HTTP version or dot */
1450 case sw_major_digit:
1451 if (ch == '.') {
1452 state = sw_first_minor_digit;
1453 break;
1454 }
1455
1456 if (ch < '0' || ch > '9') {
1457 return NGX_ERROR;
1458 }
1459
1460 break;
1461
1462 /* the first digit of minor HTTP version */
1463 case sw_first_minor_digit:
1464 if (ch < '0' || ch > '9') {
1465 return NGX_ERROR;
1466 }
1467
1468 state = sw_minor_digit;
1469 break;
1470
1471 /* the minor HTTP version or the end of the request line */
1472 case sw_minor_digit:
1473 if (ch == ' ') {
1474 state = sw_status;
1475 break;
1476 }
1477
1478 if (ch < '0' || ch > '9') {
1479 return NGX_ERROR;
1480 }
1481
1482 break;
1483
1484 /* HTTP status code */
1485 case sw_status:
1486 if (ch == ' ') {
1487 break;
1488 }
1489
1490 if (ch < '0' || ch > '9') {
1491 return NGX_ERROR;
1492 }
1493
1494 ctx->code = ctx->code * 10 + (ch - '0');
1495
1496 if (++ctx->count == 3) {
1497 state = sw_space_after_status;
1498 ctx->header_start = p - 2;
1499 }
1500
1501 break;
1502
1503 /* space or end of line */
1504 case sw_space_after_status:
1505 switch (ch) {
1506 case ' ':
1507 state = sw_status_text;
1508 break;
1509 case '.': /* IIS may send 403.1, 403.2, etc */
1510 state = sw_status_text;
1511 break;
1512 case CR:
1513 state = sw_almost_done;
1514 break;
1515 case LF:
1516 ctx->header_end = p;
1517 goto done;
1518 default:
1519 return NGX_ERROR;
1520 }
1521 break;
1522
1523 /* any text until end of line */
1524 case sw_status_text:
1525 switch (ch) {
1526 case CR:
1527 state = sw_almost_done;
1528 break;
1529 case LF:
1530 ctx->header_end = p;
1531 goto done;
1532 }
1533 break;
1534
1535 /* end of status line */
1536 case sw_almost_done:
1537 switch (ch) {
1538 case LF:
1539 ctx->header_end = p - 1;
1540 goto done;
1541 default:
1542 return NGX_ERROR;
1543 }
1544 }
1545 }
1546
1547 b->pos = p;
1548 ctx->state = state;
1549
1550 return NGX_AGAIN;
1551
1552 done:
1553
1554 b->pos = p + 1;
1555 ctx->state = sw_start;
1556
1557 return NGX_OK;
1558 }
1559
1560
1561 static ngx_int_t
ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t * ctx)1562 ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx)
1563 {
1564 size_t len;
1565 ngx_int_t rc;
1566
1567 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1568 "ssl ocsp process headers");
1569
1570 for ( ;; ) {
1571 rc = ngx_ssl_ocsp_parse_header_line(ctx);
1572
1573 if (rc == NGX_OK) {
1574
1575 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1576 "ssl ocsp header \"%*s: %*s\"",
1577 ctx->header_name_end - ctx->header_name_start,
1578 ctx->header_name_start,
1579 ctx->header_end - ctx->header_start,
1580 ctx->header_start);
1581
1582 len = ctx->header_name_end - ctx->header_name_start;
1583
1584 if (len == sizeof("Content-Type") - 1
1585 && ngx_strncasecmp(ctx->header_name_start,
1586 (u_char *) "Content-Type",
1587 sizeof("Content-Type") - 1)
1588 == 0)
1589 {
1590 len = ctx->header_end - ctx->header_start;
1591
1592 if (len != sizeof("application/ocsp-response") - 1
1593 || ngx_strncasecmp(ctx->header_start,
1594 (u_char *) "application/ocsp-response",
1595 sizeof("application/ocsp-response") - 1)
1596 != 0)
1597 {
1598 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1599 "OCSP responder sent invalid "
1600 "\"Content-Type\" header: \"%*s\"",
1601 ctx->header_end - ctx->header_start,
1602 ctx->header_start);
1603 return NGX_ERROR;
1604 }
1605
1606 continue;
1607 }
1608
1609 /* TODO: honor Content-Length */
1610
1611 continue;
1612 }
1613
1614 if (rc == NGX_DONE) {
1615 break;
1616 }
1617
1618 if (rc == NGX_AGAIN) {
1619 return NGX_AGAIN;
1620 }
1621
1622 /* rc == NGX_ERROR */
1623
1624 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1625 "OCSP responder sent invalid response");
1626
1627 return NGX_ERROR;
1628 }
1629
1630 ctx->process = ngx_ssl_ocsp_process_body;
1631 return ctx->process(ctx);
1632 }
1633
1634
1635 static ngx_int_t
ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t * ctx)1636 ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx)
1637 {
1638 u_char c, ch, *p;
1639 enum {
1640 sw_start = 0,
1641 sw_name,
1642 sw_space_before_value,
1643 sw_value,
1644 sw_space_after_value,
1645 sw_almost_done,
1646 sw_header_almost_done
1647 } state;
1648
1649 state = ctx->state;
1650
1651 for (p = ctx->response->pos; p < ctx->response->last; p++) {
1652 ch = *p;
1653
1654 #if 0
1655 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1656 "s:%d in:'%02Xd:%c'", state, ch, ch);
1657 #endif
1658
1659 switch (state) {
1660
1661 /* first char */
1662 case sw_start:
1663
1664 switch (ch) {
1665 case CR:
1666 ctx->header_end = p;
1667 state = sw_header_almost_done;
1668 break;
1669 case LF:
1670 ctx->header_end = p;
1671 goto header_done;
1672 default:
1673 state = sw_name;
1674 ctx->header_name_start = p;
1675
1676 c = (u_char) (ch | 0x20);
1677 if (c >= 'a' && c <= 'z') {
1678 break;
1679 }
1680
1681 if (ch >= '0' && ch <= '9') {
1682 break;
1683 }
1684
1685 return NGX_ERROR;
1686 }
1687 break;
1688
1689 /* header name */
1690 case sw_name:
1691 c = (u_char) (ch | 0x20);
1692 if (c >= 'a' && c <= 'z') {
1693 break;
1694 }
1695
1696 if (ch == ':') {
1697 ctx->header_name_end = p;
1698 state = sw_space_before_value;
1699 break;
1700 }
1701
1702 if (ch == '-') {
1703 break;
1704 }
1705
1706 if (ch >= '0' && ch <= '9') {
1707 break;
1708 }
1709
1710 if (ch == CR) {
1711 ctx->header_name_end = p;
1712 ctx->header_start = p;
1713 ctx->header_end = p;
1714 state = sw_almost_done;
1715 break;
1716 }
1717
1718 if (ch == LF) {
1719 ctx->header_name_end = p;
1720 ctx->header_start = p;
1721 ctx->header_end = p;
1722 goto done;
1723 }
1724
1725 return NGX_ERROR;
1726
1727 /* space* before header value */
1728 case sw_space_before_value:
1729 switch (ch) {
1730 case ' ':
1731 break;
1732 case CR:
1733 ctx->header_start = p;
1734 ctx->header_end = p;
1735 state = sw_almost_done;
1736 break;
1737 case LF:
1738 ctx->header_start = p;
1739 ctx->header_end = p;
1740 goto done;
1741 default:
1742 ctx->header_start = p;
1743 state = sw_value;
1744 break;
1745 }
1746 break;
1747
1748 /* header value */
1749 case sw_value:
1750 switch (ch) {
1751 case ' ':
1752 ctx->header_end = p;
1753 state = sw_space_after_value;
1754 break;
1755 case CR:
1756 ctx->header_end = p;
1757 state = sw_almost_done;
1758 break;
1759 case LF:
1760 ctx->header_end = p;
1761 goto done;
1762 }
1763 break;
1764
1765 /* space* before end of header line */
1766 case sw_space_after_value:
1767 switch (ch) {
1768 case ' ':
1769 break;
1770 case CR:
1771 state = sw_almost_done;
1772 break;
1773 case LF:
1774 goto done;
1775 default:
1776 state = sw_value;
1777 break;
1778 }
1779 break;
1780
1781 /* end of header line */
1782 case sw_almost_done:
1783 switch (ch) {
1784 case LF:
1785 goto done;
1786 default:
1787 return NGX_ERROR;
1788 }
1789
1790 /* end of header */
1791 case sw_header_almost_done:
1792 switch (ch) {
1793 case LF:
1794 goto header_done;
1795 default:
1796 return NGX_ERROR;
1797 }
1798 }
1799 }
1800
1801 ctx->response->pos = p;
1802 ctx->state = state;
1803
1804 return NGX_AGAIN;
1805
1806 done:
1807
1808 ctx->response->pos = p + 1;
1809 ctx->state = sw_start;
1810
1811 return NGX_OK;
1812
1813 header_done:
1814
1815 ctx->response->pos = p + 1;
1816 ctx->state = sw_start;
1817
1818 return NGX_DONE;
1819 }
1820
1821
1822 static ngx_int_t
ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t * ctx)1823 ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx)
1824 {
1825 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1826 "ssl ocsp process body");
1827
1828 if (ctx->done) {
1829 ctx->handler(ctx);
1830 return NGX_DONE;
1831 }
1832
1833 return NGX_AGAIN;
1834 }
1835
1836
1837 static u_char *
ngx_ssl_ocsp_log_error(ngx_log_t * log,u_char * buf,size_t len)1838 ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len)
1839 {
1840 u_char *p;
1841 ngx_ssl_ocsp_ctx_t *ctx;
1842
1843 p = buf;
1844
1845 if (log->action) {
1846 p = ngx_snprintf(buf, len, " while %s", log->action);
1847 len -= p - buf;
1848 buf = p;
1849 }
1850
1851 ctx = log->data;
1852
1853 if (ctx) {
1854 p = ngx_snprintf(buf, len, ", responder: %V", &ctx->host);
1855 len -= p - buf;
1856 buf = p;
1857 }
1858
1859 if (ctx && ctx->peer.name) {
1860 p = ngx_snprintf(buf, len, ", peer: %V", ctx->peer.name);
1861 len -= p - buf;
1862 buf = p;
1863 }
1864
1865 if (ctx && ctx->name) {
1866 p = ngx_snprintf(buf, len, ", certificate: \"%s\"", ctx->name);
1867 len -= p - buf;
1868 buf = p;
1869 }
1870
1871 return p;
1872 }
1873
1874
1875 #else
1876
1877
1878 ngx_int_t
ngx_ssl_stapling(ngx_conf_t * cf,ngx_ssl_t * ssl,ngx_str_t * file,ngx_str_t * responder,ngx_uint_t verify)1879 ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file,
1880 ngx_str_t *responder, ngx_uint_t verify)
1881 {
1882 ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
1883 "\"ssl_stapling\" ignored, not supported");
1884
1885 return NGX_OK;
1886 }
1887
1888
1889 ngx_int_t
ngx_ssl_stapling_resolver(ngx_conf_t * cf,ngx_ssl_t * ssl,ngx_resolver_t * resolver,ngx_msec_t resolver_timeout)1890 ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
1891 ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)
1892 {
1893 return NGX_OK;
1894 }
1895
1896
1897 #endif
1898