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_uint_t                   naddrs;
26     ngx_str_t                    host;
27     ngx_str_t                    uri;
28     in_port_t                    port;
29 
30     SSL_CTX                     *ssl_ctx;
31 
32     X509                        *cert;
33     X509                        *issuer;
34     STACK_OF(X509)              *chain;
35 
36     u_char                      *name;
37 
38     time_t                       valid;
39     time_t                       refresh;
40 
41     unsigned                     verify:1;
42     unsigned                     loading:1;
43 } ngx_ssl_stapling_t;
44 
45 
46 typedef struct {
47     ngx_addr_t                  *addrs;
48     ngx_uint_t                   naddrs;
49 
50     ngx_str_t                    host;
51     ngx_str_t                    uri;
52     in_port_t                    port;
53     ngx_uint_t                   depth;
54 
55     ngx_shm_zone_t              *shm_zone;
56 
57     ngx_resolver_t              *resolver;
58     ngx_msec_t                   resolver_timeout;
59 } ngx_ssl_ocsp_conf_t;
60 
61 
62 typedef struct {
63     ngx_rbtree_t                 rbtree;
64     ngx_rbtree_node_t            sentinel;
65     ngx_queue_t                  expire_queue;
66 } ngx_ssl_ocsp_cache_t;
67 
68 
69 typedef struct {
70     ngx_str_node_t               node;
71     ngx_queue_t                  queue;
72     int                          status;
73     time_t                       valid;
74 } ngx_ssl_ocsp_cache_node_t;
75 
76 
77 typedef struct ngx_ssl_ocsp_ctx_s  ngx_ssl_ocsp_ctx_t;
78 
79 
80 struct ngx_ssl_ocsp_s {
81     STACK_OF(X509)              *certs;
82     ngx_uint_t                   ncert;
83 
84     int                          cert_status;
85     ngx_int_t                    status;
86 
87     ngx_ssl_ocsp_conf_t         *conf;
88     ngx_ssl_ocsp_ctx_t          *ctx;
89 };
90 
91 
92 struct ngx_ssl_ocsp_ctx_s {
93     SSL_CTX                     *ssl_ctx;
94 
95     X509                        *cert;
96     X509                        *issuer;
97     STACK_OF(X509)              *chain;
98 
99     int                          status;
100     time_t                       valid;
101 
102     u_char                      *name;
103 
104     ngx_uint_t                   naddrs;
105     ngx_uint_t                   naddr;
106 
107     ngx_addr_t                  *addrs;
108     ngx_str_t                    host;
109     ngx_str_t                    uri;
110     in_port_t                    port;
111 
112     ngx_resolver_t              *resolver;
113     ngx_msec_t                   resolver_timeout;
114 
115     ngx_msec_t                   timeout;
116 
117     void                       (*handler)(ngx_ssl_ocsp_ctx_t *ctx);
118     void                        *data;
119 
120     ngx_str_t                    key;
121     ngx_buf_t                   *request;
122     ngx_buf_t                   *response;
123     ngx_peer_connection_t        peer;
124 
125     ngx_shm_zone_t              *shm_zone;
126 
127     ngx_int_t                  (*process)(ngx_ssl_ocsp_ctx_t *ctx);
128 
129     ngx_uint_t                   state;
130 
131     ngx_uint_t                   code;
132     ngx_uint_t                   count;
133     ngx_uint_t                   flags;
134     ngx_uint_t                   done;
135 
136     u_char                      *header_name_start;
137     u_char                      *header_name_end;
138     u_char                      *header_start;
139     u_char                      *header_end;
140 
141     ngx_pool_t                  *pool;
142     ngx_log_t                   *log;
143 };
144 
145 
146 static ngx_int_t ngx_ssl_stapling_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl,
147     X509 *cert, ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify);
148 static ngx_int_t ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl,
149     ngx_ssl_stapling_t *staple, ngx_str_t *file);
150 static ngx_int_t ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl,
151     ngx_ssl_stapling_t *staple);
152 static ngx_int_t ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl,
153     ngx_ssl_stapling_t *staple, ngx_str_t *responder);
154 
155 static int ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn,
156     void *data);
157 static void ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple);
158 static void ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx);
159 
160 static time_t ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time);
161 
162 static void ngx_ssl_stapling_cleanup(void *data);
163 
164 static void ngx_ssl_ocsp_validate_next(ngx_connection_t *c);
165 static void ngx_ssl_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx);
166 static ngx_int_t ngx_ssl_ocsp_responder(ngx_connection_t *c,
167     ngx_ssl_ocsp_ctx_t *ctx);
168 
169 static ngx_ssl_ocsp_ctx_t *ngx_ssl_ocsp_start(ngx_log_t *log);
170 static void ngx_ssl_ocsp_done(ngx_ssl_ocsp_ctx_t *ctx);
171 static void ngx_ssl_ocsp_next(ngx_ssl_ocsp_ctx_t *ctx);
172 static void ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx);
173 static void ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve);
174 static void ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx);
175 static void ngx_ssl_ocsp_write_handler(ngx_event_t *wev);
176 static void ngx_ssl_ocsp_read_handler(ngx_event_t *rev);
177 static void ngx_ssl_ocsp_dummy_handler(ngx_event_t *ev);
178 
179 static ngx_int_t ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx);
180 static ngx_int_t ngx_ssl_ocsp_process_status_line(ngx_ssl_ocsp_ctx_t *ctx);
181 static ngx_int_t ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t *ctx);
182 static ngx_int_t ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx);
183 static ngx_int_t ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx);
184 static ngx_int_t ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx);
185 static ngx_int_t ngx_ssl_ocsp_verify(ngx_ssl_ocsp_ctx_t *ctx);
186 
187 static ngx_int_t ngx_ssl_ocsp_cache_lookup(ngx_ssl_ocsp_ctx_t *ctx);
188 static ngx_int_t ngx_ssl_ocsp_cache_store(ngx_ssl_ocsp_ctx_t *ctx);
189 static ngx_int_t ngx_ssl_ocsp_create_key(ngx_ssl_ocsp_ctx_t *ctx);
190 
191 static u_char *ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len);
192 
193 
194 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)195 ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file,
196     ngx_str_t *responder, ngx_uint_t verify)
197 {
198     X509  *cert;
199 
200     for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
201          cert;
202          cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index))
203     {
204         if (ngx_ssl_stapling_certificate(cf, ssl, cert, file, responder, verify)
205             != NGX_OK)
206         {
207             return NGX_ERROR;
208         }
209     }
210 
211     SSL_CTX_set_tlsext_status_cb(ssl->ctx, ngx_ssl_certificate_status_callback);
212 
213     return NGX_OK;
214 }
215 
216 
217 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)218 ngx_ssl_stapling_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, X509 *cert,
219     ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify)
220 {
221     ngx_int_t            rc;
222     ngx_pool_cleanup_t  *cln;
223     ngx_ssl_stapling_t  *staple;
224 
225     staple = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_stapling_t));
226     if (staple == NULL) {
227         return NGX_ERROR;
228     }
229 
230     cln = ngx_pool_cleanup_add(cf->pool, 0);
231     if (cln == NULL) {
232         return NGX_ERROR;
233     }
234 
235     cln->handler = ngx_ssl_stapling_cleanup;
236     cln->data = staple;
237 
238     if (X509_set_ex_data(cert, ngx_ssl_stapling_index, staple) == 0) {
239         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed");
240         return NGX_ERROR;
241     }
242 
243 #ifdef SSL_CTRL_SELECT_CURRENT_CERT
244     /* OpenSSL 1.0.2+ */
245     SSL_CTX_select_current_cert(ssl->ctx, cert);
246 #endif
247 
248 #ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
249     /* OpenSSL 1.0.1+ */
250     SSL_CTX_get_extra_chain_certs(ssl->ctx, &staple->chain);
251 #else
252     staple->chain = ssl->ctx->extra_certs;
253 #endif
254 
255     staple->ssl_ctx = ssl->ctx;
256     staple->timeout = 60000;
257     staple->verify = verify;
258     staple->cert = cert;
259     staple->name = X509_get_ex_data(staple->cert,
260                                     ngx_ssl_certificate_name_index);
261 
262     if (file->len) {
263         /* use OCSP response from the file */
264 
265         if (ngx_ssl_stapling_file(cf, ssl, staple, file) != NGX_OK) {
266             return NGX_ERROR;
267         }
268 
269         return NGX_OK;
270     }
271 
272     rc = ngx_ssl_stapling_issuer(cf, ssl, staple);
273 
274     if (rc == NGX_DECLINED) {
275         return NGX_OK;
276     }
277 
278     if (rc != NGX_OK) {
279         return NGX_ERROR;
280     }
281 
282     rc = ngx_ssl_stapling_responder(cf, ssl, staple, responder);
283 
284     if (rc == NGX_DECLINED) {
285         return NGX_OK;
286     }
287 
288     if (rc != NGX_OK) {
289         return NGX_ERROR;
290     }
291 
292     return NGX_OK;
293 }
294 
295 
296 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)297 ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl,
298     ngx_ssl_stapling_t *staple, ngx_str_t *file)
299 {
300     BIO            *bio;
301     int             len;
302     u_char         *p, *buf;
303     OCSP_RESPONSE  *response;
304 
305     if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) {
306         return NGX_ERROR;
307     }
308 
309     bio = BIO_new_file((char *) file->data, "rb");
310     if (bio == NULL) {
311         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
312                       "BIO_new_file(\"%s\") failed", file->data);
313         return NGX_ERROR;
314     }
315 
316     response = d2i_OCSP_RESPONSE_bio(bio, NULL);
317     if (response == NULL) {
318         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
319                       "d2i_OCSP_RESPONSE_bio(\"%s\") failed", file->data);
320         BIO_free(bio);
321         return NGX_ERROR;
322     }
323 
324     len = i2d_OCSP_RESPONSE(response, NULL);
325     if (len <= 0) {
326         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
327                       "i2d_OCSP_RESPONSE(\"%s\") failed", file->data);
328         goto failed;
329     }
330 
331     buf = ngx_alloc(len, ssl->log);
332     if (buf == NULL) {
333         goto failed;
334     }
335 
336     p = buf;
337     len = i2d_OCSP_RESPONSE(response, &p);
338     if (len <= 0) {
339         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
340                       "i2d_OCSP_RESPONSE(\"%s\") failed", file->data);
341         ngx_free(buf);
342         goto failed;
343     }
344 
345     OCSP_RESPONSE_free(response);
346     BIO_free(bio);
347 
348     staple->staple.data = buf;
349     staple->staple.len = len;
350     staple->valid = NGX_MAX_TIME_T_VALUE;
351 
352     return NGX_OK;
353 
354 failed:
355 
356     OCSP_RESPONSE_free(response);
357     BIO_free(bio);
358 
359     return NGX_ERROR;
360 }
361 
362 
363 static ngx_int_t
ngx_ssl_stapling_issuer(ngx_conf_t * cf,ngx_ssl_t * ssl,ngx_ssl_stapling_t * staple)364 ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl,
365     ngx_ssl_stapling_t *staple)
366 {
367     int              i, n, rc;
368     X509            *cert, *issuer;
369     X509_STORE      *store;
370     X509_STORE_CTX  *store_ctx;
371 
372     cert = staple->cert;
373 
374     n = sk_X509_num(staple->chain);
375 
376     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
377                    "SSL get issuer: %d extra certs", n);
378 
379     for (i = 0; i < n; i++) {
380         issuer = sk_X509_value(staple->chain, i);
381         if (X509_check_issued(issuer, cert) == X509_V_OK) {
382 #if OPENSSL_VERSION_NUMBER >= 0x10100001L
383             X509_up_ref(issuer);
384 #else
385             CRYPTO_add(&issuer->references, 1, CRYPTO_LOCK_X509);
386 #endif
387 
388             ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
389                            "SSL get issuer: found %p in extra certs", issuer);
390 
391             staple->issuer = issuer;
392 
393             return NGX_OK;
394         }
395     }
396 
397     store = SSL_CTX_get_cert_store(ssl->ctx);
398     if (store == NULL) {
399         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
400                       "SSL_CTX_get_cert_store() failed");
401         return NGX_ERROR;
402     }
403 
404     store_ctx = X509_STORE_CTX_new();
405     if (store_ctx == NULL) {
406         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
407                       "X509_STORE_CTX_new() failed");
408         return NGX_ERROR;
409     }
410 
411     if (X509_STORE_CTX_init(store_ctx, store, NULL, NULL) == 0) {
412         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
413                       "X509_STORE_CTX_init() failed");
414         X509_STORE_CTX_free(store_ctx);
415         return NGX_ERROR;
416     }
417 
418     rc = X509_STORE_CTX_get1_issuer(&issuer, store_ctx, cert);
419 
420     if (rc == -1) {
421         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
422                       "X509_STORE_CTX_get1_issuer() failed");
423         X509_STORE_CTX_free(store_ctx);
424         return NGX_ERROR;
425     }
426 
427     if (rc == 0) {
428         ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
429                       "\"ssl_stapling\" ignored, "
430                       "issuer certificate not found for certificate \"%s\"",
431                       staple->name);
432         X509_STORE_CTX_free(store_ctx);
433         return NGX_DECLINED;
434     }
435 
436     X509_STORE_CTX_free(store_ctx);
437 
438     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
439                    "SSL get issuer: found %p in cert store", issuer);
440 
441     staple->issuer = issuer;
442 
443     return NGX_OK;
444 }
445 
446 
447 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)448 ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl,
449     ngx_ssl_stapling_t *staple, ngx_str_t *responder)
450 {
451     char                      *s;
452     ngx_str_t                  rsp;
453     ngx_url_t                  u;
454     STACK_OF(OPENSSL_STRING)  *aia;
455 
456     if (responder->len == 0) {
457 
458         /* extract OCSP responder URL from certificate */
459 
460         aia = X509_get1_ocsp(staple->cert);
461         if (aia == NULL) {
462             ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
463                           "\"ssl_stapling\" ignored, "
464                           "no OCSP responder URL in the certificate \"%s\"",
465                           staple->name);
466             return NGX_DECLINED;
467         }
468 
469 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
470         s = sk_OPENSSL_STRING_value(aia, 0);
471 #else
472         s = sk_value(aia, 0);
473 #endif
474         if (s == NULL) {
475             ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
476                           "\"ssl_stapling\" ignored, "
477                           "no OCSP responder URL in the certificate \"%s\"",
478                           staple->name);
479             X509_email_free(aia);
480             return NGX_DECLINED;
481         }
482 
483         responder = &rsp;
484 
485         responder->len = ngx_strlen(s);
486         responder->data = ngx_palloc(cf->pool, responder->len);
487         if (responder->data == NULL) {
488             X509_email_free(aia);
489             return NGX_ERROR;
490         }
491 
492         ngx_memcpy(responder->data, s, responder->len);
493         X509_email_free(aia);
494     }
495 
496     ngx_memzero(&u, sizeof(ngx_url_t));
497 
498     u.url = *responder;
499     u.default_port = 80;
500     u.uri_part = 1;
501 
502     if (u.url.len > 7
503         && ngx_strncasecmp(u.url.data, (u_char *) "http://", 7) == 0)
504     {
505         u.url.len -= 7;
506         u.url.data += 7;
507 
508     } else {
509         ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
510                       "\"ssl_stapling\" ignored, "
511                       "invalid URL prefix in OCSP responder \"%V\" "
512                       "in the certificate \"%s\"",
513                       &u.url, staple->name);
514         return NGX_DECLINED;
515     }
516 
517     if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
518         if (u.err) {
519             ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
520                           "\"ssl_stapling\" ignored, "
521                           "%s in OCSP responder \"%V\" "
522                           "in the certificate \"%s\"",
523                           u.err, &u.url, staple->name);
524             return NGX_DECLINED;
525         }
526 
527         return NGX_ERROR;
528     }
529 
530     staple->addrs = u.addrs;
531     staple->naddrs = u.naddrs;
532     staple->host = u.host;
533     staple->uri = u.uri;
534     staple->port = u.port;
535 
536     if (staple->uri.len == 0) {
537         ngx_str_set(&staple->uri, "/");
538     }
539 
540     return NGX_OK;
541 }
542 
543 
544 ngx_int_t
ngx_ssl_stapling_resolver(ngx_conf_t * cf,ngx_ssl_t * ssl,ngx_resolver_t * resolver,ngx_msec_t resolver_timeout)545 ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
546     ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)
547 {
548     X509                *cert;
549     ngx_ssl_stapling_t  *staple;
550 
551     for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
552          cert;
553          cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index))
554     {
555         staple = X509_get_ex_data(cert, ngx_ssl_stapling_index);
556         staple->resolver = resolver;
557         staple->resolver_timeout = resolver_timeout;
558     }
559 
560     return NGX_OK;
561 }
562 
563 
564 static int
ngx_ssl_certificate_status_callback(ngx_ssl_conn_t * ssl_conn,void * data)565 ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn, void *data)
566 {
567     int                  rc;
568     X509                *cert;
569     u_char              *p;
570     ngx_connection_t    *c;
571     ngx_ssl_stapling_t  *staple;
572 
573     c = ngx_ssl_get_connection(ssl_conn);
574 
575     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
576                    "SSL certificate status callback");
577 
578     rc = SSL_TLSEXT_ERR_NOACK;
579 
580     cert = SSL_get_certificate(ssl_conn);
581 
582     if (cert == NULL) {
583         return rc;
584     }
585 
586     staple = X509_get_ex_data(cert, ngx_ssl_stapling_index);
587 
588     if (staple == NULL) {
589         return rc;
590     }
591 
592     if (staple->staple.len
593         && staple->valid >= ngx_time())
594     {
595         /* we have to copy ocsp response as OpenSSL will free it by itself */
596 
597         p = OPENSSL_malloc(staple->staple.len);
598         if (p == NULL) {
599             ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "OPENSSL_malloc() failed");
600             return SSL_TLSEXT_ERR_NOACK;
601         }
602 
603         ngx_memcpy(p, staple->staple.data, staple->staple.len);
604 
605         SSL_set_tlsext_status_ocsp_resp(ssl_conn, p, staple->staple.len);
606 
607         rc = SSL_TLSEXT_ERR_OK;
608     }
609 
610     ngx_ssl_stapling_update(staple);
611 
612     return rc;
613 }
614 
615 
616 static void
ngx_ssl_stapling_update(ngx_ssl_stapling_t * staple)617 ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple)
618 {
619     ngx_ssl_ocsp_ctx_t  *ctx;
620 
621     if (staple->host.len == 0
622         || staple->loading || staple->refresh >= ngx_time())
623     {
624         return;
625     }
626 
627     staple->loading = 1;
628 
629     ctx = ngx_ssl_ocsp_start(ngx_cycle->log);
630     if (ctx == NULL) {
631         return;
632     }
633 
634     ctx->ssl_ctx = staple->ssl_ctx;
635     ctx->cert = staple->cert;
636     ctx->issuer = staple->issuer;
637     ctx->chain = staple->chain;
638     ctx->name = staple->name;
639     ctx->flags = (staple->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY);
640 
641     ctx->addrs = staple->addrs;
642     ctx->naddrs = staple->naddrs;
643     ctx->host = staple->host;
644     ctx->uri = staple->uri;
645     ctx->port = staple->port;
646     ctx->timeout = staple->timeout;
647 
648     ctx->resolver = staple->resolver;
649     ctx->resolver_timeout = staple->resolver_timeout;
650 
651     ctx->handler = ngx_ssl_stapling_ocsp_handler;
652     ctx->data = staple;
653 
654     ngx_ssl_ocsp_request(ctx);
655 
656     return;
657 }
658 
659 
660 static void
ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t * ctx)661 ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
662 {
663     time_t               now;
664     ngx_str_t            response;
665     ngx_ssl_stapling_t  *staple;
666 
667     staple = ctx->data;
668     now = ngx_time();
669 
670     if (ngx_ssl_ocsp_verify(ctx) != NGX_OK) {
671         goto error;
672     }
673 
674     if (ctx->status != V_OCSP_CERTSTATUS_GOOD) {
675         ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
676                       "certificate status \"%s\" in the OCSP response",
677                       OCSP_cert_status_str(ctx->status));
678         goto error;
679     }
680 
681     /* copy the response to memory not in ctx->pool */
682 
683     response.len = ctx->response->last - ctx->response->pos;
684     response.data = ngx_alloc(response.len, ctx->log);
685 
686     if (response.data == NULL) {
687         goto error;
688     }
689 
690     ngx_memcpy(response.data, ctx->response->pos, response.len);
691 
692     if (staple->staple.data) {
693         ngx_free(staple->staple.data);
694     }
695 
696     staple->staple = response;
697     staple->valid = ctx->valid;
698 
699     /*
700      * refresh before the response expires,
701      * but not earlier than in 5 minutes, and at least in an hour
702      */
703 
704     staple->loading = 0;
705     staple->refresh = ngx_max(ngx_min(ctx->valid - 300, now + 3600), now + 300);
706 
707     ngx_ssl_ocsp_done(ctx);
708     return;
709 
710 error:
711 
712     staple->loading = 0;
713     staple->refresh = now + 300;
714 
715     ngx_ssl_ocsp_done(ctx);
716 }
717 
718 
719 static time_t
ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME * asn1time)720 ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time)
721 {
722     BIO     *bio;
723     char    *value;
724     size_t   len;
725     time_t   time;
726 
727     /*
728      * OpenSSL doesn't provide a way to convert ASN1_GENERALIZEDTIME
729      * into time_t.  To do this, we use ASN1_GENERALIZEDTIME_print(),
730      * which uses the "MMM DD HH:MM:SS YYYY [GMT]" format (e.g.,
731      * "Feb  3 00:55:52 2015 GMT"), and parse the result.
732      */
733 
734     bio = BIO_new(BIO_s_mem());
735     if (bio == NULL) {
736         return NGX_ERROR;
737     }
738 
739     /* fake weekday prepended to match C asctime() format */
740 
741     BIO_write(bio, "Tue ", sizeof("Tue ") - 1);
742     ASN1_GENERALIZEDTIME_print(bio, asn1time);
743     len = BIO_get_mem_data(bio, &value);
744 
745     time = ngx_parse_http_time((u_char *) value, len);
746 
747     BIO_free(bio);
748 
749     return time;
750 }
751 
752 
753 static void
ngx_ssl_stapling_cleanup(void * data)754 ngx_ssl_stapling_cleanup(void *data)
755 {
756     ngx_ssl_stapling_t  *staple = data;
757 
758     if (staple->issuer) {
759         X509_free(staple->issuer);
760     }
761 
762     if (staple->staple.data) {
763         ngx_free(staple->staple.data);
764     }
765 }
766 
767 
768 ngx_int_t
ngx_ssl_ocsp(ngx_conf_t * cf,ngx_ssl_t * ssl,ngx_str_t * responder,ngx_uint_t depth,ngx_shm_zone_t * shm_zone)769 ngx_ssl_ocsp(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *responder,
770     ngx_uint_t depth, ngx_shm_zone_t *shm_zone)
771 {
772     ngx_url_t             u;
773     ngx_ssl_ocsp_conf_t  *ocf;
774 
775     ocf = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_ocsp_conf_t));
776     if (ocf == NULL) {
777         return NGX_ERROR;
778     }
779 
780     ocf->depth = depth;
781     ocf->shm_zone = shm_zone;
782 
783     if (responder->len) {
784         ngx_memzero(&u, sizeof(ngx_url_t));
785 
786         u.url = *responder;
787         u.default_port = 80;
788         u.uri_part = 1;
789 
790         if (u.url.len > 7
791             && ngx_strncasecmp(u.url.data, (u_char *) "http://", 7) == 0)
792         {
793             u.url.len -= 7;
794             u.url.data += 7;
795 
796         } else {
797             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
798                           "invalid URL prefix in OCSP responder \"%V\" "
799                           "in \"ssl_ocsp_responder\"", &u.url);
800             return NGX_ERROR;
801         }
802 
803         if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
804             if (u.err) {
805                 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
806                               "%s in OCSP responder \"%V\" "
807                               "in \"ssl_ocsp_responder\"", u.err, &u.url);
808             }
809 
810             return NGX_ERROR;
811         }
812 
813         ocf->addrs = u.addrs;
814         ocf->naddrs = u.naddrs;
815         ocf->host = u.host;
816         ocf->uri = u.uri;
817         ocf->port = u.port;
818     }
819 
820     if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_ocsp_index, ocf) == 0) {
821         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
822                       "SSL_CTX_set_ex_data() failed");
823         return NGX_ERROR;
824     }
825 
826     return NGX_OK;
827 }
828 
829 
830 ngx_int_t
ngx_ssl_ocsp_resolver(ngx_conf_t * cf,ngx_ssl_t * ssl,ngx_resolver_t * resolver,ngx_msec_t resolver_timeout)831 ngx_ssl_ocsp_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
832     ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)
833 {
834     ngx_ssl_ocsp_conf_t  *ocf;
835 
836     ocf = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_ocsp_index);
837     ocf->resolver = resolver;
838     ocf->resolver_timeout = resolver_timeout;
839 
840     return NGX_OK;
841 }
842 
843 
844 ngx_int_t
ngx_ssl_ocsp_validate(ngx_connection_t * c)845 ngx_ssl_ocsp_validate(ngx_connection_t *c)
846 {
847     X509                 *cert;
848     SSL_CTX              *ssl_ctx;
849     ngx_int_t             rc;
850     X509_STORE           *store;
851     X509_STORE_CTX       *store_ctx;
852     STACK_OF(X509)       *chain;
853     ngx_ssl_ocsp_t       *ocsp;
854     ngx_ssl_ocsp_conf_t  *ocf;
855 
856     if (c->ssl->in_ocsp) {
857         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
858             return NGX_ERROR;
859         }
860 
861         if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
862             return NGX_ERROR;
863         }
864 
865         return NGX_AGAIN;
866     }
867 
868     ssl_ctx = SSL_get_SSL_CTX(c->ssl->connection);
869 
870     ocf = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_ocsp_index);
871     if (ocf == NULL) {
872         return NGX_OK;
873     }
874 
875     if (SSL_get_verify_result(c->ssl->connection) != X509_V_OK) {
876         return NGX_OK;
877     }
878 
879     cert = SSL_get_peer_certificate(c->ssl->connection);
880     if (cert == NULL) {
881         return NGX_OK;
882     }
883 
884     ocsp = ngx_pcalloc(c->pool, sizeof(ngx_ssl_ocsp_t));
885     if (ocsp == NULL) {
886         X509_free(cert);
887         return NGX_ERROR;
888     }
889 
890     c->ssl->ocsp = ocsp;
891 
892     ocsp->status = NGX_AGAIN;
893     ocsp->cert_status = V_OCSP_CERTSTATUS_GOOD;
894     ocsp->conf = ocf;
895 
896 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined LIBRESSL_VERSION_NUMBER)
897 
898     ocsp->certs = SSL_get0_verified_chain(c->ssl->connection);
899 
900     if (ocsp->certs) {
901         ocsp->certs = X509_chain_up_ref(ocsp->certs);
902         if (ocsp->certs == NULL) {
903             X509_free(cert);
904             return NGX_ERROR;
905         }
906     }
907 
908 #endif
909 
910     if (ocsp->certs == NULL) {
911         store = SSL_CTX_get_cert_store(ssl_ctx);
912         if (store == NULL) {
913             ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
914                           "SSL_CTX_get_cert_store() failed");
915             X509_free(cert);
916             return NGX_ERROR;
917         }
918 
919         store_ctx = X509_STORE_CTX_new();
920         if (store_ctx == NULL) {
921             ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
922                           "X509_STORE_CTX_new() failed");
923             X509_free(cert);
924             return NGX_ERROR;
925         }
926 
927         chain = SSL_get_peer_cert_chain(c->ssl->connection);
928 
929         if (X509_STORE_CTX_init(store_ctx, store, cert, chain) == 0) {
930             ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
931                           "X509_STORE_CTX_init() failed");
932             X509_STORE_CTX_free(store_ctx);
933             X509_free(cert);
934             return NGX_ERROR;
935         }
936 
937         rc = X509_verify_cert(store_ctx);
938         if (rc <= 0) {
939             ngx_ssl_error(NGX_LOG_ERR, c->log, 0, "X509_verify_cert() failed");
940             X509_STORE_CTX_free(store_ctx);
941             X509_free(cert);
942             return NGX_ERROR;
943         }
944 
945         ocsp->certs = X509_STORE_CTX_get1_chain(store_ctx);
946         if (ocsp->certs == NULL) {
947             ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
948                           "X509_STORE_CTX_get1_chain() failed");
949             X509_STORE_CTX_free(store_ctx);
950             X509_free(cert);
951             return NGX_ERROR;
952         }
953 
954         X509_STORE_CTX_free(store_ctx);
955     }
956 
957     X509_free(cert);
958 
959     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
960                    "ssl ocsp validate, certs:%d", sk_X509_num(ocsp->certs));
961 
962     ngx_ssl_ocsp_validate_next(c);
963 
964     if (ocsp->status == NGX_AGAIN) {
965         c->ssl->in_ocsp = 1;
966         return NGX_AGAIN;
967     }
968 
969     return NGX_OK;
970 }
971 
972 
973 static void
ngx_ssl_ocsp_validate_next(ngx_connection_t * c)974 ngx_ssl_ocsp_validate_next(ngx_connection_t *c)
975 {
976     ngx_int_t             rc;
977     ngx_uint_t            n;
978     ngx_ssl_ocsp_t       *ocsp;
979     ngx_ssl_ocsp_ctx_t   *ctx;
980     ngx_ssl_ocsp_conf_t  *ocf;
981 
982     ocsp = c->ssl->ocsp;
983     ocf = ocsp->conf;
984 
985     n = sk_X509_num(ocsp->certs);
986 
987     for ( ;; ) {
988 
989         if (ocsp->ncert == n - 1 || (ocf->depth == 2 && ocsp->ncert == 1)) {
990             ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
991                            "ssl ocsp validated, certs:%ui", ocsp->ncert);
992             rc = NGX_OK;
993             goto done;
994         }
995 
996         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
997                        "ssl ocsp validate cert:%ui", ocsp->ncert);
998 
999         ctx = ngx_ssl_ocsp_start(c->log);
1000         if (ctx == NULL) {
1001             rc = NGX_ERROR;
1002             goto done;
1003         }
1004 
1005         ocsp->ctx = ctx;
1006 
1007         ctx->ssl_ctx = SSL_get_SSL_CTX(c->ssl->connection);
1008         ctx->cert = sk_X509_value(ocsp->certs, ocsp->ncert);
1009         ctx->issuer = sk_X509_value(ocsp->certs, ocsp->ncert + 1);
1010         ctx->chain = ocsp->certs;
1011 
1012         ctx->resolver = ocf->resolver;
1013         ctx->resolver_timeout = ocf->resolver_timeout;
1014 
1015         ctx->handler = ngx_ssl_ocsp_handler;
1016         ctx->data = c;
1017 
1018         ctx->shm_zone = ocf->shm_zone;
1019 
1020         ctx->addrs = ocf->addrs;
1021         ctx->naddrs = ocf->naddrs;
1022         ctx->host = ocf->host;
1023         ctx->uri = ocf->uri;
1024         ctx->port = ocf->port;
1025 
1026         rc = ngx_ssl_ocsp_responder(c, ctx);
1027         if (rc != NGX_OK) {
1028             goto done;
1029         }
1030 
1031         if (ctx->uri.len == 0) {
1032             ngx_str_set(&ctx->uri, "/");
1033         }
1034 
1035         ocsp->ncert++;
1036 
1037         rc = ngx_ssl_ocsp_cache_lookup(ctx);
1038 
1039         if (rc == NGX_ERROR) {
1040             goto done;
1041         }
1042 
1043         if (rc == NGX_DECLINED) {
1044             break;
1045         }
1046 
1047         /* rc == NGX_OK */
1048 
1049         if (ctx->status != V_OCSP_CERTSTATUS_GOOD) {
1050             ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1051                            "ssl ocsp cached status \"%s\"",
1052                            OCSP_cert_status_str(ctx->status));
1053             ocsp->cert_status = ctx->status;
1054             goto done;
1055         }
1056 
1057         ocsp->ctx = NULL;
1058         ngx_ssl_ocsp_done(ctx);
1059     }
1060 
1061     ngx_ssl_ocsp_request(ctx);
1062     return;
1063 
1064 done:
1065 
1066     ocsp->status = rc;
1067 
1068     if (c->ssl->in_ocsp) {
1069         c->ssl->handshaked = 1;
1070         c->ssl->handler(c);
1071     }
1072 }
1073 
1074 
1075 static void
ngx_ssl_ocsp_handler(ngx_ssl_ocsp_ctx_t * ctx)1076 ngx_ssl_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
1077 {
1078     ngx_int_t          rc;
1079     ngx_ssl_ocsp_t    *ocsp;
1080     ngx_connection_t  *c;
1081 
1082     c = ctx->data;
1083     ocsp = c->ssl->ocsp;
1084     ocsp->ctx = NULL;
1085 
1086     rc = ngx_ssl_ocsp_verify(ctx);
1087     if (rc != NGX_OK) {
1088         goto done;
1089     }
1090 
1091     rc = ngx_ssl_ocsp_cache_store(ctx);
1092     if (rc != NGX_OK) {
1093         goto done;
1094     }
1095 
1096     if (ctx->status != V_OCSP_CERTSTATUS_GOOD) {
1097         ocsp->cert_status = ctx->status;
1098         goto done;
1099     }
1100 
1101     ngx_ssl_ocsp_done(ctx);
1102 
1103     ngx_ssl_ocsp_validate_next(c);
1104 
1105     return;
1106 
1107 done:
1108 
1109     ocsp->status = rc;
1110     ngx_ssl_ocsp_done(ctx);
1111 
1112     if (c->ssl->in_ocsp) {
1113         c->ssl->handshaked = 1;
1114         c->ssl->handler(c);
1115     }
1116 }
1117 
1118 
1119 static ngx_int_t
ngx_ssl_ocsp_responder(ngx_connection_t * c,ngx_ssl_ocsp_ctx_t * ctx)1120 ngx_ssl_ocsp_responder(ngx_connection_t *c, ngx_ssl_ocsp_ctx_t *ctx)
1121 {
1122     char                      *s;
1123     ngx_str_t                  responder;
1124     ngx_url_t                  u;
1125     STACK_OF(OPENSSL_STRING)  *aia;
1126 
1127     if (ctx->host.len) {
1128         return NGX_OK;
1129     }
1130 
1131     /* extract OCSP responder URL from certificate */
1132 
1133     aia = X509_get1_ocsp(ctx->cert);
1134     if (aia == NULL) {
1135         ngx_log_error(NGX_LOG_ERR, c->log, 0,
1136                       "no OCSP responder URL in certificate");
1137         return NGX_ERROR;
1138     }
1139 
1140 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
1141     s = sk_OPENSSL_STRING_value(aia, 0);
1142 #else
1143     s = sk_value(aia, 0);
1144 #endif
1145     if (s == NULL) {
1146         ngx_log_error(NGX_LOG_ERR, c->log, 0,
1147                       "no OCSP responder URL in certificate");
1148         X509_email_free(aia);
1149         return NGX_ERROR;
1150     }
1151 
1152     responder.len = ngx_strlen(s);
1153     responder.data = ngx_palloc(ctx->pool, responder.len);
1154     if (responder.data == NULL) {
1155         X509_email_free(aia);
1156         return NGX_ERROR;
1157     }
1158 
1159     ngx_memcpy(responder.data, s, responder.len);
1160     X509_email_free(aia);
1161 
1162     ngx_memzero(&u, sizeof(ngx_url_t));
1163 
1164     u.url = responder;
1165     u.default_port = 80;
1166     u.uri_part = 1;
1167     u.no_resolve = 1;
1168 
1169     if (u.url.len > 7
1170         && ngx_strncasecmp(u.url.data, (u_char *) "http://", 7) == 0)
1171     {
1172         u.url.len -= 7;
1173         u.url.data += 7;
1174 
1175     } else {
1176         ngx_log_error(NGX_LOG_ERR, c->log, 0,
1177                       "invalid URL prefix in OCSP responder \"%V\" "
1178                       "in certificate", &u.url);
1179         return NGX_ERROR;
1180     }
1181 
1182     if (ngx_parse_url(ctx->pool, &u) != NGX_OK) {
1183         if (u.err) {
1184             ngx_log_error(NGX_LOG_ERR, c->log, 0,
1185                           "%s in OCSP responder \"%V\" in certificate",
1186                           u.err, &u.url);
1187         }
1188 
1189         return NGX_ERROR;
1190     }
1191 
1192     if (u.host.len == 0) {
1193         ngx_log_error(NGX_LOG_ERR, c->log, 0,
1194                       "empty host in OCSP responder in certificate");
1195         return NGX_ERROR;
1196     }
1197 
1198     ctx->addrs = u.addrs;
1199     ctx->naddrs = u.naddrs;
1200     ctx->host = u.host;
1201     ctx->uri = u.uri;
1202     ctx->port = u.port;
1203 
1204     return NGX_OK;
1205 }
1206 
1207 
1208 ngx_int_t
ngx_ssl_ocsp_get_status(ngx_connection_t * c,const char ** s)1209 ngx_ssl_ocsp_get_status(ngx_connection_t *c, const char **s)
1210 {
1211     ngx_ssl_ocsp_t  *ocsp;
1212 
1213     ocsp = c->ssl->ocsp;
1214     if (ocsp == NULL) {
1215         return NGX_OK;
1216     }
1217 
1218     if (ocsp->status == NGX_ERROR) {
1219         *s = "certificate status request failed";
1220         return NGX_DECLINED;
1221     }
1222 
1223     switch (ocsp->cert_status) {
1224 
1225     case V_OCSP_CERTSTATUS_GOOD:
1226         return NGX_OK;
1227 
1228     case V_OCSP_CERTSTATUS_REVOKED:
1229         *s = "certificate revoked";
1230         break;
1231 
1232     default: /* V_OCSP_CERTSTATUS_UNKNOWN */
1233         *s = "certificate status unknown";
1234     }
1235 
1236     return NGX_DECLINED;
1237 }
1238 
1239 
1240 void
ngx_ssl_ocsp_cleanup(ngx_connection_t * c)1241 ngx_ssl_ocsp_cleanup(ngx_connection_t *c)
1242 {
1243     ngx_ssl_ocsp_t  *ocsp;
1244 
1245     ocsp = c->ssl->ocsp;
1246     if (ocsp == NULL) {
1247         return;
1248     }
1249 
1250     if (ocsp->ctx) {
1251         ngx_ssl_ocsp_done(ocsp->ctx);
1252         ocsp->ctx = NULL;
1253     }
1254 
1255     if (ocsp->certs) {
1256         sk_X509_pop_free(ocsp->certs, X509_free);
1257         ocsp->certs = NULL;
1258     }
1259 }
1260 
1261 
1262 static ngx_ssl_ocsp_ctx_t *
ngx_ssl_ocsp_start(ngx_log_t * log)1263 ngx_ssl_ocsp_start(ngx_log_t *log)
1264 {
1265     ngx_pool_t          *pool;
1266     ngx_ssl_ocsp_ctx_t  *ctx;
1267 
1268     pool = ngx_create_pool(2048, log);
1269     if (pool == NULL) {
1270         return NULL;
1271     }
1272 
1273     ctx = ngx_pcalloc(pool, sizeof(ngx_ssl_ocsp_ctx_t));
1274     if (ctx == NULL) {
1275         ngx_destroy_pool(pool);
1276         return NULL;
1277     }
1278 
1279     log = ngx_palloc(pool, sizeof(ngx_log_t));
1280     if (log == NULL) {
1281         ngx_destroy_pool(pool);
1282         return NULL;
1283     }
1284 
1285     ctx->pool = pool;
1286 
1287     *log = *ctx->pool->log;
1288 
1289     ctx->pool->log = log;
1290     ctx->log = log;
1291 
1292     log->handler = ngx_ssl_ocsp_log_error;
1293     log->data = ctx;
1294     log->action = "requesting certificate status";
1295 
1296     return ctx;
1297 }
1298 
1299 
1300 static void
ngx_ssl_ocsp_done(ngx_ssl_ocsp_ctx_t * ctx)1301 ngx_ssl_ocsp_done(ngx_ssl_ocsp_ctx_t *ctx)
1302 {
1303     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1304                    "ssl ocsp done");
1305 
1306     if (ctx->peer.connection) {
1307         ngx_close_connection(ctx->peer.connection);
1308     }
1309 
1310     ngx_destroy_pool(ctx->pool);
1311 }
1312 
1313 
1314 static void
ngx_ssl_ocsp_error(ngx_ssl_ocsp_ctx_t * ctx)1315 ngx_ssl_ocsp_error(ngx_ssl_ocsp_ctx_t *ctx)
1316 {
1317     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1318                    "ssl ocsp error");
1319 
1320     ctx->code = 0;
1321     ctx->handler(ctx);
1322 }
1323 
1324 
1325 static void
ngx_ssl_ocsp_next(ngx_ssl_ocsp_ctx_t * ctx)1326 ngx_ssl_ocsp_next(ngx_ssl_ocsp_ctx_t *ctx)
1327 {
1328     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1329                    "ssl ocsp next");
1330 
1331     if (++ctx->naddr >= ctx->naddrs) {
1332         ngx_ssl_ocsp_error(ctx);
1333         return;
1334     }
1335 
1336     ctx->request->pos = ctx->request->start;
1337 
1338     if (ctx->response) {
1339         ctx->response->last = ctx->response->pos;
1340     }
1341 
1342     if (ctx->peer.connection) {
1343         ngx_close_connection(ctx->peer.connection);
1344         ctx->peer.connection = NULL;
1345     }
1346 
1347     ctx->state = 0;
1348     ctx->count = 0;
1349     ctx->done = 0;
1350 
1351     ngx_ssl_ocsp_connect(ctx);
1352 }
1353 
1354 
1355 static void
ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t * ctx)1356 ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx)
1357 {
1358     ngx_resolver_ctx_t  *resolve, temp;
1359 
1360     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1361                    "ssl ocsp request");
1362 
1363     if (ngx_ssl_ocsp_create_request(ctx) != NGX_OK) {
1364         ngx_ssl_ocsp_error(ctx);
1365         return;
1366     }
1367 
1368     if (ctx->resolver) {
1369         /* resolve OCSP responder hostname */
1370 
1371         temp.name = ctx->host;
1372 
1373         resolve = ngx_resolve_start(ctx->resolver, &temp);
1374         if (resolve == NULL) {
1375             ngx_ssl_ocsp_error(ctx);
1376             return;
1377         }
1378 
1379         if (resolve == NGX_NO_RESOLVER) {
1380             if (ctx->naddrs == 0) {
1381                 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1382                               "no resolver defined to resolve %V", &ctx->host);
1383 
1384                 ngx_ssl_ocsp_error(ctx);
1385                 return;
1386             }
1387 
1388             ngx_log_error(NGX_LOG_WARN, ctx->log, 0,
1389                           "no resolver defined to resolve %V", &ctx->host);
1390             goto connect;
1391         }
1392 
1393         resolve->name = ctx->host;
1394         resolve->handler = ngx_ssl_ocsp_resolve_handler;
1395         resolve->data = ctx;
1396         resolve->timeout = ctx->resolver_timeout;
1397 
1398         if (ngx_resolve_name(resolve) != NGX_OK) {
1399             ngx_ssl_ocsp_error(ctx);
1400             return;
1401         }
1402 
1403         return;
1404     }
1405 
1406 connect:
1407 
1408     ngx_ssl_ocsp_connect(ctx);
1409 }
1410 
1411 
1412 static void
ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t * resolve)1413 ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve)
1414 {
1415     ngx_ssl_ocsp_ctx_t *ctx = resolve->data;
1416 
1417     u_char           *p;
1418     size_t            len;
1419     socklen_t         socklen;
1420     ngx_uint_t        i;
1421     struct sockaddr  *sockaddr;
1422 
1423     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1424                    "ssl ocsp resolve handler");
1425 
1426     if (resolve->state) {
1427         ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1428                       "%V could not be resolved (%i: %s)",
1429                       &resolve->name, resolve->state,
1430                       ngx_resolver_strerror(resolve->state));
1431         goto failed;
1432     }
1433 
1434 #if (NGX_DEBUG)
1435     {
1436     u_char     text[NGX_SOCKADDR_STRLEN];
1437     ngx_str_t  addr;
1438 
1439     addr.data = text;
1440 
1441     for (i = 0; i < resolve->naddrs; i++) {
1442         addr.len = ngx_sock_ntop(resolve->addrs[i].sockaddr,
1443                                  resolve->addrs[i].socklen,
1444                                  text, NGX_SOCKADDR_STRLEN, 0);
1445 
1446         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1447                        "name was resolved to %V", &addr);
1448 
1449     }
1450     }
1451 #endif
1452 
1453     ctx->naddrs = resolve->naddrs;
1454     ctx->addrs = ngx_pcalloc(ctx->pool, ctx->naddrs * sizeof(ngx_addr_t));
1455 
1456     if (ctx->addrs == NULL) {
1457         goto failed;
1458     }
1459 
1460     for (i = 0; i < resolve->naddrs; i++) {
1461 
1462         socklen = resolve->addrs[i].socklen;
1463 
1464         sockaddr = ngx_palloc(ctx->pool, socklen);
1465         if (sockaddr == NULL) {
1466             goto failed;
1467         }
1468 
1469         ngx_memcpy(sockaddr, resolve->addrs[i].sockaddr, socklen);
1470         ngx_inet_set_port(sockaddr, ctx->port);
1471 
1472         ctx->addrs[i].sockaddr = sockaddr;
1473         ctx->addrs[i].socklen = socklen;
1474 
1475         p = ngx_pnalloc(ctx->pool, NGX_SOCKADDR_STRLEN);
1476         if (p == NULL) {
1477             goto failed;
1478         }
1479 
1480         len = ngx_sock_ntop(sockaddr, socklen, p, NGX_SOCKADDR_STRLEN, 1);
1481 
1482         ctx->addrs[i].name.len = len;
1483         ctx->addrs[i].name.data = p;
1484     }
1485 
1486     ngx_resolve_name_done(resolve);
1487 
1488     ngx_ssl_ocsp_connect(ctx);
1489     return;
1490 
1491 failed:
1492 
1493     ngx_resolve_name_done(resolve);
1494     ngx_ssl_ocsp_error(ctx);
1495 }
1496 
1497 
1498 static void
ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t * ctx)1499 ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx)
1500 {
1501     ngx_int_t    rc;
1502     ngx_addr_t  *addr;
1503 
1504     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1505                    "ssl ocsp connect %ui/%ui", ctx->naddr, ctx->naddrs);
1506 
1507     addr = &ctx->addrs[ctx->naddr];
1508 
1509     ctx->peer.sockaddr = addr->sockaddr;
1510     ctx->peer.socklen = addr->socklen;
1511     ctx->peer.name = &addr->name;
1512     ctx->peer.get = ngx_event_get_peer;
1513     ctx->peer.log = ctx->log;
1514     ctx->peer.log_error = NGX_ERROR_ERR;
1515 
1516     rc = ngx_event_connect_peer(&ctx->peer);
1517 
1518     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1519                    "ssl ocsp connect peer done");
1520 
1521     if (rc == NGX_ERROR) {
1522         ngx_ssl_ocsp_error(ctx);
1523         return;
1524     }
1525 
1526     if (rc == NGX_BUSY || rc == NGX_DECLINED) {
1527         ngx_ssl_ocsp_next(ctx);
1528         return;
1529     }
1530 
1531     ctx->peer.connection->data = ctx;
1532     ctx->peer.connection->pool = ctx->pool;
1533 
1534     ctx->peer.connection->read->handler = ngx_ssl_ocsp_read_handler;
1535     ctx->peer.connection->write->handler = ngx_ssl_ocsp_write_handler;
1536 
1537     ctx->process = ngx_ssl_ocsp_process_status_line;
1538 
1539     if (ctx->timeout) {
1540         ngx_add_timer(ctx->peer.connection->read, ctx->timeout);
1541         ngx_add_timer(ctx->peer.connection->write, ctx->timeout);
1542     }
1543 
1544     if (rc == NGX_OK) {
1545         ngx_ssl_ocsp_write_handler(ctx->peer.connection->write);
1546         return;
1547     }
1548 }
1549 
1550 
1551 static void
ngx_ssl_ocsp_write_handler(ngx_event_t * wev)1552 ngx_ssl_ocsp_write_handler(ngx_event_t *wev)
1553 {
1554     ssize_t              n, size;
1555     ngx_connection_t    *c;
1556     ngx_ssl_ocsp_ctx_t  *ctx;
1557 
1558     c = wev->data;
1559     ctx = c->data;
1560 
1561     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, wev->log, 0,
1562                    "ssl ocsp write handler");
1563 
1564     if (wev->timedout) {
1565         ngx_log_error(NGX_LOG_ERR, wev->log, NGX_ETIMEDOUT,
1566                       "OCSP responder timed out");
1567         ngx_ssl_ocsp_next(ctx);
1568         return;
1569     }
1570 
1571     size = ctx->request->last - ctx->request->pos;
1572 
1573     n = ngx_send(c, ctx->request->pos, size);
1574 
1575     if (n == NGX_ERROR) {
1576         ngx_ssl_ocsp_next(ctx);
1577         return;
1578     }
1579 
1580     if (n > 0) {
1581         ctx->request->pos += n;
1582 
1583         if (n == size) {
1584             wev->handler = ngx_ssl_ocsp_dummy_handler;
1585 
1586             if (wev->timer_set) {
1587                 ngx_del_timer(wev);
1588             }
1589 
1590             if (ngx_handle_write_event(wev, 0) != NGX_OK) {
1591                 ngx_ssl_ocsp_error(ctx);
1592             }
1593 
1594             return;
1595         }
1596     }
1597 
1598     if (!wev->timer_set && ctx->timeout) {
1599         ngx_add_timer(wev, ctx->timeout);
1600     }
1601 }
1602 
1603 
1604 static void
ngx_ssl_ocsp_read_handler(ngx_event_t * rev)1605 ngx_ssl_ocsp_read_handler(ngx_event_t *rev)
1606 {
1607     ssize_t              n, size;
1608     ngx_int_t            rc;
1609     ngx_connection_t    *c;
1610     ngx_ssl_ocsp_ctx_t  *ctx;
1611 
1612     c = rev->data;
1613     ctx = c->data;
1614 
1615     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, rev->log, 0,
1616                    "ssl ocsp read handler");
1617 
1618     if (rev->timedout) {
1619         ngx_log_error(NGX_LOG_ERR, rev->log, NGX_ETIMEDOUT,
1620                       "OCSP responder timed out");
1621         ngx_ssl_ocsp_next(ctx);
1622         return;
1623     }
1624 
1625     if (ctx->response == NULL) {
1626         ctx->response = ngx_create_temp_buf(ctx->pool, 16384);
1627         if (ctx->response == NULL) {
1628             ngx_ssl_ocsp_error(ctx);
1629             return;
1630         }
1631     }
1632 
1633     for ( ;; ) {
1634 
1635         size = ctx->response->end - ctx->response->last;
1636 
1637         n = ngx_recv(c, ctx->response->last, size);
1638 
1639         if (n > 0) {
1640             ctx->response->last += n;
1641 
1642             rc = ctx->process(ctx);
1643 
1644             if (rc == NGX_ERROR) {
1645                 ngx_ssl_ocsp_next(ctx);
1646                 return;
1647             }
1648 
1649             continue;
1650         }
1651 
1652         if (n == NGX_AGAIN) {
1653 
1654             if (ngx_handle_read_event(rev, 0) != NGX_OK) {
1655                 ngx_ssl_ocsp_error(ctx);
1656             }
1657 
1658             return;
1659         }
1660 
1661         break;
1662     }
1663 
1664     ctx->done = 1;
1665 
1666     rc = ctx->process(ctx);
1667 
1668     if (rc == NGX_DONE) {
1669         /* ctx->handler() was called */
1670         return;
1671     }
1672 
1673     ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1674                   "OCSP responder prematurely closed connection");
1675 
1676     ngx_ssl_ocsp_next(ctx);
1677 }
1678 
1679 
1680 static void
ngx_ssl_ocsp_dummy_handler(ngx_event_t * ev)1681 ngx_ssl_ocsp_dummy_handler(ngx_event_t *ev)
1682 {
1683     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0,
1684                    "ssl ocsp dummy handler");
1685 }
1686 
1687 
1688 static ngx_int_t
ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t * ctx)1689 ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx)
1690 {
1691     int            len;
1692     u_char        *p;
1693     uintptr_t      escape;
1694     ngx_str_t      binary, base64;
1695     ngx_buf_t     *b;
1696     OCSP_CERTID   *id;
1697     OCSP_REQUEST  *ocsp;
1698 
1699     ocsp = OCSP_REQUEST_new();
1700     if (ocsp == NULL) {
1701         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1702                       "OCSP_REQUEST_new() failed");
1703         return NGX_ERROR;
1704     }
1705 
1706     id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
1707     if (id == NULL) {
1708         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1709                       "OCSP_cert_to_id() failed");
1710         goto failed;
1711     }
1712 
1713     if (OCSP_request_add0_id(ocsp, id) == NULL) {
1714         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1715                       "OCSP_request_add0_id() failed");
1716         OCSP_CERTID_free(id);
1717         goto failed;
1718     }
1719 
1720     len = i2d_OCSP_REQUEST(ocsp, NULL);
1721     if (len <= 0) {
1722         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1723                       "i2d_OCSP_REQUEST() failed");
1724         goto failed;
1725     }
1726 
1727     binary.len = len;
1728     binary.data = ngx_palloc(ctx->pool, len);
1729     if (binary.data == NULL) {
1730         goto failed;
1731     }
1732 
1733     p = binary.data;
1734     len = i2d_OCSP_REQUEST(ocsp, &p);
1735     if (len <= 0) {
1736         ngx_ssl_error(NGX_LOG_EMERG, ctx->log, 0,
1737                       "i2d_OCSP_REQUEST() failed");
1738         goto failed;
1739     }
1740 
1741     base64.len = ngx_base64_encoded_length(binary.len);
1742     base64.data = ngx_palloc(ctx->pool, base64.len);
1743     if (base64.data == NULL) {
1744         goto failed;
1745     }
1746 
1747     ngx_encode_base64(&base64, &binary);
1748 
1749     escape = ngx_escape_uri(NULL, base64.data, base64.len,
1750                             NGX_ESCAPE_URI_COMPONENT);
1751 
1752     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1753                    "ssl ocsp request length %z, escape %d",
1754                    base64.len, (int) escape);
1755 
1756     len = sizeof("GET ") - 1 + ctx->uri.len + sizeof("/") - 1
1757           + base64.len + 2 * escape + sizeof(" HTTP/1.0" CRLF) - 1
1758           + sizeof("Host: ") - 1 + ctx->host.len + sizeof(CRLF) - 1
1759           + sizeof(CRLF) - 1;
1760 
1761     b = ngx_create_temp_buf(ctx->pool, len);
1762     if (b == NULL) {
1763         goto failed;
1764     }
1765 
1766     p = b->last;
1767 
1768     p = ngx_cpymem(p, "GET ", sizeof("GET ") - 1);
1769     p = ngx_cpymem(p, ctx->uri.data, ctx->uri.len);
1770 
1771     if (ctx->uri.data[ctx->uri.len - 1] != '/') {
1772         *p++ = '/';
1773     }
1774 
1775     if (escape == 0) {
1776         p = ngx_cpymem(p, base64.data, base64.len);
1777 
1778     } else {
1779         p = (u_char *) ngx_escape_uri(p, base64.data, base64.len,
1780                                       NGX_ESCAPE_URI_COMPONENT);
1781     }
1782 
1783     p = ngx_cpymem(p, " HTTP/1.0" CRLF, sizeof(" HTTP/1.0" CRLF) - 1);
1784     p = ngx_cpymem(p, "Host: ", sizeof("Host: ") - 1);
1785     p = ngx_cpymem(p, ctx->host.data, ctx->host.len);
1786     *p++ = CR; *p++ = LF;
1787 
1788     /* add "\r\n" at the header end */
1789     *p++ = CR; *p++ = LF;
1790 
1791     b->last = p;
1792     ctx->request = b;
1793 
1794     OCSP_REQUEST_free(ocsp);
1795 
1796     return NGX_OK;
1797 
1798 failed:
1799 
1800     OCSP_REQUEST_free(ocsp);
1801 
1802     return NGX_ERROR;
1803 }
1804 
1805 
1806 static ngx_int_t
ngx_ssl_ocsp_process_status_line(ngx_ssl_ocsp_ctx_t * ctx)1807 ngx_ssl_ocsp_process_status_line(ngx_ssl_ocsp_ctx_t *ctx)
1808 {
1809     ngx_int_t  rc;
1810 
1811     rc = ngx_ssl_ocsp_parse_status_line(ctx);
1812 
1813     if (rc == NGX_OK) {
1814         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1815                        "ssl ocsp status %ui \"%*s\"",
1816                        ctx->code,
1817                        ctx->header_end - ctx->header_start,
1818                        ctx->header_start);
1819 
1820         ctx->process = ngx_ssl_ocsp_process_headers;
1821         return ctx->process(ctx);
1822     }
1823 
1824     if (rc == NGX_AGAIN) {
1825         return NGX_AGAIN;
1826     }
1827 
1828     /* rc == NGX_ERROR */
1829 
1830     ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1831                   "OCSP responder sent invalid response");
1832 
1833     return NGX_ERROR;
1834 }
1835 
1836 
1837 static ngx_int_t
ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t * ctx)1838 ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t *ctx)
1839 {
1840     u_char      ch;
1841     u_char     *p;
1842     ngx_buf_t  *b;
1843     enum {
1844         sw_start = 0,
1845         sw_H,
1846         sw_HT,
1847         sw_HTT,
1848         sw_HTTP,
1849         sw_first_major_digit,
1850         sw_major_digit,
1851         sw_first_minor_digit,
1852         sw_minor_digit,
1853         sw_status,
1854         sw_space_after_status,
1855         sw_status_text,
1856         sw_almost_done
1857     } state;
1858 
1859     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1860                    "ssl ocsp process status line");
1861 
1862     state = ctx->state;
1863     b = ctx->response;
1864 
1865     for (p = b->pos; p < b->last; p++) {
1866         ch = *p;
1867 
1868         switch (state) {
1869 
1870         /* "HTTP/" */
1871         case sw_start:
1872             switch (ch) {
1873             case 'H':
1874                 state = sw_H;
1875                 break;
1876             default:
1877                 return NGX_ERROR;
1878             }
1879             break;
1880 
1881         case sw_H:
1882             switch (ch) {
1883             case 'T':
1884                 state = sw_HT;
1885                 break;
1886             default:
1887                 return NGX_ERROR;
1888             }
1889             break;
1890 
1891         case sw_HT:
1892             switch (ch) {
1893             case 'T':
1894                 state = sw_HTT;
1895                 break;
1896             default:
1897                 return NGX_ERROR;
1898             }
1899             break;
1900 
1901         case sw_HTT:
1902             switch (ch) {
1903             case 'P':
1904                 state = sw_HTTP;
1905                 break;
1906             default:
1907                 return NGX_ERROR;
1908             }
1909             break;
1910 
1911         case sw_HTTP:
1912             switch (ch) {
1913             case '/':
1914                 state = sw_first_major_digit;
1915                 break;
1916             default:
1917                 return NGX_ERROR;
1918             }
1919             break;
1920 
1921         /* the first digit of major HTTP version */
1922         case sw_first_major_digit:
1923             if (ch < '1' || ch > '9') {
1924                 return NGX_ERROR;
1925             }
1926 
1927             state = sw_major_digit;
1928             break;
1929 
1930         /* the major HTTP version or dot */
1931         case sw_major_digit:
1932             if (ch == '.') {
1933                 state = sw_first_minor_digit;
1934                 break;
1935             }
1936 
1937             if (ch < '0' || ch > '9') {
1938                 return NGX_ERROR;
1939             }
1940 
1941             break;
1942 
1943         /* the first digit of minor HTTP version */
1944         case sw_first_minor_digit:
1945             if (ch < '0' || ch > '9') {
1946                 return NGX_ERROR;
1947             }
1948 
1949             state = sw_minor_digit;
1950             break;
1951 
1952         /* the minor HTTP version or the end of the request line */
1953         case sw_minor_digit:
1954             if (ch == ' ') {
1955                 state = sw_status;
1956                 break;
1957             }
1958 
1959             if (ch < '0' || ch > '9') {
1960                 return NGX_ERROR;
1961             }
1962 
1963             break;
1964 
1965         /* HTTP status code */
1966         case sw_status:
1967             if (ch == ' ') {
1968                 break;
1969             }
1970 
1971             if (ch < '0' || ch > '9') {
1972                 return NGX_ERROR;
1973             }
1974 
1975             ctx->code = ctx->code * 10 + (ch - '0');
1976 
1977             if (++ctx->count == 3) {
1978                 state = sw_space_after_status;
1979                 ctx->header_start = p - 2;
1980             }
1981 
1982             break;
1983 
1984         /* space or end of line */
1985         case sw_space_after_status:
1986             switch (ch) {
1987             case ' ':
1988                 state = sw_status_text;
1989                 break;
1990             case '.':                    /* IIS may send 403.1, 403.2, etc */
1991                 state = sw_status_text;
1992                 break;
1993             case CR:
1994                 state = sw_almost_done;
1995                 break;
1996             case LF:
1997                 ctx->header_end = p;
1998                 goto done;
1999             default:
2000                 return NGX_ERROR;
2001             }
2002             break;
2003 
2004         /* any text until end of line */
2005         case sw_status_text:
2006             switch (ch) {
2007             case CR:
2008                 state = sw_almost_done;
2009                 break;
2010             case LF:
2011                 ctx->header_end = p;
2012                 goto done;
2013             }
2014             break;
2015 
2016         /* end of status line */
2017         case sw_almost_done:
2018             switch (ch) {
2019             case LF:
2020                 ctx->header_end = p - 1;
2021                 goto done;
2022             default:
2023                 return NGX_ERROR;
2024             }
2025         }
2026     }
2027 
2028     b->pos = p;
2029     ctx->state = state;
2030 
2031     return NGX_AGAIN;
2032 
2033 done:
2034 
2035     b->pos = p + 1;
2036     ctx->state = sw_start;
2037 
2038     return NGX_OK;
2039 }
2040 
2041 
2042 static ngx_int_t
ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t * ctx)2043 ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx)
2044 {
2045     size_t     len;
2046     ngx_int_t  rc;
2047 
2048     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
2049                    "ssl ocsp process headers");
2050 
2051     for ( ;; ) {
2052         rc = ngx_ssl_ocsp_parse_header_line(ctx);
2053 
2054         if (rc == NGX_OK) {
2055 
2056             ngx_log_debug4(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
2057                            "ssl ocsp header \"%*s: %*s\"",
2058                            ctx->header_name_end - ctx->header_name_start,
2059                            ctx->header_name_start,
2060                            ctx->header_end - ctx->header_start,
2061                            ctx->header_start);
2062 
2063             len = ctx->header_name_end - ctx->header_name_start;
2064 
2065             if (len == sizeof("Content-Type") - 1
2066                 && ngx_strncasecmp(ctx->header_name_start,
2067                                    (u_char *) "Content-Type",
2068                                    sizeof("Content-Type") - 1)
2069                    == 0)
2070             {
2071                 len = ctx->header_end - ctx->header_start;
2072 
2073                 if (len != sizeof("application/ocsp-response") - 1
2074                     || ngx_strncasecmp(ctx->header_start,
2075                                        (u_char *) "application/ocsp-response",
2076                                        sizeof("application/ocsp-response") - 1)
2077                        != 0)
2078                 {
2079                     ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
2080                                   "OCSP responder sent invalid "
2081                                   "\"Content-Type\" header: \"%*s\"",
2082                                   ctx->header_end - ctx->header_start,
2083                                   ctx->header_start);
2084                     return NGX_ERROR;
2085                 }
2086 
2087                 continue;
2088             }
2089 
2090             /* TODO: honor Content-Length */
2091 
2092             continue;
2093         }
2094 
2095         if (rc == NGX_DONE) {
2096             break;
2097         }
2098 
2099         if (rc == NGX_AGAIN) {
2100             return NGX_AGAIN;
2101         }
2102 
2103         /* rc == NGX_ERROR */
2104 
2105         ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
2106                       "OCSP responder sent invalid response");
2107 
2108         return NGX_ERROR;
2109     }
2110 
2111     ctx->process = ngx_ssl_ocsp_process_body;
2112     return ctx->process(ctx);
2113 }
2114 
2115 
2116 static ngx_int_t
ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t * ctx)2117 ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx)
2118 {
2119     u_char  c, ch, *p;
2120     enum {
2121         sw_start = 0,
2122         sw_name,
2123         sw_space_before_value,
2124         sw_value,
2125         sw_space_after_value,
2126         sw_almost_done,
2127         sw_header_almost_done
2128     } state;
2129 
2130     state = ctx->state;
2131 
2132     for (p = ctx->response->pos; p < ctx->response->last; p++) {
2133         ch = *p;
2134 
2135 #if 0
2136         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
2137                        "s:%d in:'%02Xd:%c'", state, ch, ch);
2138 #endif
2139 
2140         switch (state) {
2141 
2142         /* first char */
2143         case sw_start:
2144 
2145             switch (ch) {
2146             case CR:
2147                 ctx->header_end = p;
2148                 state = sw_header_almost_done;
2149                 break;
2150             case LF:
2151                 ctx->header_end = p;
2152                 goto header_done;
2153             default:
2154                 state = sw_name;
2155                 ctx->header_name_start = p;
2156 
2157                 c = (u_char) (ch | 0x20);
2158                 if (c >= 'a' && c <= 'z') {
2159                     break;
2160                 }
2161 
2162                 if (ch >= '0' && ch <= '9') {
2163                     break;
2164                 }
2165 
2166                 return NGX_ERROR;
2167             }
2168             break;
2169 
2170         /* header name */
2171         case sw_name:
2172             c = (u_char) (ch | 0x20);
2173             if (c >= 'a' && c <= 'z') {
2174                 break;
2175             }
2176 
2177             if (ch == ':') {
2178                 ctx->header_name_end = p;
2179                 state = sw_space_before_value;
2180                 break;
2181             }
2182 
2183             if (ch == '-') {
2184                 break;
2185             }
2186 
2187             if (ch >= '0' && ch <= '9') {
2188                 break;
2189             }
2190 
2191             if (ch == CR) {
2192                 ctx->header_name_end = p;
2193                 ctx->header_start = p;
2194                 ctx->header_end = p;
2195                 state = sw_almost_done;
2196                 break;
2197             }
2198 
2199             if (ch == LF) {
2200                 ctx->header_name_end = p;
2201                 ctx->header_start = p;
2202                 ctx->header_end = p;
2203                 goto done;
2204             }
2205 
2206             return NGX_ERROR;
2207 
2208         /* space* before header value */
2209         case sw_space_before_value:
2210             switch (ch) {
2211             case ' ':
2212                 break;
2213             case CR:
2214                 ctx->header_start = p;
2215                 ctx->header_end = p;
2216                 state = sw_almost_done;
2217                 break;
2218             case LF:
2219                 ctx->header_start = p;
2220                 ctx->header_end = p;
2221                 goto done;
2222             default:
2223                 ctx->header_start = p;
2224                 state = sw_value;
2225                 break;
2226             }
2227             break;
2228 
2229         /* header value */
2230         case sw_value:
2231             switch (ch) {
2232             case ' ':
2233                 ctx->header_end = p;
2234                 state = sw_space_after_value;
2235                 break;
2236             case CR:
2237                 ctx->header_end = p;
2238                 state = sw_almost_done;
2239                 break;
2240             case LF:
2241                 ctx->header_end = p;
2242                 goto done;
2243             }
2244             break;
2245 
2246         /* space* before end of header line */
2247         case sw_space_after_value:
2248             switch (ch) {
2249             case ' ':
2250                 break;
2251             case CR:
2252                 state = sw_almost_done;
2253                 break;
2254             case LF:
2255                 goto done;
2256             default:
2257                 state = sw_value;
2258                 break;
2259             }
2260             break;
2261 
2262         /* end of header line */
2263         case sw_almost_done:
2264             switch (ch) {
2265             case LF:
2266                 goto done;
2267             default:
2268                 return NGX_ERROR;
2269             }
2270 
2271         /* end of header */
2272         case sw_header_almost_done:
2273             switch (ch) {
2274             case LF:
2275                 goto header_done;
2276             default:
2277                 return NGX_ERROR;
2278             }
2279         }
2280     }
2281 
2282     ctx->response->pos = p;
2283     ctx->state = state;
2284 
2285     return NGX_AGAIN;
2286 
2287 done:
2288 
2289     ctx->response->pos = p + 1;
2290     ctx->state = sw_start;
2291 
2292     return NGX_OK;
2293 
2294 header_done:
2295 
2296     ctx->response->pos = p + 1;
2297     ctx->state = sw_start;
2298 
2299     return NGX_DONE;
2300 }
2301 
2302 
2303 static ngx_int_t
ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t * ctx)2304 ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx)
2305 {
2306     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
2307                    "ssl ocsp process body");
2308 
2309     if (ctx->done) {
2310         ctx->handler(ctx);
2311         return NGX_DONE;
2312     }
2313 
2314     return NGX_AGAIN;
2315 }
2316 
2317 
2318 static ngx_int_t
ngx_ssl_ocsp_verify(ngx_ssl_ocsp_ctx_t * ctx)2319 ngx_ssl_ocsp_verify(ngx_ssl_ocsp_ctx_t *ctx)
2320 {
2321     int                    n;
2322     size_t                 len;
2323     X509_STORE            *store;
2324     const u_char          *p;
2325     OCSP_CERTID           *id;
2326     OCSP_RESPONSE         *ocsp;
2327     OCSP_BASICRESP        *basic;
2328     ASN1_GENERALIZEDTIME  *thisupdate, *nextupdate;
2329 
2330     ocsp = NULL;
2331     basic = NULL;
2332     id = NULL;
2333 
2334     if (ctx->code != 200) {
2335         goto error;
2336     }
2337 
2338     /* check the response */
2339 
2340     len = ctx->response->last - ctx->response->pos;
2341     p = ctx->response->pos;
2342 
2343     ocsp = d2i_OCSP_RESPONSE(NULL, &p, len);
2344     if (ocsp == NULL) {
2345         ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
2346                       "d2i_OCSP_RESPONSE() failed");
2347         goto error;
2348     }
2349 
2350     n = OCSP_response_status(ocsp);
2351 
2352     if (n != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
2353         ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
2354                       "OCSP response not successful (%d: %s)",
2355                       n, OCSP_response_status_str(n));
2356         goto error;
2357     }
2358 
2359     basic = OCSP_response_get1_basic(ocsp);
2360     if (basic == NULL) {
2361         ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
2362                       "OCSP_response_get1_basic() failed");
2363         goto error;
2364     }
2365 
2366     store = SSL_CTX_get_cert_store(ctx->ssl_ctx);
2367     if (store == NULL) {
2368         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
2369                       "SSL_CTX_get_cert_store() failed");
2370         goto error;
2371     }
2372 
2373     if (OCSP_basic_verify(basic, ctx->chain, store, ctx->flags) != 1) {
2374         ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
2375                       "OCSP_basic_verify() failed");
2376         goto error;
2377     }
2378 
2379     id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
2380     if (id == NULL) {
2381         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
2382                       "OCSP_cert_to_id() failed");
2383         goto error;
2384     }
2385 
2386     if (OCSP_resp_find_status(basic, id, &ctx->status, NULL, NULL,
2387                               &thisupdate, &nextupdate)
2388         != 1)
2389     {
2390         ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
2391                       "certificate status not found in the OCSP response");
2392         goto error;
2393     }
2394 
2395     if (OCSP_check_validity(thisupdate, nextupdate, 300, -1) != 1) {
2396         ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
2397                       "OCSP_check_validity() failed");
2398         goto error;
2399     }
2400 
2401     if (nextupdate) {
2402         ctx->valid = ngx_ssl_stapling_time(nextupdate);
2403         if (ctx->valid == (time_t) NGX_ERROR) {
2404             ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
2405                           "invalid nextUpdate time in certificate status");
2406             goto error;
2407         }
2408 
2409     } else {
2410         ctx->valid = NGX_MAX_TIME_T_VALUE;
2411     }
2412 
2413     OCSP_CERTID_free(id);
2414     OCSP_BASICRESP_free(basic);
2415     OCSP_RESPONSE_free(ocsp);
2416 
2417     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
2418                    "ssl ocsp response, %s, %uz",
2419                    OCSP_cert_status_str(ctx->status), len);
2420 
2421     return NGX_OK;
2422 
2423 error:
2424 
2425     if (id) {
2426         OCSP_CERTID_free(id);
2427     }
2428 
2429     if (basic) {
2430         OCSP_BASICRESP_free(basic);
2431     }
2432 
2433     if (ocsp) {
2434         OCSP_RESPONSE_free(ocsp);
2435     }
2436 
2437     return NGX_ERROR;
2438 }
2439 
2440 
2441 ngx_int_t
ngx_ssl_ocsp_cache_init(ngx_shm_zone_t * shm_zone,void * data)2442 ngx_ssl_ocsp_cache_init(ngx_shm_zone_t *shm_zone, void *data)
2443 {
2444     size_t                 len;
2445     ngx_slab_pool_t       *shpool;
2446     ngx_ssl_ocsp_cache_t  *cache;
2447 
2448     if (data) {
2449         shm_zone->data = data;
2450         return NGX_OK;
2451     }
2452 
2453     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
2454 
2455     if (shm_zone->shm.exists) {
2456         shm_zone->data = shpool->data;
2457         return NGX_OK;
2458     }
2459 
2460     cache = ngx_slab_alloc(shpool, sizeof(ngx_ssl_ocsp_cache_t));
2461     if (cache == NULL) {
2462         return NGX_ERROR;
2463     }
2464 
2465     shpool->data = cache;
2466     shm_zone->data = cache;
2467 
2468     ngx_rbtree_init(&cache->rbtree, &cache->sentinel,
2469                     ngx_str_rbtree_insert_value);
2470 
2471     ngx_queue_init(&cache->expire_queue);
2472 
2473     len = sizeof(" in OCSP cache \"\"") + shm_zone->shm.name.len;
2474 
2475     shpool->log_ctx = ngx_slab_alloc(shpool, len);
2476     if (shpool->log_ctx == NULL) {
2477         return NGX_ERROR;
2478     }
2479 
2480     ngx_sprintf(shpool->log_ctx, " in OCSP cache \"%V\"%Z",
2481                 &shm_zone->shm.name);
2482 
2483     shpool->log_nomem = 0;
2484 
2485     return NGX_OK;
2486 }
2487 
2488 
2489 static ngx_int_t
ngx_ssl_ocsp_cache_lookup(ngx_ssl_ocsp_ctx_t * ctx)2490 ngx_ssl_ocsp_cache_lookup(ngx_ssl_ocsp_ctx_t *ctx)
2491 {
2492     uint32_t                    hash;
2493     ngx_shm_zone_t             *shm_zone;
2494     ngx_slab_pool_t            *shpool;
2495     ngx_ssl_ocsp_cache_t       *cache;
2496     ngx_ssl_ocsp_cache_node_t  *node;
2497 
2498     shm_zone = ctx->shm_zone;
2499 
2500     if (shm_zone == NULL) {
2501         return NGX_DECLINED;
2502     }
2503 
2504     if (ngx_ssl_ocsp_create_key(ctx) != NGX_OK) {
2505         return NGX_ERROR;
2506     }
2507 
2508     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0, "ssl ocsp cache lookup");
2509 
2510     cache = shm_zone->data;
2511     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
2512     hash = ngx_hash_key(ctx->key.data, ctx->key.len);
2513 
2514     ngx_shmtx_lock(&shpool->mutex);
2515 
2516     node = (ngx_ssl_ocsp_cache_node_t *)
2517                ngx_str_rbtree_lookup(&cache->rbtree, &ctx->key, hash);
2518 
2519     if (node) {
2520         if (node->valid > ngx_time()) {
2521             ctx->status = node->status;
2522             ngx_shmtx_unlock(&shpool->mutex);
2523 
2524             ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
2525                            "ssl ocsp cache hit, %s",
2526                            OCSP_cert_status_str(ctx->status));
2527 
2528             return NGX_OK;
2529         }
2530 
2531         ngx_queue_remove(&node->queue);
2532         ngx_rbtree_delete(&cache->rbtree, &node->node.node);
2533         ngx_slab_free_locked(shpool, node);
2534 
2535         ngx_shmtx_unlock(&shpool->mutex);
2536 
2537         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
2538                        "ssl ocsp cache expired");
2539 
2540         return NGX_DECLINED;
2541     }
2542 
2543     ngx_shmtx_unlock(&shpool->mutex);
2544 
2545     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0, "ssl ocsp cache miss");
2546 
2547     return NGX_DECLINED;
2548 }
2549 
2550 
2551 static ngx_int_t
ngx_ssl_ocsp_cache_store(ngx_ssl_ocsp_ctx_t * ctx)2552 ngx_ssl_ocsp_cache_store(ngx_ssl_ocsp_ctx_t *ctx)
2553 {
2554     time_t                      now, valid;
2555     uint32_t                    hash;
2556     ngx_queue_t                *q;
2557     ngx_shm_zone_t             *shm_zone;
2558     ngx_slab_pool_t            *shpool;
2559     ngx_ssl_ocsp_cache_t       *cache;
2560     ngx_ssl_ocsp_cache_node_t  *node;
2561 
2562     shm_zone = ctx->shm_zone;
2563 
2564     if (shm_zone == NULL) {
2565         return NGX_OK;
2566     }
2567 
2568     valid = ctx->valid;
2569 
2570     now = ngx_time();
2571 
2572     if (valid < now) {
2573         return NGX_OK;
2574     }
2575 
2576     if (valid == NGX_MAX_TIME_T_VALUE) {
2577         valid = now + 3600;
2578     }
2579 
2580     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
2581                    "ssl ocsp cache store, valid:%T", valid - now);
2582 
2583     cache = shm_zone->data;
2584     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
2585     hash = ngx_hash_key(ctx->key.data, ctx->key.len);
2586 
2587     ngx_shmtx_lock(&shpool->mutex);
2588 
2589     node = ngx_slab_calloc_locked(shpool,
2590                              sizeof(ngx_ssl_ocsp_cache_node_t) + ctx->key.len);
2591     if (node == NULL) {
2592 
2593         if (!ngx_queue_empty(&cache->expire_queue)) {
2594             q = ngx_queue_last(&cache->expire_queue);
2595             node = ngx_queue_data(q, ngx_ssl_ocsp_cache_node_t, queue);
2596 
2597             ngx_rbtree_delete(&cache->rbtree, &node->node.node);
2598             ngx_queue_remove(q);
2599             ngx_slab_free_locked(shpool, node);
2600 
2601             node = ngx_slab_alloc_locked(shpool,
2602                              sizeof(ngx_ssl_ocsp_cache_node_t) + ctx->key.len);
2603         }
2604 
2605         if (node == NULL) {
2606             ngx_shmtx_unlock(&shpool->mutex);
2607             ngx_log_error(NGX_LOG_ALERT, ctx->log, 0,
2608                           "could not allocate new entry%s", shpool->log_ctx);
2609             return NGX_ERROR;
2610         }
2611     }
2612 
2613     node->node.str.len = ctx->key.len;
2614     node->node.str.data = (u_char *) node + sizeof(ngx_ssl_ocsp_cache_node_t);
2615     ngx_memcpy(node->node.str.data, ctx->key.data, ctx->key.len);
2616     node->node.node.key = hash;
2617     node->status = ctx->status;
2618     node->valid = valid;
2619 
2620     ngx_rbtree_insert(&cache->rbtree, &node->node.node);
2621     ngx_queue_insert_head(&cache->expire_queue, &node->queue);
2622 
2623     ngx_shmtx_unlock(&shpool->mutex);
2624 
2625     return NGX_OK;
2626 }
2627 
2628 
2629 static ngx_int_t
ngx_ssl_ocsp_create_key(ngx_ssl_ocsp_ctx_t * ctx)2630 ngx_ssl_ocsp_create_key(ngx_ssl_ocsp_ctx_t *ctx)
2631 {
2632     u_char        *p;
2633     X509_NAME     *name;
2634     ASN1_INTEGER  *serial;
2635 
2636     p = ngx_pnalloc(ctx->pool, 60);
2637     if (p == NULL) {
2638         return NGX_ERROR;
2639     }
2640 
2641     ctx->key.data = p;
2642     ctx->key.len = 60;
2643 
2644     name = X509_get_subject_name(ctx->issuer);
2645     if (X509_NAME_digest(name, EVP_sha1(), p, NULL) == 0) {
2646         return NGX_ERROR;
2647     }
2648 
2649     p += 20;
2650 
2651     if (X509_pubkey_digest(ctx->issuer, EVP_sha1(), p, NULL) == 0) {
2652         return NGX_ERROR;
2653     }
2654 
2655     p += 20;
2656 
2657     serial = X509_get_serialNumber(ctx->cert);
2658     if (serial->length > 20) {
2659         return NGX_ERROR;
2660     }
2661 
2662     p = ngx_cpymem(p, serial->data, serial->length);
2663     ngx_memzero(p, 20 - serial->length);
2664 
2665     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
2666                    "ssl ocsp key %xV", &ctx->key);
2667 
2668     return NGX_OK;
2669 }
2670 
2671 
2672 static u_char *
ngx_ssl_ocsp_log_error(ngx_log_t * log,u_char * buf,size_t len)2673 ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len)
2674 {
2675     u_char              *p;
2676     ngx_ssl_ocsp_ctx_t  *ctx;
2677 
2678     p = buf;
2679 
2680     if (log->action) {
2681         p = ngx_snprintf(buf, len, " while %s", log->action);
2682         len -= p - buf;
2683         buf = p;
2684     }
2685 
2686     ctx = log->data;
2687 
2688     if (ctx) {
2689         p = ngx_snprintf(buf, len, ", responder: %V", &ctx->host);
2690         len -= p - buf;
2691         buf = p;
2692     }
2693 
2694     if (ctx && ctx->peer.name) {
2695         p = ngx_snprintf(buf, len, ", peer: %V", ctx->peer.name);
2696         len -= p - buf;
2697         buf = p;
2698     }
2699 
2700     if (ctx && ctx->name) {
2701         p = ngx_snprintf(buf, len, ", certificate: \"%s\"", ctx->name);
2702         len -= p - buf;
2703         buf = p;
2704     }
2705 
2706     return p;
2707 }
2708 
2709 
2710 #else
2711 
2712 
2713 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)2714 ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file,
2715     ngx_str_t *responder, ngx_uint_t verify)
2716 {
2717     ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
2718                   "\"ssl_stapling\" ignored, not supported");
2719 
2720     return NGX_OK;
2721 }
2722 
2723 
2724 ngx_int_t
ngx_ssl_stapling_resolver(ngx_conf_t * cf,ngx_ssl_t * ssl,ngx_resolver_t * resolver,ngx_msec_t resolver_timeout)2725 ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
2726     ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)
2727 {
2728     return NGX_OK;
2729 }
2730 
2731 
2732 ngx_int_t
ngx_ssl_ocsp(ngx_conf_t * cf,ngx_ssl_t * ssl,ngx_str_t * responder,ngx_uint_t depth,ngx_shm_zone_t * shm_zone)2733 ngx_ssl_ocsp(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *responder,
2734     ngx_uint_t depth, ngx_shm_zone_t *shm_zone)
2735 {
2736     ngx_log_error(NGX_LOG_EMERG, ssl->log, 0,
2737                   "\"ssl_ocsp\" is not supported on this platform");
2738 
2739     return NGX_ERROR;
2740 }
2741 
2742 
2743 ngx_int_t
ngx_ssl_ocsp_resolver(ngx_conf_t * cf,ngx_ssl_t * ssl,ngx_resolver_t * resolver,ngx_msec_t resolver_timeout)2744 ngx_ssl_ocsp_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
2745     ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)
2746 {
2747     return NGX_OK;
2748 }
2749 
2750 
2751 ngx_int_t
ngx_ssl_ocsp_validate(ngx_connection_t * c)2752 ngx_ssl_ocsp_validate(ngx_connection_t *c)
2753 {
2754     return NGX_OK;
2755 }
2756 
2757 
2758 ngx_int_t
ngx_ssl_ocsp_get_status(ngx_connection_t * c,const char ** s)2759 ngx_ssl_ocsp_get_status(ngx_connection_t *c, const char **s)
2760 {
2761     return NGX_OK;
2762 }
2763 
2764 
2765 void
ngx_ssl_ocsp_cleanup(ngx_connection_t * c)2766 ngx_ssl_ocsp_cleanup(ngx_connection_t *c)
2767 {
2768 }
2769 
2770 
2771 ngx_int_t
ngx_ssl_ocsp_cache_init(ngx_shm_zone_t * shm_zone,void * data)2772 ngx_ssl_ocsp_cache_init(ngx_shm_zone_t *shm_zone, void *data)
2773 {
2774     return NGX_OK;
2775 }
2776 
2777 
2778 #endif
2779