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