src/event/ngx_event_openssl_stapling.c - nginx-1.7.10

Data types defined

Functions defined

Source code


  1. /*
  2. * Copyright (C) Maxim Dounin
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <ngx_event.h>
  8. #include <ngx_event_connect.h>


  9. #if (!defined OPENSSL_NO_OCSP && defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB)


  10. typedef struct {
  11.     ngx_str_t                    staple;
  12.     ngx_msec_t                   timeout;

  13.     ngx_resolver_t              *resolver;
  14.     ngx_msec_t                   resolver_timeout;

  15.     ngx_addr_t                  *addrs;
  16.     ngx_str_t                    host;
  17.     ngx_str_t                    uri;
  18.     in_port_t                    port;

  19.     SSL_CTX                     *ssl_ctx;

  20.     X509                        *cert;
  21.     X509                        *issuer;

  22.     time_t                       valid;

  23.     unsigned                     verify:1;
  24.     unsigned                     loading:1;
  25. } ngx_ssl_stapling_t;


  26. typedef struct ngx_ssl_ocsp_ctx_s  ngx_ssl_ocsp_ctx_t;

  27. struct ngx_ssl_ocsp_ctx_s {
  28.     X509                        *cert;
  29.     X509                        *issuer;

  30.     ngx_uint_t                   naddrs;

  31.     ngx_addr_t                  *addrs;
  32.     ngx_str_t                    host;
  33.     ngx_str_t                    uri;
  34.     in_port_t                    port;

  35.     ngx_resolver_t              *resolver;
  36.     ngx_msec_t                   resolver_timeout;

  37.     ngx_msec_t                   timeout;

  38.     void                       (*handler)(ngx_ssl_ocsp_ctx_t *r);
  39.     void                        *data;

  40.     ngx_buf_t                   *request;
  41.     ngx_buf_t                   *response;
  42.     ngx_peer_connection_t        peer;

  43.     ngx_int_t                  (*process)(ngx_ssl_ocsp_ctx_t *r);

  44.     ngx_uint_t                   state;

  45.     ngx_uint_t                   code;
  46.     ngx_uint_t                   count;

  47.     ngx_uint_t                   done;

  48.     u_char                      *header_name_start;
  49.     u_char                      *header_name_end;
  50.     u_char                      *header_start;
  51.     u_char                      *header_end;

  52.     ngx_pool_t                  *pool;
  53.     ngx_log_t                   *log;
  54. };


  55. static ngx_int_t ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl,
  56.     ngx_str_t *file);
  57. static ngx_int_t ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl);
  58. static ngx_int_t ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl,
  59.     ngx_str_t *responder);

  60. static int ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn,
  61.     void *data);
  62. static void ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple);
  63. static void ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx);

  64. static void ngx_ssl_stapling_cleanup(void *data);

  65. static ngx_ssl_ocsp_ctx_t *ngx_ssl_ocsp_start(void);
  66. static void ngx_ssl_ocsp_done(ngx_ssl_ocsp_ctx_t *ctx);
  67. static void ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx);
  68. static void ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve);
  69. static void ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx);
  70. static void ngx_ssl_ocsp_write_handler(ngx_event_t *wev);
  71. static void ngx_ssl_ocsp_read_handler(ngx_event_t *rev);
  72. static void ngx_ssl_ocsp_dummy_handler(ngx_event_t *ev);

  73. static ngx_int_t ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx);
  74. static ngx_int_t ngx_ssl_ocsp_process_status_line(ngx_ssl_ocsp_ctx_t *ctx);
  75. static ngx_int_t ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t *ctx);
  76. static ngx_int_t ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx);
  77. static ngx_int_t ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx);
  78. static ngx_int_t ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx);

  79. static u_char *ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len);


  80. ngx_int_t
  81. ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file,
  82.     ngx_str_t *responder, ngx_uint_t verify)
  83. {
  84.     ngx_int_t                  rc;
  85.     ngx_pool_cleanup_t        *cln;
  86.     ngx_ssl_stapling_t        *staple;

  87.     staple = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_stapling_t));
  88.     if (staple == NULL) {
  89.         return NGX_ERROR;
  90.     }

  91.     cln = ngx_pool_cleanup_add(cf->pool, 0);
  92.     if (cln == NULL) {
  93.         return NGX_ERROR;
  94.     }

  95.     cln->handler = ngx_ssl_stapling_cleanup;
  96.     cln->data = staple;

  97.     if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_stapling_index, staple)
  98.         == 0)
  99.     {
  100.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  101.                       "SSL_CTX_set_ex_data() failed");
  102.         return NGX_ERROR;
  103.     }

  104.     staple->ssl_ctx = ssl->ctx;
  105.     staple->timeout = 60000;
  106.     staple->verify = verify;

  107.     if (file->len) {
  108.         /* use OCSP response from the file */

  109.         if (ngx_ssl_stapling_file(cf, ssl, file) != NGX_OK) {
  110.             return NGX_ERROR;
  111.         }

  112.         goto done;
  113.     }

  114.     rc = ngx_ssl_stapling_issuer(cf, ssl);

  115.     if (rc == NGX_DECLINED) {
  116.         return NGX_OK;
  117.     }

  118.     if (rc != NGX_OK) {
  119.         return NGX_ERROR;
  120.     }

  121.     rc = ngx_ssl_stapling_responder(cf, ssl, responder);

  122.     if (rc == NGX_DECLINED) {
  123.         return NGX_OK;
  124.     }

  125.     if (rc != NGX_OK) {
  126.         return NGX_ERROR;
  127.     }

  128. done:

  129.     SSL_CTX_set_tlsext_status_cb(ssl->ctx, ngx_ssl_certificate_status_callback);
  130.     SSL_CTX_set_tlsext_status_arg(ssl->ctx, staple);

  131.     return NGX_OK;
  132. }


  133. static ngx_int_t
  134. ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file)
  135. {
  136.     BIO                 *bio;
  137.     int                  len;
  138.     u_char              *p, *buf;
  139.     OCSP_RESPONSE       *response;
  140.     ngx_ssl_stapling_t  *staple;

  141.     staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index);

  142.     if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) {
  143.         return NGX_ERROR;
  144.     }

  145.     bio = BIO_new_file((char *) file->data, "r");
  146.     if (bio == NULL) {
  147.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  148.                       "BIO_new_file(\"%s\") failed", file->data);
  149.         return NGX_ERROR;
  150.     }

  151.     response = d2i_OCSP_RESPONSE_bio(bio, NULL);
  152.     if (response == NULL) {
  153.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  154.                       "d2i_OCSP_RESPONSE_bio(\"%s\") failed", file->data);
  155.         BIO_free(bio);
  156.         return NGX_ERROR;
  157.     }

  158.     len = i2d_OCSP_RESPONSE(response, NULL);
  159.     if (len <= 0) {
  160.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  161.                       "i2d_OCSP_RESPONSE(\"%s\") failed", file->data);
  162.         goto failed;
  163.     }

  164.     buf = ngx_alloc(len, ssl->log);
  165.     if (buf == NULL) {
  166.         goto failed;
  167.     }

  168.     p = buf;
  169.     len = i2d_OCSP_RESPONSE(response, &p);
  170.     if (len <= 0) {
  171.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  172.                       "i2d_OCSP_RESPONSE(\"%s\") failed", file->data);
  173.         ngx_free(buf);
  174.         goto failed;
  175.     }

  176.     OCSP_RESPONSE_free(response);
  177.     BIO_free(bio);

  178.     staple->staple.data = buf;
  179.     staple->staple.len = len;

  180.     return NGX_OK;

  181. failed:

  182.     OCSP_RESPONSE_free(response);
  183.     BIO_free(bio);

  184.     return NGX_ERROR;
  185. }


  186. static ngx_int_t
  187. ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl)
  188. {
  189.     int                  i, n, rc;
  190.     X509                *cert, *issuer;
  191.     X509_STORE          *store;
  192.     X509_STORE_CTX      *store_ctx;
  193.     STACK_OF(X509)      *chain;
  194.     ngx_ssl_stapling_t  *staple;

  195.     staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index);
  196.     cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);

  197. #if OPENSSL_VERSION_NUMBER >= 0x10001000L
  198.     SSL_CTX_get_extra_chain_certs(ssl->ctx, &chain);
  199. #else
  200.     chain = ssl->ctx->extra_certs;
  201. #endif

  202.     n = sk_X509_num(chain);

  203.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
  204.                    "SSL get issuer: %d extra certs", n);

  205.     for (i = 0; i < n; i++) {
  206.         issuer = sk_X509_value(chain, i);
  207.         if (X509_check_issued(issuer, cert) == X509_V_OK) {
  208.             CRYPTO_add(&issuer->references, 1, CRYPTO_LOCK_X509);

  209.             ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
  210.                            "SSL get issuer: found %p in extra certs", issuer);

  211.             staple->cert = cert;
  212.             staple->issuer = issuer;

  213.             return NGX_OK;
  214.         }
  215.     }

  216.     store = SSL_CTX_get_cert_store(ssl->ctx);
  217.     if (store == NULL) {
  218.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  219.                       "SSL_CTX_get_cert_store() failed");
  220.         return NGX_ERROR;
  221.     }

  222.     store_ctx = X509_STORE_CTX_new();
  223.     if (store_ctx == NULL) {
  224.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  225.                       "X509_STORE_CTX_new() failed");
  226.         return NGX_ERROR;
  227.     }

  228.     if (X509_STORE_CTX_init(store_ctx, store, NULL, NULL) == 0) {
  229.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  230.                       "X509_STORE_CTX_init() failed");
  231.         return NGX_ERROR;
  232.     }

  233.     rc = X509_STORE_CTX_get1_issuer(&issuer, store_ctx, cert);

  234.     if (rc == -1) {
  235.         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
  236.                       "X509_STORE_CTX_get1_issuer() failed");
  237.         X509_STORE_CTX_free(store_ctx);
  238.         return NGX_ERROR;
  239.     }

  240.     if (rc == 0) {
  241.         ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
  242.                       "\"ssl_stapling\" ignored, issuer certificate not found");
  243.         X509_STORE_CTX_free(store_ctx);
  244.         return NGX_DECLINED;
  245.     }

  246.     X509_STORE_CTX_free(store_ctx);

  247.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
  248.                    "SSL get issuer: found %p in cert store", issuer);

  249.     staple->cert = cert;
  250.     staple->issuer = issuer;

  251.     return NGX_OK;
  252. }


  253. static ngx_int_t
  254. ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *responder)
  255. {
  256.     ngx_url_t                  u;
  257.     char                      *s;
  258.     ngx_ssl_stapling_t        *staple;
  259.     STACK_OF(OPENSSL_STRING)  *aia;

  260.     staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index);

  261.     if (responder->len == 0) {

  262.         /* extract OCSP responder URL from certificate */

  263.         aia = X509_get1_ocsp(staple->cert);
  264.         if (aia == NULL) {
  265.             ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
  266.                           "\"ssl_stapling\" ignored, "
  267.                           "no OCSP responder URL in the certificate");
  268.             return NGX_DECLINED;
  269.         }

  270. #if OPENSSL_VERSION_NUMBER >= 0x10000000L
  271.         s = sk_OPENSSL_STRING_value(aia, 0);
  272. #else
  273.         s = sk_value(aia, 0);
  274. #endif
  275.         if (s == NULL) {
  276.             ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
  277.                           "\"ssl_stapling\" ignored, "
  278.                           "no OCSP responder URL in the certificate");
  279.             X509_email_free(aia);
  280.             return NGX_DECLINED;
  281.         }

  282.         responder->len = ngx_strlen(s);
  283.         responder->data = ngx_palloc(cf->pool, responder->len);
  284.         if (responder->data == NULL) {
  285.             X509_email_free(aia);
  286.             return NGX_ERROR;
  287.         }

  288.         ngx_memcpy(responder->data, s, responder->len);
  289.         X509_email_free(aia);
  290.     }

  291.     ngx_memzero(&u, sizeof(ngx_url_t));

  292.     u.url = *responder;
  293.     u.default_port = 80;
  294.     u.uri_part = 1;

  295.     if (u.url.len > 7
  296.         && ngx_strncasecmp(u.url.data, (u_char *) "http://", 7) == 0)
  297.     {
  298.         u.url.len -= 7;
  299.         u.url.data += 7;

  300.     } else {
  301.         ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
  302.                       "\"ssl_stapling\" ignored, "
  303.                       "invalid URL prefix in OCSP responder \"%V\"", &u.url);
  304.         return NGX_DECLINED;
  305.     }

  306.     if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
  307.         if (u.err) {
  308.             ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
  309.                           "\"ssl_stapling\" ignored, "
  310.                           "%s in OCSP responder \"%V\"", u.err, &u.url);
  311.             return NGX_DECLINED;
  312.         }

  313.         return NGX_ERROR;
  314.     }

  315.     staple->addrs = u.addrs;
  316.     staple->host = u.host;
  317.     staple->uri = u.uri;
  318.     staple->port = u.port;

  319.     if (staple->uri.len == 0) {
  320.         ngx_str_set(&staple->uri, "/");
  321.     }

  322.     return NGX_OK;
  323. }


  324. ngx_int_t
  325. ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
  326.     ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)
  327. {
  328.     ngx_ssl_stapling_t  *staple;

  329.     staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index);

  330.     staple->resolver = resolver;
  331.     staple->resolver_timeout = resolver_timeout;

  332.     return NGX_OK;
  333. }


  334. static int
  335. ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn, void *data)
  336. {
  337.     int                  rc;
  338.     u_char              *p;
  339.     ngx_connection_t    *c;
  340.     ngx_ssl_stapling_t  *staple;

  341.     c = ngx_ssl_get_connection(ssl_conn);

  342.     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
  343.                    "SSL certificate status callback");

  344.     staple = data;
  345.     rc = SSL_TLSEXT_ERR_NOACK;

  346.     if (staple->staple.len) {
  347.         /* we have to copy ocsp response as OpenSSL will free it by itself */

  348.         p = OPENSSL_malloc(staple->staple.len);
  349.         if (p == NULL) {
  350.             ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "OPENSSL_malloc() failed");
  351.             return SSL_TLSEXT_ERR_NOACK;
  352.         }

  353.         ngx_memcpy(p, staple->staple.data, staple->staple.len);

  354.         SSL_set_tlsext_status_ocsp_resp(ssl_conn, p, staple->staple.len);

  355.         rc = SSL_TLSEXT_ERR_OK;
  356.     }

  357.     ngx_ssl_stapling_update(staple);

  358.     return rc;
  359. }


  360. static void
  361. ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple)
  362. {
  363.     ngx_ssl_ocsp_ctx_t  *ctx;

  364.     if (staple->host.len == 0
  365.         || staple->loading || staple->valid >= ngx_time())
  366.     {
  367.         return;
  368.     }

  369.     staple->loading = 1;

  370.     ctx = ngx_ssl_ocsp_start();
  371.     if (ctx == NULL) {
  372.         return;
  373.     }

  374.     ctx->cert = staple->cert;
  375.     ctx->issuer = staple->issuer;

  376.     ctx->addrs = staple->addrs;
  377.     ctx->host = staple->host;
  378.     ctx->uri = staple->uri;
  379.     ctx->port = staple->port;
  380.     ctx->timeout = staple->timeout;

  381.     ctx->resolver = staple->resolver;
  382.     ctx->resolver_timeout = staple->resolver_timeout;

  383.     ctx->handler = ngx_ssl_stapling_ocsp_handler;
  384.     ctx->data = staple;

  385.     ngx_ssl_ocsp_request(ctx);

  386.     return;
  387. }


  388. static void
  389. ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
  390. {
  391. #if OPENSSL_VERSION_NUMBER >= 0x0090707fL
  392.     const
  393. #endif
  394.     u_char                *p;
  395.     int                    n;
  396.     size_t                 len;
  397.     ngx_str_t              response;
  398.     X509_STORE            *store;
  399.     STACK_OF(X509)        *chain;
  400.     OCSP_CERTID           *id;
  401.     OCSP_RESPONSE         *ocsp;
  402.     OCSP_BASICRESP        *basic;
  403.     ngx_ssl_stapling_t    *staple;
  404.     ASN1_GENERALIZEDTIME  *thisupdate, *nextupdate;

  405.     staple = ctx->data;
  406.     ocsp = NULL;
  407.     basic = NULL;
  408.     id = NULL;

  409.     if (ctx->code != 200) {
  410.         goto error;
  411.     }

  412.     /* check the response */

  413.     len = ctx->response->last - ctx->response->pos;
  414.     p = ctx->response->pos;

  415.     ocsp = d2i_OCSP_RESPONSE(NULL, &p, len);
  416.     if (ocsp == NULL) {
  417.         ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
  418.                       "d2i_OCSP_RESPONSE() failed");
  419.         goto error;
  420.     }

  421.     n = OCSP_response_status(ocsp);

  422.     if (n != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
  423.         ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
  424.                       "OCSP response not successful (%d: %s)",
  425.                       n, OCSP_response_status_str(n));
  426.         goto error;
  427.     }

  428.     basic = OCSP_response_get1_basic(ocsp);
  429.     if (basic == NULL) {
  430.         ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
  431.                       "OCSP_response_get1_basic() failed");
  432.         goto error;
  433.     }

  434.     store = SSL_CTX_get_cert_store(staple->ssl_ctx);
  435.     if (store == NULL) {
  436.         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
  437.                       "SSL_CTX_get_cert_store() failed");
  438.         goto error;
  439.     }

  440. #if OPENSSL_VERSION_NUMBER >= 0x10001000L
  441.     SSL_CTX_get_extra_chain_certs(staple->ssl_ctx, &chain);
  442. #else
  443.     chain = staple->ssl_ctx->extra_certs;
  444. #endif

  445.     if (OCSP_basic_verify(basic, chain, store,
  446.                           staple->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY)
  447.         != 1)
  448.     {
  449.         ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
  450.                       "OCSP_basic_verify() failed");
  451.         goto error;
  452.     }

  453.     id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
  454.     if (id == NULL) {
  455.         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
  456.                       "OCSP_cert_to_id() failed");
  457.         goto error;
  458.     }

  459.     if (OCSP_resp_find_status(basic, id, &n, NULL, NULL,
  460.                               &thisupdate, &nextupdate)
  461.         != 1)
  462.     {
  463.         ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
  464.                       "certificate status not found in the OCSP response");
  465.         goto error;
  466.     }

  467.     if (n != V_OCSP_CERTSTATUS_GOOD) {
  468.         ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
  469.                       "certificate status \"%s\" in the OCSP response",
  470.                       OCSP_cert_status_str(n));
  471.         goto error;
  472.     }

  473.     if (OCSP_check_validity(thisupdate, nextupdate, 300, -1) != 1) {
  474.         ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
  475.                       "OCSP_check_validity() failed");
  476.         goto error;
  477.     }

  478.     OCSP_CERTID_free(id);
  479.     OCSP_BASICRESP_free(basic);
  480.     OCSP_RESPONSE_free(ocsp);

  481.     /* copy the response to memory not in ctx->pool */

  482.     response.len = len;
  483.     response.data = ngx_alloc(response.len, ctx->log);

  484.     if (response.data == NULL) {
  485.         goto done;
  486.     }

  487.     ngx_memcpy(response.data, ctx->response->pos, response.len);

  488.     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
  489.                    "ssl ocsp response, %s, %uz",
  490.                    OCSP_cert_status_str(n), response.len);

  491.     if (staple->staple.data) {
  492.         ngx_free(staple->staple.data);
  493.     }

  494.     staple->staple = response;

  495. done:

  496.     staple->loading = 0;
  497.     staple->valid = ngx_time() + 3600; /* ssl_stapling_valid */

  498.     ngx_ssl_ocsp_done(ctx);
  499.     return;

  500. error:

  501.     staple->loading = 0;
  502.     staple->valid = ngx_time() + 300; /* ssl_stapling_err_valid */

  503.     if (id) {
  504.         OCSP_CERTID_free(id);
  505.     }

  506.     if (basic) {
  507.         OCSP_BASICRESP_free(basic);
  508.     }

  509.     if (ocsp) {
  510.         OCSP_RESPONSE_free(ocsp);
  511.     }

  512.     ngx_ssl_ocsp_done(ctx);
  513. }


  514. static void
  515. ngx_ssl_stapling_cleanup(void *data)
  516. {
  517.     ngx_ssl_stapling_t  *staple = data;

  518.     if (staple->issuer) {
  519.         X509_free(staple->issuer);
  520.     }

  521.     if (staple->staple.data) {
  522.         ngx_free(staple->staple.data);
  523.     }
  524. }


  525. static ngx_ssl_ocsp_ctx_t *
  526. ngx_ssl_ocsp_start(void)
  527. {
  528.     ngx_log_t           *log;
  529.     ngx_pool_t          *pool;
  530.     ngx_ssl_ocsp_ctx_t  *ctx;

  531.     pool = ngx_create_pool(2048, ngx_cycle->log);
  532.     if (pool == NULL) {
  533.         return NULL;
  534.     }

  535.     ctx = ngx_pcalloc(pool, sizeof(ngx_ssl_ocsp_ctx_t));
  536.     if (ctx == NULL) {
  537.         ngx_destroy_pool(pool);
  538.         return NULL;
  539.     }

  540.     log = ngx_palloc(pool, sizeof(ngx_log_t));
  541.     if (log == NULL) {
  542.         ngx_destroy_pool(pool);
  543.         return NULL;
  544.     }

  545.     ctx->pool = pool;

  546.     *log = *ctx->pool->log;

  547.     ctx->pool->log = log;
  548.     ctx->log = log;

  549.     log->handler = ngx_ssl_ocsp_log_error;
  550.     log->data = ctx;
  551.     log->action = "requesting certificate status";

  552.     return ctx;
  553. }


  554. static void
  555. ngx_ssl_ocsp_done(ngx_ssl_ocsp_ctx_t *ctx)
  556. {
  557.     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
  558.                    "ssl ocsp done");

  559.     if (ctx->peer.connection) {
  560.         ngx_close_connection(ctx->peer.connection);
  561.     }

  562.     ngx_destroy_pool(ctx->pool);
  563. }


  564. static void
  565. ngx_ssl_ocsp_error(ngx_ssl_ocsp_ctx_t *ctx)
  566. {
  567.     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
  568.                    "ssl ocsp error");

  569.     ctx->code = 0;
  570.     ctx->handler(ctx);
  571. }


  572. static void
  573. ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx)
  574. {
  575.     ngx_resolver_ctx_t  *resolve, temp;

  576.     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
  577.                    "ssl ocsp request");

  578.     if (ngx_ssl_ocsp_create_request(ctx) != NGX_OK) {
  579.         ngx_ssl_ocsp_error(ctx);
  580.         return;
  581.     }

  582.     if (ctx->resolver) {
  583.         /* resolve OCSP responder hostname */

  584.         temp.name = ctx->host;

  585.         resolve = ngx_resolve_start(ctx->resolver, &temp);
  586.         if (resolve == NULL) {
  587.             ngx_ssl_ocsp_error(ctx);
  588.             return;
  589.         }

  590.         if (resolve == NGX_NO_RESOLVER) {
  591.             ngx_log_error(NGX_LOG_WARN, ctx->log, 0,
  592.                           "no resolver defined to resolve %V", &ctx->host);
  593.             goto connect;
  594.         }

  595.         resolve->name = ctx->host;
  596.         resolve->handler = ngx_ssl_ocsp_resolve_handler;
  597.         resolve->data = ctx;
  598.         resolve->timeout = ctx->resolver_timeout;

  599.         if (ngx_resolve_name(resolve) != NGX_OK) {
  600.             ngx_ssl_ocsp_error(ctx);
  601.             return;
  602.         }

  603.         return;
  604.     }

  605. connect:

  606.     ngx_ssl_ocsp_connect(ctx);
  607. }


  608. static void
  609. ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve)
  610. {
  611.     ngx_ssl_ocsp_ctx_t *ctx = resolve->data;

  612.     u_char           *p;
  613.     size_t            len;
  614.     in_port_t         port;
  615.     socklen_t         socklen;
  616.     ngx_uint_t        i;
  617.     struct sockaddr  *sockaddr;

  618.     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
  619.                    "ssl ocsp resolve handler");

  620.     if (resolve->state) {
  621.         ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
  622.                       "%V could not be resolved (%i: %s)",
  623.                       &resolve->name, resolve->state,
  624.                       ngx_resolver_strerror(resolve->state));
  625.         goto failed;
  626.     }

  627. #if (NGX_DEBUG)
  628.     {
  629.     u_char     text[NGX_SOCKADDR_STRLEN];
  630.     ngx_str_t  addr;

  631.     addr.data = text;

  632.     for (i = 0; i < resolve->naddrs; i++) {
  633.         addr.len = ngx_sock_ntop(resolve->addrs[i].sockaddr,
  634.                                  resolve->addrs[i].socklen,
  635.                                  text, NGX_SOCKADDR_STRLEN, 0);

  636.         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
  637.                        "name was resolved to %V", &addr);

  638.     }
  639.     }
  640. #endif

  641.     ctx->naddrs = resolve->naddrs;
  642.     ctx->addrs = ngx_pcalloc(ctx->pool, ctx->naddrs * sizeof(ngx_addr_t));

  643.     if (ctx->addrs == NULL) {
  644.         goto failed;
  645.     }

  646.     port = htons(ctx->port);

  647.     for (i = 0; i < resolve->naddrs; i++) {

  648.         socklen = resolve->addrs[i].socklen;

  649.         sockaddr = ngx_palloc(ctx->pool, socklen);
  650.         if (sockaddr == NULL) {
  651.             goto failed;
  652.         }

  653.         ngx_memcpy(sockaddr, resolve->addrs[i].sockaddr, socklen);

  654.         switch (sockaddr->sa_family) {
  655. #if (NGX_HAVE_INET6)
  656.         case AF_INET6:
  657.             ((struct sockaddr_in6 *) sockaddr)->sin6_port = port;
  658.             break;
  659. #endif
  660.         default: /* AF_INET */
  661.             ((struct sockaddr_in *) sockaddr)->sin_port = port;
  662.         }

  663.         ctx->addrs[i].sockaddr = sockaddr;
  664.         ctx->addrs[i].socklen = socklen;

  665.         p = ngx_pnalloc(ctx->pool, NGX_SOCKADDR_STRLEN);
  666.         if (p == NULL) {
  667.             goto failed;
  668.         }

  669.         len = ngx_sock_ntop(sockaddr, socklen, p, NGX_SOCKADDR_STRLEN, 1);

  670.         ctx->addrs[i].name.len = len;
  671.         ctx->addrs[i].name.data = p;
  672.     }

  673.     ngx_resolve_name_done(resolve);

  674.     ngx_ssl_ocsp_connect(ctx);
  675.     return;

  676. failed:

  677.     ngx_resolve_name_done(resolve);
  678.     ngx_ssl_ocsp_error(ctx);
  679. }


  680. static void
  681. ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx)
  682. {
  683.     ngx_int_t    rc;

  684.     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
  685.                    "ssl ocsp connect");

  686.     /* TODO: use all ip addresses */

  687.     ctx->peer.sockaddr = ctx->addrs[0].sockaddr;
  688.     ctx->peer.socklen = ctx->addrs[0].socklen;
  689.     ctx->peer.name = &ctx->addrs[0].name;
  690.     ctx->peer.get = ngx_event_get_peer;
  691.     ctx->peer.log = ctx->log;
  692.     ctx->peer.log_error = NGX_ERROR_ERR;

  693.     rc = ngx_event_connect_peer(&ctx->peer);

  694.     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
  695.                    "ssl ocsp connect peer done");

  696.     if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
  697.         ngx_ssl_ocsp_error(ctx);
  698.         return;
  699.     }

  700.     ctx->peer.connection->data = ctx;
  701.     ctx->peer.connection->pool = ctx->pool;

  702.     ctx->peer.connection->read->handler = ngx_ssl_ocsp_read_handler;
  703.     ctx->peer.connection->write->handler = ngx_ssl_ocsp_write_handler;

  704.     ctx->process = ngx_ssl_ocsp_process_status_line;

  705.     ngx_add_timer(ctx->peer.connection->read, ctx->timeout);
  706.     ngx_add_timer(ctx->peer.connection->write, ctx->timeout);

  707.     if (rc == NGX_OK) {
  708.         ngx_ssl_ocsp_write_handler(ctx->peer.connection->write);
  709.         return;
  710.     }
  711. }


  712. static void
  713. ngx_ssl_ocsp_write_handler(ngx_event_t *wev)
  714. {
  715.     ssize_t              n, size;
  716.     ngx_connection_t    *c;
  717.     ngx_ssl_ocsp_ctx_t  *ctx;

  718.     c = wev->data;
  719.     ctx = c->data;

  720.     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, wev->log, 0,
  721.                    "ssl ocsp write handler");

  722.     if (wev->timedout) {
  723.         ngx_log_error(NGX_LOG_ERR, wev->log, NGX_ETIMEDOUT,
  724.                       "OCSP responder timed out");
  725.         ngx_ssl_ocsp_error(ctx);
  726.         return;
  727.     }

  728.     size = ctx->request->last - ctx->request->pos;

  729.     n = ngx_send(c, ctx->request->pos, size);

  730.     if (n == NGX_ERROR) {
  731.         ngx_ssl_ocsp_error(ctx);
  732.         return;
  733.     }

  734.     if (n > 0) {
  735.         ctx->request->pos += n;

  736.         if (n == size) {
  737.             wev->handler = ngx_ssl_ocsp_dummy_handler;

  738.             if (wev->timer_set) {
  739.                 ngx_del_timer(wev);
  740.             }

  741.             if (ngx_handle_write_event(wev, 0) != NGX_OK) {
  742.                 ngx_ssl_ocsp_error(ctx);
  743.             }

  744.             return;
  745.         }
  746.     }

  747.     if (!wev->timer_set) {
  748.         ngx_add_timer(wev, ctx->timeout);
  749.     }
  750. }


  751. static void
  752. ngx_ssl_ocsp_read_handler(ngx_event_t *rev)
  753. {
  754.     ssize_t            n, size;
  755.     ngx_int_t          rc;
  756.     ngx_ssl_ocsp_ctx_t    *ctx;
  757.     ngx_connection_t  *c;

  758.     c = rev->data;
  759.     ctx = c->data;

  760.     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, rev->log, 0,
  761.                    "ssl ocsp read handler");

  762.     if (rev->timedout) {
  763.         ngx_log_error(NGX_LOG_ERR, rev->log, NGX_ETIMEDOUT,
  764.                       "OCSP responder timed out");
  765.         ngx_ssl_ocsp_error(ctx);
  766.         return;
  767.     }

  768.     if (ctx->response == NULL) {
  769.         ctx->response = ngx_create_temp_buf(ctx->pool, 16384);
  770.         if (ctx->response == NULL) {
  771.             ngx_ssl_ocsp_error(ctx);
  772.             return;
  773.         }
  774.     }

  775.     for ( ;; ) {

  776.         size = ctx->response->end - ctx->response->last;

  777.         n = ngx_recv(c, ctx->response->last, size);

  778.         if (n > 0) {
  779.             ctx->response->last += n;

  780.             rc = ctx->process(ctx);

  781.             if (rc == NGX_ERROR) {
  782.                 ngx_ssl_ocsp_error(ctx);
  783.                 return;
  784.             }

  785.             continue;
  786.         }

  787.         if (n == NGX_AGAIN) {

  788.             if (ngx_handle_read_event(rev, 0) != NGX_OK) {
  789.                 ngx_ssl_ocsp_error(ctx);
  790.             }

  791.             return;
  792.         }

  793.         break;
  794.     }

  795.     ctx->done = 1;

  796.     rc = ctx->process(ctx);

  797.     if (rc == NGX_DONE) {
  798.         /* ctx->handler() was called */
  799.         return;
  800.     }

  801.     ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
  802.                   "OCSP responder prematurely closed connection");

  803.     ngx_ssl_ocsp_error(ctx);
  804. }


  805. static void
  806. ngx_ssl_ocsp_dummy_handler(ngx_event_t *ev)
  807. {
  808.     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0,
  809.                    "ssl ocsp dummy handler");
  810. }


  811. static ngx_int_t
  812. ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx)
  813. {
  814.     int            len;
  815.     u_char        *p;
  816.     uintptr_t      escape;
  817.     ngx_str_t      binary, base64;
  818.     ngx_buf_t     *b;
  819.     OCSP_CERTID   *id;
  820.     OCSP_REQUEST  *ocsp;

  821.     ocsp = OCSP_REQUEST_new();
  822.     if (ocsp == NULL) {
  823.         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
  824.                       "OCSP_REQUEST_new() failed");
  825.         return NGX_ERROR;
  826.     }

  827.     id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
  828.     if (id == NULL) {
  829.         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
  830.                       "OCSP_cert_to_id() failed");
  831.         goto failed;
  832.     }

  833.     if (OCSP_request_add0_id(ocsp, id) == NULL) {
  834.         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
  835.                       "OCSP_request_add0_id() failed");
  836.         goto failed;
  837.     }

  838.     len = i2d_OCSP_REQUEST(ocsp, NULL);
  839.     if (len <= 0) {
  840.         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
  841.                       "i2d_OCSP_REQUEST() failed");
  842.         goto failed;
  843.     }

  844.     binary.len = len;
  845.     binary.data = ngx_palloc(ctx->pool, len);
  846.     if (binary.data == NULL) {
  847.         goto failed;
  848.     }

  849.     p = binary.data;
  850.     len = i2d_OCSP_REQUEST(ocsp, &p);
  851.     if (len <= 0) {
  852.         ngx_ssl_error(NGX_LOG_EMERG, ctx->log, 0,
  853.                       "i2d_OCSP_REQUEST() failed");
  854.         goto failed;
  855.     }

  856.     base64.len = ngx_base64_encoded_length(binary.len);
  857.     base64.data = ngx_palloc(ctx->pool, base64.len);
  858.     if (base64.data == NULL) {
  859.         goto failed;
  860.     }

  861.     ngx_encode_base64(&base64, &binary);

  862.     escape = ngx_escape_uri(NULL, base64.data, base64.len,
  863.                             NGX_ESCAPE_URI_COMPONENT);

  864.     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
  865.                    "ssl ocsp request length %z, escape %d",
  866.                    base64.len, escape);

  867.     len = sizeof("GET ") - 1 + ctx->uri.len + sizeof("/") - 1
  868.           + base64.len + 2 * escape + sizeof(" HTTP/1.0" CRLF) - 1
  869.           + sizeof("Host: ") - 1 + ctx->host.len + sizeof(CRLF) - 1
  870.           + sizeof(CRLF) - 1;

  871.     b = ngx_create_temp_buf(ctx->pool, len);
  872.     if (b == NULL) {
  873.         goto failed;
  874.     }

  875.     p = b->last;

  876.     p = ngx_cpymem(p, "GET ", sizeof("GET ") - 1);
  877.     p = ngx_cpymem(p, ctx->uri.data, ctx->uri.len);

  878.     if (ctx->uri.data[ctx->uri.len - 1] != '/') {
  879.         *p++ = '/';
  880.     }

  881.     if (escape == 0) {
  882.         p = ngx_cpymem(p, base64.data, base64.len);

  883.     } else {
  884.         p = (u_char *) ngx_escape_uri(p, base64.data, base64.len,
  885.                                       NGX_ESCAPE_URI_COMPONENT);
  886.     }

  887.     p = ngx_cpymem(p, " HTTP/1.0" CRLF, sizeof(" HTTP/1.0" CRLF) - 1);
  888.     p = ngx_cpymem(p, "Host: ", sizeof("Host: ") - 1);
  889.     p = ngx_cpymem(p, ctx->host.data, ctx->host.len);
  890.     *p++ = CR; *p++ = LF;

  891.     /* add "\r\n" at the header end */
  892.     *p++ = CR; *p++ = LF;

  893.     b->last = p;
  894.     ctx->request = b;

  895.     OCSP_REQUEST_free(ocsp);

  896.     return NGX_OK;

  897. failed:

  898.     OCSP_REQUEST_free(ocsp);

  899.     return NGX_ERROR;
  900. }


  901. static ngx_int_t
  902. ngx_ssl_ocsp_process_status_line(ngx_ssl_ocsp_ctx_t *ctx)
  903. {
  904.     ngx_int_t  rc;

  905.     rc = ngx_ssl_ocsp_parse_status_line(ctx);

  906.     if (rc == NGX_OK) {
  907. #if 0
  908.         ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
  909.                        "ssl ocsp status line \"%*s\"",
  910.                        ctx->response->pos - ctx->response->start,
  911.                        ctx->response->start);
  912. #endif

  913.         ctx->process = ngx_ssl_ocsp_process_headers;
  914.         return ctx->process(ctx);
  915.     }

  916.     if (rc == NGX_AGAIN) {
  917.         return NGX_AGAIN;
  918.     }

  919.     /* rc == NGX_ERROR */

  920.     ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
  921.                   "OCSP responder sent invalid response");

  922.     return NGX_ERROR;
  923. }


  924. static ngx_int_t
  925. ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t *ctx)
  926. {
  927.     u_char      ch;
  928.     u_char     *p;
  929.     ngx_buf_t  *b;
  930.     enum {
  931.         sw_start = 0,
  932.         sw_H,
  933.         sw_HT,
  934.         sw_HTT,
  935.         sw_HTTP,
  936.         sw_first_major_digit,
  937.         sw_major_digit,
  938.         sw_first_minor_digit,
  939.         sw_minor_digit,
  940.         sw_status,
  941.         sw_space_after_status,
  942.         sw_status_text,
  943.         sw_almost_done
  944.     } state;

  945.     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
  946.                    "ssl ocsp process status line");

  947.     state = ctx->state;
  948.     b = ctx->response;

  949.     for (p = b->pos; p < b->last; p++) {
  950.         ch = *p;

  951.         switch (state) {

  952.         /* "HTTP/" */
  953.         case sw_start:
  954.             switch (ch) {
  955.             case 'H':
  956.                 state = sw_H;
  957.                 break;
  958.             default:
  959.                 return NGX_ERROR;
  960.             }
  961.             break;

  962.         case sw_H:
  963.             switch (ch) {
  964.             case 'T':
  965.                 state = sw_HT;
  966.                 break;
  967.             default:
  968.                 return NGX_ERROR;
  969.             }
  970.             break;

  971.         case sw_HT:
  972.             switch (ch) {
  973.             case 'T':
  974.                 state = sw_HTT;
  975.                 break;
  976.             default:
  977.                 return NGX_ERROR;
  978.             }
  979.             break;

  980.         case sw_HTT:
  981.             switch (ch) {
  982.             case 'P':
  983.                 state = sw_HTTP;
  984.                 break;
  985.             default:
  986.                 return NGX_ERROR;
  987.             }
  988.             break;

  989.         case sw_HTTP:
  990.             switch (ch) {
  991.             case '/':
  992.                 state = sw_first_major_digit;
  993.                 break;
  994.             default:
  995.                 return NGX_ERROR;
  996.             }
  997.             break;

  998.         /* the first digit of major HTTP version */
  999.         case sw_first_major_digit:
  1000.             if (ch < '1' || ch > '9') {
  1001.                 return NGX_ERROR;
  1002.             }

  1003.             state = sw_major_digit;
  1004.             break;

  1005.         /* the major HTTP version or dot */
  1006.         case sw_major_digit:
  1007.             if (ch == '.') {
  1008.                 state = sw_first_minor_digit;
  1009.                 break;
  1010.             }

  1011.             if (ch < '0' || ch > '9') {
  1012.                 return NGX_ERROR;
  1013.             }

  1014.             break;

  1015.         /* the first digit of minor HTTP version */
  1016.         case sw_first_minor_digit:
  1017.             if (ch < '0' || ch > '9') {
  1018.                 return NGX_ERROR;
  1019.             }

  1020.             state = sw_minor_digit;
  1021.             break;

  1022.         /* the minor HTTP version or the end of the request line */
  1023.         case sw_minor_digit:
  1024.             if (ch == ' ') {
  1025.                 state = sw_status;
  1026.                 break;
  1027.             }

  1028.             if (ch < '0' || ch > '9') {
  1029.                 return NGX_ERROR;
  1030.             }

  1031.             break;

  1032.         /* HTTP status code */
  1033.         case sw_status:
  1034.             if (ch == ' ') {
  1035.                 break;
  1036.             }

  1037.             if (ch < '0' || ch > '9') {
  1038.                 return NGX_ERROR;
  1039.             }

  1040.             ctx->code = ctx->code * 10 + ch - '0';

  1041.             if (++ctx->count == 3) {
  1042.                 state = sw_space_after_status;
  1043.             }

  1044.             break;

  1045.         /* space or end of line */
  1046.         case sw_space_after_status:
  1047.             switch (ch) {
  1048.             case ' ':
  1049.                 state = sw_status_text;
  1050.                 break;
  1051.             case '.':                    /* IIS may send 403.1, 403.2, etc */
  1052.                 state = sw_status_text;
  1053.                 break;
  1054.             case CR:
  1055.                 state = sw_almost_done;
  1056.                 break;
  1057.             case LF:
  1058.                 goto done;
  1059.             default:
  1060.                 return NGX_ERROR;
  1061.             }
  1062.             break;

  1063.         /* any text until end of line */
  1064.         case sw_status_text:
  1065.             switch (ch) {
  1066.             case CR:
  1067.                 state = sw_almost_done;
  1068.                 break;
  1069.             case LF:
  1070.                 goto done;
  1071.             }
  1072.             break;

  1073.         /* end of status line */
  1074.         case sw_almost_done:
  1075.             switch (ch) {
  1076.             case LF:
  1077.                 goto done;
  1078.             default:
  1079.                 return NGX_ERROR;
  1080.             }
  1081.         }
  1082.     }

  1083.     b->pos = p;
  1084.     ctx->state = state;

  1085.     return NGX_AGAIN;

  1086. done:

  1087.     b->pos = p + 1;
  1088.     ctx->state = sw_start;

  1089.     return NGX_OK;
  1090. }


  1091. static ngx_int_t
  1092. ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx)
  1093. {
  1094.     size_t     len;
  1095.     ngx_int_t  rc;

  1096.     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
  1097.                    "ssl ocsp process headers");

  1098.     for ( ;; ) {
  1099.         rc = ngx_ssl_ocsp_parse_header_line(ctx);

  1100.         if (rc == NGX_OK) {

  1101.             ngx_log_debug4(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
  1102.                            "ssl ocsp header \"%*s: %*s\"",
  1103.                            ctx->header_name_end - ctx->header_name_start,
  1104.                            ctx->header_name_start,
  1105.                            ctx->header_end - ctx->header_start,
  1106.                            ctx->header_start);

  1107.             len = ctx->header_name_end - ctx->header_name_start;

  1108.             if (len == sizeof("Content-Type") - 1
  1109.                 && ngx_strncasecmp(ctx->header_name_start,
  1110.                                    (u_char *) "Content-Type",
  1111.                                    sizeof("Content-Type") - 1)
  1112.                    == 0)
  1113.             {
  1114.                 len = ctx->header_end - ctx->header_start;

  1115.                 if (len != sizeof("application/ocsp-response") - 1
  1116.                     || ngx_strncasecmp(ctx->header_start,
  1117.                                        (u_char *) "application/ocsp-response",
  1118.                                        sizeof("application/ocsp-response") - 1)
  1119.                        != 0)
  1120.                 {
  1121.                     ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
  1122.                                   "OCSP responder sent invalid "
  1123.                                   "\"Content-Type\" header: \"%*s\"",
  1124.                                   ctx->header_end - ctx->header_start,
  1125.                                   ctx->header_start);
  1126.                     return NGX_ERROR;
  1127.                 }

  1128.                 continue;
  1129.             }

  1130.             /* TODO: honor Content-Length */

  1131.             continue;
  1132.         }

  1133.         if (rc == NGX_DONE) {
  1134.             break;
  1135.         }

  1136.         if (rc == NGX_AGAIN) {
  1137.             return NGX_AGAIN;
  1138.         }

  1139.         /* rc == NGX_ERROR */

  1140.         ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
  1141.                       "OCSP responder sent invalid response");

  1142.         return NGX_ERROR;
  1143.     }

  1144.     ctx->process = ngx_ssl_ocsp_process_body;
  1145.     return ctx->process(ctx);
  1146. }

  1147. static ngx_int_t
  1148. ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx)
  1149. {
  1150.     u_char      c, ch, *p;
  1151.     enum {
  1152.         sw_start = 0,
  1153.         sw_name,
  1154.         sw_space_before_value,
  1155.         sw_value,
  1156.         sw_space_after_value,
  1157.         sw_almost_done,
  1158.         sw_header_almost_done
  1159.     } state;

  1160.     state = ctx->state;

  1161.     for (p = ctx->response->pos; p < ctx->response->last; p++) {
  1162.         ch = *p;

  1163. #if 0
  1164.         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
  1165.                        "s:%d in:'%02Xd:%c'", state, ch, ch);
  1166. #endif

  1167.         switch (state) {

  1168.         /* first char */
  1169.         case sw_start:

  1170.             switch (ch) {
  1171.             case CR:
  1172.                 ctx->header_end = p;
  1173.                 state = sw_header_almost_done;
  1174.                 break;
  1175.             case LF:
  1176.                 ctx->header_end = p;
  1177.                 goto header_done;
  1178.             default:
  1179.                 state = sw_name;
  1180.                 ctx->header_name_start = p;

  1181.                 c = (u_char) (ch | 0x20);
  1182.                 if (c >= 'a' && c <= 'z') {
  1183.                     break;
  1184.                 }

  1185.                 if (ch >= '0' && ch <= '9') {
  1186.                     break;
  1187.                 }

  1188.                 return NGX_ERROR;
  1189.             }
  1190.             break;

  1191.         /* header name */
  1192.         case sw_name:
  1193.             c = (u_char) (ch | 0x20);
  1194.             if (c >= 'a' && c <= 'z') {
  1195.                 break;
  1196.             }

  1197.             if (ch == ':') {
  1198.                 ctx->header_name_end = p;
  1199.                 state = sw_space_before_value;
  1200.                 break;
  1201.             }

  1202.             if (ch == '-') {
  1203.                 break;
  1204.             }

  1205.             if (ch >= '0' && ch <= '9') {
  1206.                 break;
  1207.             }

  1208.             if (ch == CR) {
  1209.                 ctx->header_name_end = p;
  1210.                 ctx->header_start = p;
  1211.                 ctx->header_end = p;
  1212.                 state = sw_almost_done;
  1213.                 break;
  1214.             }

  1215.             if (ch == LF) {
  1216.                 ctx->header_name_end = p;
  1217.                 ctx->header_start = p;
  1218.                 ctx->header_end = p;
  1219.                 goto done;
  1220.             }

  1221.             return NGX_ERROR;

  1222.         /* space* before header value */
  1223.         case sw_space_before_value:
  1224.             switch (ch) {
  1225.             case ' ':
  1226.                 break;
  1227.             case CR:
  1228.                 ctx->header_start = p;
  1229.                 ctx->header_end = p;
  1230.                 state = sw_almost_done;
  1231.                 break;
  1232.             case LF:
  1233.                 ctx->header_start = p;
  1234.                 ctx->header_end = p;
  1235.                 goto done;
  1236.             default:
  1237.                 ctx->header_start = p;
  1238.                 state = sw_value;
  1239.                 break;
  1240.             }
  1241.             break;

  1242.         /* header value */
  1243.         case sw_value:
  1244.             switch (ch) {
  1245.             case ' ':
  1246.                 ctx->header_end = p;
  1247.                 state = sw_space_after_value;
  1248.                 break;
  1249.             case CR:
  1250.                 ctx->header_end = p;
  1251.                 state = sw_almost_done;
  1252.                 break;
  1253.             case LF:
  1254.                 ctx->header_end = p;
  1255.                 goto done;
  1256.             }
  1257.             break;

  1258.         /* space* before end of header line */
  1259.         case sw_space_after_value:
  1260.             switch (ch) {
  1261.             case ' ':
  1262.                 break;
  1263.             case CR:
  1264.                 state = sw_almost_done;
  1265.                 break;
  1266.             case LF:
  1267.                 goto done;
  1268.             default:
  1269.                 state = sw_value;
  1270.                 break;
  1271.             }
  1272.             break;

  1273.         /* end of header line */
  1274.         case sw_almost_done:
  1275.             switch (ch) {
  1276.             case LF:
  1277.                 goto done;
  1278.             default:
  1279.                 return NGX_ERROR;
  1280.             }

  1281.         /* end of header */
  1282.         case sw_header_almost_done:
  1283.             switch (ch) {
  1284.             case LF:
  1285.                 goto header_done;
  1286.             default:
  1287.                 return NGX_ERROR;
  1288.             }
  1289.         }
  1290.     }

  1291.     ctx->response->pos = p;
  1292.     ctx->state = state;

  1293.     return NGX_AGAIN;

  1294. done:

  1295.     ctx->response->pos = p + 1;
  1296.     ctx->state = sw_start;

  1297.     return NGX_OK;

  1298. header_done:

  1299.     ctx->response->pos = p + 1;
  1300.     ctx->state = sw_start;

  1301.     return NGX_DONE;
  1302. }


  1303. static ngx_int_t
  1304. ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx)
  1305. {
  1306.     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
  1307.                    "ssl ocsp process body");

  1308.     if (ctx->done) {
  1309.         ctx->handler(ctx);
  1310.         return NGX_DONE;
  1311.     }

  1312.     return NGX_AGAIN;
  1313. }


  1314. static u_char *
  1315. ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len)
  1316. {
  1317.     u_char              *p;
  1318.     ngx_ssl_ocsp_ctx_t  *ctx;

  1319.     p = buf;

  1320.     if (log->action) {
  1321.         p = ngx_snprintf(buf, len, " while %s", log->action);
  1322.         len -= p - buf;
  1323.     }

  1324.     ctx = log->data;

  1325.     if (ctx) {
  1326.         p = ngx_snprintf(p, len, ", responder: %V", &ctx->host);
  1327.     }

  1328.     return p;
  1329. }


  1330. #else


  1331. ngx_int_t
  1332. ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file,
  1333.     ngx_str_t *responder, ngx_uint_t verify)
  1334. {
  1335.     ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
  1336.                   "\"ssl_stapling\" ignored, not supported");

  1337.     return NGX_OK;
  1338. }

  1339. ngx_int_t
  1340. ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
  1341.     ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)
  1342. {
  1343.     return NGX_OK;
  1344. }


  1345. #endif