Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.13.12 ]​[ nginx-1.12.2 ]​

0001 
0002 /*
0003  * Copyright (C) Maxim Dounin
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_event.h>
0011 #include <ngx_event_connect.h>
0012 
0013 
0014 #if (!defined OPENSSL_NO_OCSP && defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB)
0015 
0016 
0017 typedef struct {
0018     ngx_str_t                    staple;
0019     ngx_msec_t                   timeout;
0020 
0021     ngx_resolver_t              *resolver;
0022     ngx_msec_t                   resolver_timeout;
0023 
0024     ngx_addr_t                  *addrs;
0025     ngx_str_t                    host;
0026     ngx_str_t                    uri;
0027     in_port_t                    port;
0028 
0029     SSL_CTX                     *ssl_ctx;
0030 
0031     X509                        *cert;
0032     X509                        *issuer;
0033 
0034     u_char                      *name;
0035 
0036     time_t                       valid;
0037     time_t                       refresh;
0038 
0039     unsigned                     verify:1;
0040     unsigned                     loading:1;
0041 } ngx_ssl_stapling_t;
0042 
0043 
0044 typedef struct ngx_ssl_ocsp_ctx_s  ngx_ssl_ocsp_ctx_t;
0045 
0046 struct ngx_ssl_ocsp_ctx_s {
0047     X509                        *cert;
0048     X509                        *issuer;
0049 
0050     u_char                      *name;
0051 
0052     ngx_uint_t                   naddrs;
0053 
0054     ngx_addr_t                  *addrs;
0055     ngx_str_t                    host;
0056     ngx_str_t                    uri;
0057     in_port_t                    port;
0058 
0059     ngx_resolver_t              *resolver;
0060     ngx_msec_t                   resolver_timeout;
0061 
0062     ngx_msec_t                   timeout;
0063 
0064     void                       (*handler)(ngx_ssl_ocsp_ctx_t *ctx);
0065     void                        *data;
0066 
0067     ngx_buf_t                   *request;
0068     ngx_buf_t                   *response;
0069     ngx_peer_connection_t        peer;
0070 
0071     ngx_int_t                  (*process)(ngx_ssl_ocsp_ctx_t *ctx);
0072 
0073     ngx_uint_t                   state;
0074 
0075     ngx_uint_t                   code;
0076     ngx_uint_t                   count;
0077 
0078     ngx_uint_t                   done;
0079 
0080     u_char                      *header_name_start;
0081     u_char                      *header_name_end;
0082     u_char                      *header_start;
0083     u_char                      *header_end;
0084 
0085     ngx_pool_t                  *pool;
0086     ngx_log_t                   *log;
0087 };
0088 
0089 
0090 static ngx_int_t ngx_ssl_stapling_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl,
0091     X509 *cert, ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify);
0092 static ngx_int_t ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl,
0093     ngx_ssl_stapling_t *staple, ngx_str_t *file);
0094 static ngx_int_t ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl,
0095     ngx_ssl_stapling_t *staple);
0096 static ngx_int_t ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl,
0097     ngx_ssl_stapling_t *staple, ngx_str_t *responder);
0098 
0099 static int ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn,
0100     void *data);
0101 static void ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple);
0102 static void ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx);
0103 
0104 static time_t ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time);
0105 
0106 static void ngx_ssl_stapling_cleanup(void *data);
0107 
0108 static ngx_ssl_ocsp_ctx_t *ngx_ssl_ocsp_start(void);
0109 static void ngx_ssl_ocsp_done(ngx_ssl_ocsp_ctx_t *ctx);
0110 static void ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx);
0111 static void ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve);
0112 static void ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx);
0113 static void ngx_ssl_ocsp_write_handler(ngx_event_t *wev);
0114 static void ngx_ssl_ocsp_read_handler(ngx_event_t *rev);
0115 static void ngx_ssl_ocsp_dummy_handler(ngx_event_t *ev);
0116 
0117 static ngx_int_t ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx);
0118 static ngx_int_t ngx_ssl_ocsp_process_status_line(ngx_ssl_ocsp_ctx_t *ctx);
0119 static ngx_int_t ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t *ctx);
0120 static ngx_int_t ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx);
0121 static ngx_int_t ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx);
0122 static ngx_int_t ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx);
0123 
0124 static u_char *ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len);
0125 
0126 
0127 ngx_int_t
0128 ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file,
0129     ngx_str_t *responder, ngx_uint_t verify)
0130 {
0131     X509  *cert;
0132 
0133     for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
0134          cert;
0135          cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index))
0136     {
0137         if (ngx_ssl_stapling_certificate(cf, ssl, cert, file, responder, verify)
0138             != NGX_OK)
0139         {
0140             return NGX_ERROR;
0141         }
0142     }
0143 
0144     SSL_CTX_set_tlsext_status_cb(ssl->ctx, ngx_ssl_certificate_status_callback);
0145 
0146     return NGX_OK;
0147 }
0148 
0149 
0150 static ngx_int_t
0151 ngx_ssl_stapling_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, X509 *cert,
0152     ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify)
0153 {
0154     ngx_int_t            rc;
0155     ngx_pool_cleanup_t  *cln;
0156     ngx_ssl_stapling_t  *staple;
0157 
0158     staple = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_stapling_t));
0159     if (staple == NULL) {
0160         return NGX_ERROR;
0161     }
0162 
0163     cln = ngx_pool_cleanup_add(cf->pool, 0);
0164     if (cln == NULL) {
0165         return NGX_ERROR;
0166     }
0167 
0168     cln->handler = ngx_ssl_stapling_cleanup;
0169     cln->data = staple;
0170 
0171     if (X509_set_ex_data(cert, ngx_ssl_stapling_index, staple) == 0) {
0172         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed");
0173         return NGX_ERROR;
0174     }
0175 
0176     staple->ssl_ctx = ssl->ctx;
0177     staple->timeout = 60000;
0178     staple->verify = verify;
0179     staple->cert = cert;
0180     staple->name = X509_get_ex_data(staple->cert,
0181                                     ngx_ssl_certificate_name_index);
0182 
0183     if (file->len) {
0184         /* use OCSP response from the file */
0185 
0186         if (ngx_ssl_stapling_file(cf, ssl, staple, file) != NGX_OK) {
0187             return NGX_ERROR;
0188         }
0189 
0190         return NGX_OK;
0191     }
0192 
0193     rc = ngx_ssl_stapling_issuer(cf, ssl, staple);
0194 
0195     if (rc == NGX_DECLINED) {
0196         return NGX_OK;
0197     }
0198 
0199     if (rc != NGX_OK) {
0200         return NGX_ERROR;
0201     }
0202 
0203     rc = ngx_ssl_stapling_responder(cf, ssl, staple, responder);
0204 
0205     if (rc == NGX_DECLINED) {
0206         return NGX_OK;
0207     }
0208 
0209     if (rc != NGX_OK) {
0210         return NGX_ERROR;
0211     }
0212 
0213     return NGX_OK;
0214 }
0215 
0216 
0217 static ngx_int_t
0218 ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl,
0219     ngx_ssl_stapling_t *staple, ngx_str_t *file)
0220 {
0221     BIO            *bio;
0222     int             len;
0223     u_char         *p, *buf;
0224     OCSP_RESPONSE  *response;
0225 
0226     if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) {
0227         return NGX_ERROR;
0228     }
0229 
0230     bio = BIO_new_file((char *) file->data, "r");
0231     if (bio == NULL) {
0232         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0233                       "BIO_new_file(\"%s\") failed", file->data);
0234         return NGX_ERROR;
0235     }
0236 
0237     response = d2i_OCSP_RESPONSE_bio(bio, NULL);
0238     if (response == NULL) {
0239         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0240                       "d2i_OCSP_RESPONSE_bio(\"%s\") failed", file->data);
0241         BIO_free(bio);
0242         return NGX_ERROR;
0243     }
0244 
0245     len = i2d_OCSP_RESPONSE(response, NULL);
0246     if (len <= 0) {
0247         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0248                       "i2d_OCSP_RESPONSE(\"%s\") failed", file->data);
0249         goto failed;
0250     }
0251 
0252     buf = ngx_alloc(len, ssl->log);
0253     if (buf == NULL) {
0254         goto failed;
0255     }
0256 
0257     p = buf;
0258     len = i2d_OCSP_RESPONSE(response, &p);
0259     if (len <= 0) {
0260         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0261                       "i2d_OCSP_RESPONSE(\"%s\") failed", file->data);
0262         ngx_free(buf);
0263         goto failed;
0264     }
0265 
0266     OCSP_RESPONSE_free(response);
0267     BIO_free(bio);
0268 
0269     staple->staple.data = buf;
0270     staple->staple.len = len;
0271     staple->valid = NGX_MAX_TIME_T_VALUE;
0272 
0273     return NGX_OK;
0274 
0275 failed:
0276 
0277     OCSP_RESPONSE_free(response);
0278     BIO_free(bio);
0279 
0280     return NGX_ERROR;
0281 }
0282 
0283 
0284 static ngx_int_t
0285 ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl,
0286     ngx_ssl_stapling_t *staple)
0287 {
0288     int              i, n, rc;
0289     X509            *cert, *issuer;
0290     X509_STORE      *store;
0291     X509_STORE_CTX  *store_ctx;
0292     STACK_OF(X509)  *chain;
0293 
0294     cert = staple->cert;
0295 
0296 #ifdef SSL_CTRL_SELECT_CURRENT_CERT
0297     /* OpenSSL 1.0.2+ */
0298     SSL_CTX_select_current_cert(ssl->ctx, cert);
0299 #endif
0300 
0301 #ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
0302     /* OpenSSL 1.0.1+ */
0303     SSL_CTX_get_extra_chain_certs(ssl->ctx, &chain);
0304 #else
0305     chain = ssl->ctx->extra_certs;
0306 #endif
0307 
0308     n = sk_X509_num(chain);
0309 
0310     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
0311                    "SSL get issuer: %d extra certs", n);
0312 
0313     for (i = 0; i < n; i++) {
0314         issuer = sk_X509_value(chain, i);
0315         if (X509_check_issued(issuer, cert) == X509_V_OK) {
0316 #if OPENSSL_VERSION_NUMBER >= 0x10100001L
0317             X509_up_ref(issuer);
0318 #else
0319             CRYPTO_add(&issuer->references, 1, CRYPTO_LOCK_X509);
0320 #endif
0321 
0322             ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
0323                            "SSL get issuer: found %p in extra certs", issuer);
0324 
0325             staple->issuer = issuer;
0326 
0327             return NGX_OK;
0328         }
0329     }
0330 
0331     store = SSL_CTX_get_cert_store(ssl->ctx);
0332     if (store == NULL) {
0333         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0334                       "SSL_CTX_get_cert_store() failed");
0335         return NGX_ERROR;
0336     }
0337 
0338     store_ctx = X509_STORE_CTX_new();
0339     if (store_ctx == NULL) {
0340         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0341                       "X509_STORE_CTX_new() failed");
0342         return NGX_ERROR;
0343     }
0344 
0345     if (X509_STORE_CTX_init(store_ctx, store, NULL, NULL) == 0) {
0346         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0347                       "X509_STORE_CTX_init() failed");
0348         X509_STORE_CTX_free(store_ctx);
0349         return NGX_ERROR;
0350     }
0351 
0352     rc = X509_STORE_CTX_get1_issuer(&issuer, store_ctx, cert);
0353 
0354     if (rc == -1) {
0355         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0356                       "X509_STORE_CTX_get1_issuer() failed");
0357         X509_STORE_CTX_free(store_ctx);
0358         return NGX_ERROR;
0359     }
0360 
0361     if (rc == 0) {
0362         ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
0363                       "\"ssl_stapling\" ignored, "
0364                       "issuer certificate not found for certificate \"%s\"",
0365                       staple->name);
0366         X509_STORE_CTX_free(store_ctx);
0367         return NGX_DECLINED;
0368     }
0369 
0370     X509_STORE_CTX_free(store_ctx);
0371 
0372     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
0373                    "SSL get issuer: found %p in cert store", issuer);
0374 
0375     staple->issuer = issuer;
0376 
0377     return NGX_OK;
0378 }
0379 
0380 
0381 static ngx_int_t
0382 ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl,
0383     ngx_ssl_stapling_t *staple, ngx_str_t *responder)
0384 {
0385     char                      *s;
0386     ngx_str_t                  rsp;
0387     ngx_url_t                  u;
0388     STACK_OF(OPENSSL_STRING)  *aia;
0389 
0390     if (responder->len == 0) {
0391 
0392         /* extract OCSP responder URL from certificate */
0393 
0394         aia = X509_get1_ocsp(staple->cert);
0395         if (aia == NULL) {
0396             ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
0397                           "\"ssl_stapling\" ignored, "
0398                           "no OCSP responder URL in the certificate \"%s\"",
0399                           staple->name);
0400             return NGX_DECLINED;
0401         }
0402 
0403 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
0404         s = sk_OPENSSL_STRING_value(aia, 0);
0405 #else
0406         s = sk_value(aia, 0);
0407 #endif
0408         if (s == NULL) {
0409             ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
0410                           "\"ssl_stapling\" ignored, "
0411                           "no OCSP responder URL in the certificate \"%s\"",
0412                           staple->name);
0413             X509_email_free(aia);
0414             return NGX_DECLINED;
0415         }
0416 
0417         responder = &rsp;
0418 
0419         responder->len = ngx_strlen(s);
0420         responder->data = ngx_palloc(cf->pool, responder->len);
0421         if (responder->data == NULL) {
0422             X509_email_free(aia);
0423             return NGX_ERROR;
0424         }
0425 
0426         ngx_memcpy(responder->data, s, responder->len);
0427         X509_email_free(aia);
0428     }
0429 
0430     ngx_memzero(&u, sizeof(ngx_url_t));
0431 
0432     u.url = *responder;
0433     u.default_port = 80;
0434     u.uri_part = 1;
0435 
0436     if (u.url.len > 7
0437         && ngx_strncasecmp(u.url.data, (u_char *) "http://", 7) == 0)
0438     {
0439         u.url.len -= 7;
0440         u.url.data += 7;
0441 
0442     } else {
0443         ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
0444                       "\"ssl_stapling\" ignored, "
0445                       "invalid URL prefix in OCSP responder \"%V\" "
0446                       "in the certificate \"%s\"",
0447                       &u.url, staple->name);
0448         return NGX_DECLINED;
0449     }
0450 
0451     if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
0452         if (u.err) {
0453             ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
0454                           "\"ssl_stapling\" ignored, "
0455                           "%s in OCSP responder \"%V\" "
0456                           "in the certificate \"%s\"",
0457                           u.err, &u.url, staple->name);
0458             return NGX_DECLINED;
0459         }
0460 
0461         return NGX_ERROR;
0462     }
0463 
0464     staple->addrs = u.addrs;
0465     staple->host = u.host;
0466     staple->uri = u.uri;
0467     staple->port = u.port;
0468 
0469     if (staple->uri.len == 0) {
0470         ngx_str_set(&staple->uri, "/");
0471     }
0472 
0473     return NGX_OK;
0474 }
0475 
0476 
0477 ngx_int_t
0478 ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
0479     ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)
0480 {
0481     X509                *cert;
0482     ngx_ssl_stapling_t  *staple;
0483 
0484     for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
0485          cert;
0486          cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index))
0487     {
0488         staple = X509_get_ex_data(cert, ngx_ssl_stapling_index);
0489         staple->resolver = resolver;
0490         staple->resolver_timeout = resolver_timeout;
0491     }
0492 
0493     return NGX_OK;
0494 }
0495 
0496 
0497 static int
0498 ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn, void *data)
0499 {
0500     int                  rc;
0501     X509                *cert;
0502     u_char              *p;
0503     ngx_connection_t    *c;
0504     ngx_ssl_stapling_t  *staple;
0505 
0506     c = ngx_ssl_get_connection(ssl_conn);
0507 
0508     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
0509                    "SSL certificate status callback");
0510 
0511     rc = SSL_TLSEXT_ERR_NOACK;
0512 
0513     cert = SSL_get_certificate(ssl_conn);
0514     staple = X509_get_ex_data(cert, ngx_ssl_stapling_index);
0515 
0516     if (staple == NULL) {
0517         return rc;
0518     }
0519 
0520     if (staple->staple.len
0521         && staple->valid >= ngx_time())
0522     {
0523         /* we have to copy ocsp response as OpenSSL will free it by itself */
0524 
0525         p = OPENSSL_malloc(staple->staple.len);
0526         if (p == NULL) {
0527             ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "OPENSSL_malloc() failed");
0528             return SSL_TLSEXT_ERR_NOACK;
0529         }
0530 
0531         ngx_memcpy(p, staple->staple.data, staple->staple.len);
0532 
0533         SSL_set_tlsext_status_ocsp_resp(ssl_conn, p, staple->staple.len);
0534 
0535         rc = SSL_TLSEXT_ERR_OK;
0536     }
0537 
0538     ngx_ssl_stapling_update(staple);
0539 
0540     return rc;
0541 }
0542 
0543 
0544 static void
0545 ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple)
0546 {
0547     ngx_ssl_ocsp_ctx_t  *ctx;
0548 
0549     if (staple->host.len == 0
0550         || staple->loading || staple->refresh >= ngx_time())
0551     {
0552         return;
0553     }
0554 
0555     staple->loading = 1;
0556 
0557     ctx = ngx_ssl_ocsp_start();
0558     if (ctx == NULL) {
0559         return;
0560     }
0561 
0562     ctx->cert = staple->cert;
0563     ctx->issuer = staple->issuer;
0564     ctx->name = staple->name;
0565 
0566     ctx->addrs = staple->addrs;
0567     ctx->host = staple->host;
0568     ctx->uri = staple->uri;
0569     ctx->port = staple->port;
0570     ctx->timeout = staple->timeout;
0571 
0572     ctx->resolver = staple->resolver;
0573     ctx->resolver_timeout = staple->resolver_timeout;
0574 
0575     ctx->handler = ngx_ssl_stapling_ocsp_handler;
0576     ctx->data = staple;
0577 
0578     ngx_ssl_ocsp_request(ctx);
0579 
0580     return;
0581 }
0582 
0583 
0584 static void
0585 ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
0586 {
0587 #if OPENSSL_VERSION_NUMBER >= 0x0090707fL
0588     const
0589 #endif
0590     u_char                *p;
0591     int                    n;
0592     size_t                 len;
0593     time_t                 now, valid;
0594     ngx_str_t              response;
0595     X509_STORE            *store;
0596     STACK_OF(X509)        *chain;
0597     OCSP_CERTID           *id;
0598     OCSP_RESPONSE         *ocsp;
0599     OCSP_BASICRESP        *basic;
0600     ngx_ssl_stapling_t    *staple;
0601     ASN1_GENERALIZEDTIME  *thisupdate, *nextupdate;
0602 
0603     staple = ctx->data;
0604     now = ngx_time();
0605     ocsp = NULL;
0606     basic = NULL;
0607     id = NULL;
0608 
0609     if (ctx->code != 200) {
0610         goto error;
0611     }
0612 
0613     /* check the response */
0614 
0615     len = ctx->response->last - ctx->response->pos;
0616     p = ctx->response->pos;
0617 
0618     ocsp = d2i_OCSP_RESPONSE(NULL, &p, len);
0619     if (ocsp == NULL) {
0620         ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
0621                       "d2i_OCSP_RESPONSE() failed");
0622         goto error;
0623     }
0624 
0625     n = OCSP_response_status(ocsp);
0626 
0627     if (n != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
0628         ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
0629                       "OCSP response not successful (%d: %s)",
0630                       n, OCSP_response_status_str(n));
0631         goto error;
0632     }
0633 
0634     basic = OCSP_response_get1_basic(ocsp);
0635     if (basic == NULL) {
0636         ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
0637                       "OCSP_response_get1_basic() failed");
0638         goto error;
0639     }
0640 
0641     store = SSL_CTX_get_cert_store(staple->ssl_ctx);
0642     if (store == NULL) {
0643         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
0644                       "SSL_CTX_get_cert_store() failed");
0645         goto error;
0646     }
0647 
0648 #ifdef SSL_CTRL_SELECT_CURRENT_CERT
0649     /* OpenSSL 1.0.2+ */
0650     SSL_CTX_select_current_cert(staple->ssl_ctx, ctx->cert);
0651 #endif
0652 
0653 #ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
0654     /* OpenSSL 1.0.1+ */
0655     SSL_CTX_get_extra_chain_certs(staple->ssl_ctx, &chain);
0656 #else
0657     chain = staple->ssl_ctx->extra_certs;
0658 #endif
0659 
0660     if (OCSP_basic_verify(basic, chain, store,
0661                           staple->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY)
0662         != 1)
0663     {
0664         ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
0665                       "OCSP_basic_verify() failed");
0666         goto error;
0667     }
0668 
0669     id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
0670     if (id == NULL) {
0671         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
0672                       "OCSP_cert_to_id() failed");
0673         goto error;
0674     }
0675 
0676     if (OCSP_resp_find_status(basic, id, &n, NULL, NULL,
0677                               &thisupdate, &nextupdate)
0678         != 1)
0679     {
0680         ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
0681                       "certificate status not found in the OCSP response");
0682         goto error;
0683     }
0684 
0685     if (n != V_OCSP_CERTSTATUS_GOOD) {
0686         ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
0687                       "certificate status \"%s\" in the OCSP response",
0688                       OCSP_cert_status_str(n));
0689         goto error;
0690     }
0691 
0692     if (OCSP_check_validity(thisupdate, nextupdate, 300, -1) != 1) {
0693         ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
0694                       "OCSP_check_validity() failed");
0695         goto error;
0696     }
0697 
0698     if (nextupdate) {
0699         valid = ngx_ssl_stapling_time(nextupdate);
0700         if (valid == (time_t) NGX_ERROR) {
0701             ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
0702                           "invalid nextUpdate time in certificate status");
0703             goto error;
0704         }
0705 
0706     } else {
0707         valid = NGX_MAX_TIME_T_VALUE;
0708     }
0709 
0710     OCSP_CERTID_free(id);
0711     OCSP_BASICRESP_free(basic);
0712     OCSP_RESPONSE_free(ocsp);
0713 
0714     id = NULL;
0715     basic = NULL;
0716     ocsp = NULL;
0717 
0718     /* copy the response to memory not in ctx->pool */
0719 
0720     response.len = len;
0721     response.data = ngx_alloc(response.len, ctx->log);
0722 
0723     if (response.data == NULL) {
0724         goto error;
0725     }
0726 
0727     ngx_memcpy(response.data, ctx->response->pos, response.len);
0728 
0729     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
0730                    "ssl ocsp response, %s, %uz",
0731                    OCSP_cert_status_str(n), response.len);
0732 
0733     if (staple->staple.data) {
0734         ngx_free(staple->staple.data);
0735     }
0736 
0737     staple->staple = response;
0738     staple->valid = valid;
0739 
0740     /*
0741      * refresh before the response expires,
0742      * but not earlier than in 5 minutes, and at least in an hour
0743      */
0744 
0745     staple->loading = 0;
0746     staple->refresh = ngx_max(ngx_min(valid - 300, now + 3600), now + 300);
0747 
0748     ngx_ssl_ocsp_done(ctx);
0749     return;
0750 
0751 error:
0752 
0753     staple->loading = 0;
0754     staple->refresh = now + 300;
0755 
0756     if (id) {
0757         OCSP_CERTID_free(id);
0758     }
0759 
0760     if (basic) {
0761         OCSP_BASICRESP_free(basic);
0762     }
0763 
0764     if (ocsp) {
0765         OCSP_RESPONSE_free(ocsp);
0766     }
0767 
0768     ngx_ssl_ocsp_done(ctx);
0769 }
0770 
0771 
0772 static time_t
0773 ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time)
0774 {
0775     BIO     *bio;
0776     char    *value;
0777     size_t   len;
0778     time_t   time;
0779 
0780     /*
0781      * OpenSSL doesn't provide a way to convert ASN1_GENERALIZEDTIME
0782      * into time_t.  To do this, we use ASN1_GENERALIZEDTIME_print(),
0783      * which uses the "MMM DD HH:MM:SS YYYY [GMT]" format (e.g.,
0784      * "Feb  3 00:55:52 2015 GMT"), and parse the result.
0785      */
0786 
0787     bio = BIO_new(BIO_s_mem());
0788     if (bio == NULL) {
0789         return NGX_ERROR;
0790     }
0791 
0792     /* fake weekday prepended to match C asctime() format */
0793 
0794     BIO_write(bio, "Tue ", sizeof("Tue ") - 1);
0795     ASN1_GENERALIZEDTIME_print(bio, asn1time);
0796     len = BIO_get_mem_data(bio, &value);
0797 
0798     time = ngx_parse_http_time((u_char *) value, len);
0799 
0800     BIO_free(bio);
0801 
0802     return time;
0803 }
0804 
0805 
0806 static void
0807 ngx_ssl_stapling_cleanup(void *data)
0808 {
0809     ngx_ssl_stapling_t  *staple = data;
0810 
0811     if (staple->issuer) {
0812         X509_free(staple->issuer);
0813     }
0814 
0815     if (staple->staple.data) {
0816         ngx_free(staple->staple.data);
0817     }
0818 }
0819 
0820 
0821 static ngx_ssl_ocsp_ctx_t *
0822 ngx_ssl_ocsp_start(void)
0823 {
0824     ngx_log_t           *log;
0825     ngx_pool_t          *pool;
0826     ngx_ssl_ocsp_ctx_t  *ctx;
0827 
0828     pool = ngx_create_pool(2048, ngx_cycle->log);
0829     if (pool == NULL) {
0830         return NULL;
0831     }
0832 
0833     ctx = ngx_pcalloc(pool, sizeof(ngx_ssl_ocsp_ctx_t));
0834     if (ctx == NULL) {
0835         ngx_destroy_pool(pool);
0836         return NULL;
0837     }
0838 
0839     log = ngx_palloc(pool, sizeof(ngx_log_t));
0840     if (log == NULL) {
0841         ngx_destroy_pool(pool);
0842         return NULL;
0843     }
0844 
0845     ctx->pool = pool;
0846 
0847     *log = *ctx->pool->log;
0848 
0849     ctx->pool->log = log;
0850     ctx->log = log;
0851 
0852     log->handler = ngx_ssl_ocsp_log_error;
0853     log->data = ctx;
0854     log->action = "requesting certificate status";
0855 
0856     return ctx;
0857 }
0858 
0859 
0860 static void
0861 ngx_ssl_ocsp_done(ngx_ssl_ocsp_ctx_t *ctx)
0862 {
0863     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
0864                    "ssl ocsp done");
0865 
0866     if (ctx->peer.connection) {
0867         ngx_close_connection(ctx->peer.connection);
0868     }
0869 
0870     ngx_destroy_pool(ctx->pool);
0871 }
0872 
0873 
0874 static void
0875 ngx_ssl_ocsp_error(ngx_ssl_ocsp_ctx_t *ctx)
0876 {
0877     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
0878                    "ssl ocsp error");
0879 
0880     ctx->code = 0;
0881     ctx->handler(ctx);
0882 }
0883 
0884 
0885 static void
0886 ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx)
0887 {
0888     ngx_resolver_ctx_t  *resolve, temp;
0889 
0890     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
0891                    "ssl ocsp request");
0892 
0893     if (ngx_ssl_ocsp_create_request(ctx) != NGX_OK) {
0894         ngx_ssl_ocsp_error(ctx);
0895         return;
0896     }
0897 
0898     if (ctx->resolver) {
0899         /* resolve OCSP responder hostname */
0900 
0901         temp.name = ctx->host;
0902 
0903         resolve = ngx_resolve_start(ctx->resolver, &temp);
0904         if (resolve == NULL) {
0905             ngx_ssl_ocsp_error(ctx);
0906             return;
0907         }
0908 
0909         if (resolve == NGX_NO_RESOLVER) {
0910             ngx_log_error(NGX_LOG_WARN, ctx->log, 0,
0911                           "no resolver defined to resolve %V", &ctx->host);
0912             goto connect;
0913         }
0914 
0915         resolve->name = ctx->host;
0916         resolve->handler = ngx_ssl_ocsp_resolve_handler;
0917         resolve->data = ctx;
0918         resolve->timeout = ctx->resolver_timeout;
0919 
0920         if (ngx_resolve_name(resolve) != NGX_OK) {
0921             ngx_ssl_ocsp_error(ctx);
0922             return;
0923         }
0924 
0925         return;
0926     }
0927 
0928 connect:
0929 
0930     ngx_ssl_ocsp_connect(ctx);
0931 }
0932 
0933 
0934 static void
0935 ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve)
0936 {
0937     ngx_ssl_ocsp_ctx_t *ctx = resolve->data;
0938 
0939     u_char           *p;
0940     size_t            len;
0941     socklen_t         socklen;
0942     ngx_uint_t        i;
0943     struct sockaddr  *sockaddr;
0944 
0945     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
0946                    "ssl ocsp resolve handler");
0947 
0948     if (resolve->state) {
0949         ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
0950                       "%V could not be resolved (%i: %s)",
0951                       &resolve->name, resolve->state,
0952                       ngx_resolver_strerror(resolve->state));
0953         goto failed;
0954     }
0955 
0956 #if (NGX_DEBUG)
0957     {
0958     u_char     text[NGX_SOCKADDR_STRLEN];
0959     ngx_str_t  addr;
0960 
0961     addr.data = text;
0962 
0963     for (i = 0; i < resolve->naddrs; i++) {
0964         addr.len = ngx_sock_ntop(resolve->addrs[i].sockaddr,
0965                                  resolve->addrs[i].socklen,
0966                                  text, NGX_SOCKADDR_STRLEN, 0);
0967 
0968         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
0969                        "name was resolved to %V", &addr);
0970 
0971     }
0972     }
0973 #endif
0974 
0975     ctx->naddrs = resolve->naddrs;
0976     ctx->addrs = ngx_pcalloc(ctx->pool, ctx->naddrs * sizeof(ngx_addr_t));
0977 
0978     if (ctx->addrs == NULL) {
0979         goto failed;
0980     }
0981 
0982     for (i = 0; i < resolve->naddrs; i++) {
0983 
0984         socklen = resolve->addrs[i].socklen;
0985 
0986         sockaddr = ngx_palloc(ctx->pool, socklen);
0987         if (sockaddr == NULL) {
0988             goto failed;
0989         }
0990 
0991         ngx_memcpy(sockaddr, resolve->addrs[i].sockaddr, socklen);
0992         ngx_inet_set_port(sockaddr, ctx->port);
0993 
0994         ctx->addrs[i].sockaddr = sockaddr;
0995         ctx->addrs[i].socklen = socklen;
0996 
0997         p = ngx_pnalloc(ctx->pool, NGX_SOCKADDR_STRLEN);
0998         if (p == NULL) {
0999             goto failed;
1000         }
1001 
1002         len = ngx_sock_ntop(sockaddr, socklen, p, NGX_SOCKADDR_STRLEN, 1);
1003 
1004         ctx->addrs[i].name.len = len;
1005         ctx->addrs[i].name.data = p;
1006     }
1007 
1008     ngx_resolve_name_done(resolve);
1009 
1010     ngx_ssl_ocsp_connect(ctx);
1011     return;
1012 
1013 failed:
1014 
1015     ngx_resolve_name_done(resolve);
1016     ngx_ssl_ocsp_error(ctx);
1017 }
1018 
1019 
1020 static void
1021 ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx)
1022 {
1023     ngx_int_t  rc;
1024 
1025     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1026                    "ssl ocsp connect");
1027 
1028     /* TODO: use all ip addresses */
1029 
1030     ctx->peer.sockaddr = ctx->addrs[0].sockaddr;
1031     ctx->peer.socklen = ctx->addrs[0].socklen;
1032     ctx->peer.name = &ctx->addrs[0].name;
1033     ctx->peer.get = ngx_event_get_peer;
1034     ctx->peer.log = ctx->log;
1035     ctx->peer.log_error = NGX_ERROR_ERR;
1036 
1037     rc = ngx_event_connect_peer(&ctx->peer);
1038 
1039     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1040                    "ssl ocsp connect peer done");
1041 
1042     if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
1043         ngx_ssl_ocsp_error(ctx);
1044         return;
1045     }
1046 
1047     ctx->peer.connection->data = ctx;
1048     ctx->peer.connection->pool = ctx->pool;
1049 
1050     ctx->peer.connection->read->handler = ngx_ssl_ocsp_read_handler;
1051     ctx->peer.connection->write->handler = ngx_ssl_ocsp_write_handler;
1052 
1053     ctx->process = ngx_ssl_ocsp_process_status_line;
1054 
1055     ngx_add_timer(ctx->peer.connection->read, ctx->timeout);
1056     ngx_add_timer(ctx->peer.connection->write, ctx->timeout);
1057 
1058     if (rc == NGX_OK) {
1059         ngx_ssl_ocsp_write_handler(ctx->peer.connection->write);
1060         return;
1061     }
1062 }
1063 
1064 
1065 static void
1066 ngx_ssl_ocsp_write_handler(ngx_event_t *wev)
1067 {
1068     ssize_t              n, size;
1069     ngx_connection_t    *c;
1070     ngx_ssl_ocsp_ctx_t  *ctx;
1071 
1072     c = wev->data;
1073     ctx = c->data;
1074 
1075     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, wev->log, 0,
1076                    "ssl ocsp write handler");
1077 
1078     if (wev->timedout) {
1079         ngx_log_error(NGX_LOG_ERR, wev->log, NGX_ETIMEDOUT,
1080                       "OCSP responder timed out");
1081         ngx_ssl_ocsp_error(ctx);
1082         return;
1083     }
1084 
1085     size = ctx->request->last - ctx->request->pos;
1086 
1087     n = ngx_send(c, ctx->request->pos, size);
1088 
1089     if (n == NGX_ERROR) {
1090         ngx_ssl_ocsp_error(ctx);
1091         return;
1092     }
1093 
1094     if (n > 0) {
1095         ctx->request->pos += n;
1096 
1097         if (n == size) {
1098             wev->handler = ngx_ssl_ocsp_dummy_handler;
1099 
1100             if (wev->timer_set) {
1101                 ngx_del_timer(wev);
1102             }
1103 
1104             if (ngx_handle_write_event(wev, 0) != NGX_OK) {
1105                 ngx_ssl_ocsp_error(ctx);
1106             }
1107 
1108             return;
1109         }
1110     }
1111 
1112     if (!wev->timer_set) {
1113         ngx_add_timer(wev, ctx->timeout);
1114     }
1115 }
1116 
1117 
1118 static void
1119 ngx_ssl_ocsp_read_handler(ngx_event_t *rev)
1120 {
1121     ssize_t              n, size;
1122     ngx_int_t            rc;
1123     ngx_connection_t    *c;
1124     ngx_ssl_ocsp_ctx_t  *ctx;
1125 
1126     c = rev->data;
1127     ctx = c->data;
1128 
1129     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, rev->log, 0,
1130                    "ssl ocsp read handler");
1131 
1132     if (rev->timedout) {
1133         ngx_log_error(NGX_LOG_ERR, rev->log, NGX_ETIMEDOUT,
1134                       "OCSP responder timed out");
1135         ngx_ssl_ocsp_error(ctx);
1136         return;
1137     }
1138 
1139     if (ctx->response == NULL) {
1140         ctx->response = ngx_create_temp_buf(ctx->pool, 16384);
1141         if (ctx->response == NULL) {
1142             ngx_ssl_ocsp_error(ctx);
1143             return;
1144         }
1145     }
1146 
1147     for ( ;; ) {
1148 
1149         size = ctx->response->end - ctx->response->last;
1150 
1151         n = ngx_recv(c, ctx->response->last, size);
1152 
1153         if (n > 0) {
1154             ctx->response->last += n;
1155 
1156             rc = ctx->process(ctx);
1157 
1158             if (rc == NGX_ERROR) {
1159                 ngx_ssl_ocsp_error(ctx);
1160                 return;
1161             }
1162 
1163             continue;
1164         }
1165 
1166         if (n == NGX_AGAIN) {
1167 
1168             if (ngx_handle_read_event(rev, 0) != NGX_OK) {
1169                 ngx_ssl_ocsp_error(ctx);
1170             }
1171 
1172             return;
1173         }
1174 
1175         break;
1176     }
1177 
1178     ctx->done = 1;
1179 
1180     rc = ctx->process(ctx);
1181 
1182     if (rc == NGX_DONE) {
1183         /* ctx->handler() was called */
1184         return;
1185     }
1186 
1187     ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1188                   "OCSP responder prematurely closed connection");
1189 
1190     ngx_ssl_ocsp_error(ctx);
1191 }
1192 
1193 
1194 static void
1195 ngx_ssl_ocsp_dummy_handler(ngx_event_t *ev)
1196 {
1197     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0,
1198                    "ssl ocsp dummy handler");
1199 }
1200 
1201 
1202 static ngx_int_t
1203 ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx)
1204 {
1205     int            len;
1206     u_char        *p;
1207     uintptr_t      escape;
1208     ngx_str_t      binary, base64;
1209     ngx_buf_t     *b;
1210     OCSP_CERTID   *id;
1211     OCSP_REQUEST  *ocsp;
1212 
1213     ocsp = OCSP_REQUEST_new();
1214     if (ocsp == NULL) {
1215         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1216                       "OCSP_REQUEST_new() failed");
1217         return NGX_ERROR;
1218     }
1219 
1220     id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
1221     if (id == NULL) {
1222         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1223                       "OCSP_cert_to_id() failed");
1224         goto failed;
1225     }
1226 
1227     if (OCSP_request_add0_id(ocsp, id) == NULL) {
1228         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1229                       "OCSP_request_add0_id() failed");
1230         OCSP_CERTID_free(id);
1231         goto failed;
1232     }
1233 
1234     len = i2d_OCSP_REQUEST(ocsp, NULL);
1235     if (len <= 0) {
1236         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1237                       "i2d_OCSP_REQUEST() failed");
1238         goto failed;
1239     }
1240 
1241     binary.len = len;
1242     binary.data = ngx_palloc(ctx->pool, len);
1243     if (binary.data == NULL) {
1244         goto failed;
1245     }
1246 
1247     p = binary.data;
1248     len = i2d_OCSP_REQUEST(ocsp, &p);
1249     if (len <= 0) {
1250         ngx_ssl_error(NGX_LOG_EMERG, ctx->log, 0,
1251                       "i2d_OCSP_REQUEST() failed");
1252         goto failed;
1253     }
1254 
1255     base64.len = ngx_base64_encoded_length(binary.len);
1256     base64.data = ngx_palloc(ctx->pool, base64.len);
1257     if (base64.data == NULL) {
1258         goto failed;
1259     }
1260 
1261     ngx_encode_base64(&base64, &binary);
1262 
1263     escape = ngx_escape_uri(NULL, base64.data, base64.len,
1264                             NGX_ESCAPE_URI_COMPONENT);
1265 
1266     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1267                    "ssl ocsp request length %z, escape %d",
1268                    base64.len, (int) escape);
1269 
1270     len = sizeof("GET ") - 1 + ctx->uri.len + sizeof("/") - 1
1271           + base64.len + 2 * escape + sizeof(" HTTP/1.0" CRLF) - 1
1272           + sizeof("Host: ") - 1 + ctx->host.len + sizeof(CRLF) - 1
1273           + sizeof(CRLF) - 1;
1274 
1275     b = ngx_create_temp_buf(ctx->pool, len);
1276     if (b == NULL) {
1277         goto failed;
1278     }
1279 
1280     p = b->last;
1281 
1282     p = ngx_cpymem(p, "GET ", sizeof("GET ") - 1);
1283     p = ngx_cpymem(p, ctx->uri.data, ctx->uri.len);
1284 
1285     if (ctx->uri.data[ctx->uri.len - 1] != '/') {
1286         *p++ = '/';
1287     }
1288 
1289     if (escape == 0) {
1290         p = ngx_cpymem(p, base64.data, base64.len);
1291 
1292     } else {
1293         p = (u_char *) ngx_escape_uri(p, base64.data, base64.len,
1294                                       NGX_ESCAPE_URI_COMPONENT);
1295     }
1296 
1297     p = ngx_cpymem(p, " HTTP/1.0" CRLF, sizeof(" HTTP/1.0" CRLF) - 1);
1298     p = ngx_cpymem(p, "Host: ", sizeof("Host: ") - 1);
1299     p = ngx_cpymem(p, ctx->host.data, ctx->host.len);
1300     *p++ = CR; *p++ = LF;
1301 
1302     /* add "\r\n" at the header end */
1303     *p++ = CR; *p++ = LF;
1304 
1305     b->last = p;
1306     ctx->request = b;
1307 
1308     OCSP_REQUEST_free(ocsp);
1309 
1310     return NGX_OK;
1311 
1312 failed:
1313 
1314     OCSP_REQUEST_free(ocsp);
1315 
1316     return NGX_ERROR;
1317 }
1318 
1319 
1320 static ngx_int_t
1321 ngx_ssl_ocsp_process_status_line(ngx_ssl_ocsp_ctx_t *ctx)
1322 {
1323     ngx_int_t  rc;
1324 
1325     rc = ngx_ssl_ocsp_parse_status_line(ctx);
1326 
1327     if (rc == NGX_OK) {
1328         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1329                        "ssl ocsp status %ui \"%*s\"",
1330                        ctx->code,
1331                        ctx->header_end - ctx->header_start,
1332                        ctx->header_start);
1333 
1334         ctx->process = ngx_ssl_ocsp_process_headers;
1335         return ctx->process(ctx);
1336     }
1337 
1338     if (rc == NGX_AGAIN) {
1339         return NGX_AGAIN;
1340     }
1341 
1342     /* rc == NGX_ERROR */
1343 
1344     ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1345                   "OCSP responder sent invalid response");
1346 
1347     return NGX_ERROR;
1348 }
1349 
1350 
1351 static ngx_int_t
1352 ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t *ctx)
1353 {
1354     u_char      ch;
1355     u_char     *p;
1356     ngx_buf_t  *b;
1357     enum {
1358         sw_start = 0,
1359         sw_H,
1360         sw_HT,
1361         sw_HTT,
1362         sw_HTTP,
1363         sw_first_major_digit,
1364         sw_major_digit,
1365         sw_first_minor_digit,
1366         sw_minor_digit,
1367         sw_status,
1368         sw_space_after_status,
1369         sw_status_text,
1370         sw_almost_done
1371     } state;
1372 
1373     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1374                    "ssl ocsp process status line");
1375 
1376     state = ctx->state;
1377     b = ctx->response;
1378 
1379     for (p = b->pos; p < b->last; p++) {
1380         ch = *p;
1381 
1382         switch (state) {
1383 
1384         /* "HTTP/" */
1385         case sw_start:
1386             switch (ch) {
1387             case 'H':
1388                 state = sw_H;
1389                 break;
1390             default:
1391                 return NGX_ERROR;
1392             }
1393             break;
1394 
1395         case sw_H:
1396             switch (ch) {
1397             case 'T':
1398                 state = sw_HT;
1399                 break;
1400             default:
1401                 return NGX_ERROR;
1402             }
1403             break;
1404 
1405         case sw_HT:
1406             switch (ch) {
1407             case 'T':
1408                 state = sw_HTT;
1409                 break;
1410             default:
1411                 return NGX_ERROR;
1412             }
1413             break;
1414 
1415         case sw_HTT:
1416             switch (ch) {
1417             case 'P':
1418                 state = sw_HTTP;
1419                 break;
1420             default:
1421                 return NGX_ERROR;
1422             }
1423             break;
1424 
1425         case sw_HTTP:
1426             switch (ch) {
1427             case '/':
1428                 state = sw_first_major_digit;
1429                 break;
1430             default:
1431                 return NGX_ERROR;
1432             }
1433             break;
1434 
1435         /* the first digit of major HTTP version */
1436         case sw_first_major_digit:
1437             if (ch < '1' || ch > '9') {
1438                 return NGX_ERROR;
1439             }
1440 
1441             state = sw_major_digit;
1442             break;
1443 
1444         /* the major HTTP version or dot */
1445         case sw_major_digit:
1446             if (ch == '.') {
1447                 state = sw_first_minor_digit;
1448                 break;
1449             }
1450 
1451             if (ch < '0' || ch > '9') {
1452                 return NGX_ERROR;
1453             }
1454 
1455             break;
1456 
1457         /* the first digit of minor HTTP version */
1458         case sw_first_minor_digit:
1459             if (ch < '0' || ch > '9') {
1460                 return NGX_ERROR;
1461             }
1462 
1463             state = sw_minor_digit;
1464             break;
1465 
1466         /* the minor HTTP version or the end of the request line */
1467         case sw_minor_digit:
1468             if (ch == ' ') {
1469                 state = sw_status;
1470                 break;
1471             }
1472 
1473             if (ch < '0' || ch > '9') {
1474                 return NGX_ERROR;
1475             }
1476 
1477             break;
1478 
1479         /* HTTP status code */
1480         case sw_status:
1481             if (ch == ' ') {
1482                 break;
1483             }
1484 
1485             if (ch < '0' || ch > '9') {
1486                 return NGX_ERROR;
1487             }
1488 
1489             ctx->code = ctx->code * 10 + ch - '0';
1490 
1491             if (++ctx->count == 3) {
1492                 state = sw_space_after_status;
1493                 ctx->header_start = p - 2;
1494             }
1495 
1496             break;
1497 
1498         /* space or end of line */
1499         case sw_space_after_status:
1500             switch (ch) {
1501             case ' ':
1502                 state = sw_status_text;
1503                 break;
1504             case '.':                    /* IIS may send 403.1, 403.2, etc */
1505                 state = sw_status_text;
1506                 break;
1507             case CR:
1508                 state = sw_almost_done;
1509                 break;
1510             case LF:
1511                 ctx->header_end = p;
1512                 goto done;
1513             default:
1514                 return NGX_ERROR;
1515             }
1516             break;
1517 
1518         /* any text until end of line */
1519         case sw_status_text:
1520             switch (ch) {
1521             case CR:
1522                 state = sw_almost_done;
1523                 break;
1524             case LF:
1525                 ctx->header_end = p;
1526                 goto done;
1527             }
1528             break;
1529 
1530         /* end of status line */
1531         case sw_almost_done:
1532             switch (ch) {
1533             case LF:
1534                 ctx->header_end = p - 1;
1535                 goto done;
1536             default:
1537                 return NGX_ERROR;
1538             }
1539         }
1540     }
1541 
1542     b->pos = p;
1543     ctx->state = state;
1544 
1545     return NGX_AGAIN;
1546 
1547 done:
1548 
1549     b->pos = p + 1;
1550     ctx->state = sw_start;
1551 
1552     return NGX_OK;
1553 }
1554 
1555 
1556 static ngx_int_t
1557 ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx)
1558 {
1559     size_t     len;
1560     ngx_int_t  rc;
1561 
1562     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1563                    "ssl ocsp process headers");
1564 
1565     for ( ;; ) {
1566         rc = ngx_ssl_ocsp_parse_header_line(ctx);
1567 
1568         if (rc == NGX_OK) {
1569 
1570             ngx_log_debug4(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1571                            "ssl ocsp header \"%*s: %*s\"",
1572                            ctx->header_name_end - ctx->header_name_start,
1573                            ctx->header_name_start,
1574                            ctx->header_end - ctx->header_start,
1575                            ctx->header_start);
1576 
1577             len = ctx->header_name_end - ctx->header_name_start;
1578 
1579             if (len == sizeof("Content-Type") - 1
1580                 && ngx_strncasecmp(ctx->header_name_start,
1581                                    (u_char *) "Content-Type",
1582                                    sizeof("Content-Type") - 1)
1583                    == 0)
1584             {
1585                 len = ctx->header_end - ctx->header_start;
1586 
1587                 if (len != sizeof("application/ocsp-response") - 1
1588                     || ngx_strncasecmp(ctx->header_start,
1589                                        (u_char *) "application/ocsp-response",
1590                                        sizeof("application/ocsp-response") - 1)
1591                        != 0)
1592                 {
1593                     ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1594                                   "OCSP responder sent invalid "
1595                                   "\"Content-Type\" header: \"%*s\"",
1596                                   ctx->header_end - ctx->header_start,
1597                                   ctx->header_start);
1598                     return NGX_ERROR;
1599                 }
1600 
1601                 continue;
1602             }
1603 
1604             /* TODO: honor Content-Length */
1605 
1606             continue;
1607         }
1608 
1609         if (rc == NGX_DONE) {
1610             break;
1611         }
1612 
1613         if (rc == NGX_AGAIN) {
1614             return NGX_AGAIN;
1615         }
1616 
1617         /* rc == NGX_ERROR */
1618 
1619         ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1620                       "OCSP responder sent invalid response");
1621 
1622         return NGX_ERROR;
1623     }
1624 
1625     ctx->process = ngx_ssl_ocsp_process_body;
1626     return ctx->process(ctx);
1627 }
1628 
1629 
1630 static ngx_int_t
1631 ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx)
1632 {
1633     u_char  c, ch, *p;
1634     enum {
1635         sw_start = 0,
1636         sw_name,
1637         sw_space_before_value,
1638         sw_value,
1639         sw_space_after_value,
1640         sw_almost_done,
1641         sw_header_almost_done
1642     } state;
1643 
1644     state = ctx->state;
1645 
1646     for (p = ctx->response->pos; p < ctx->response->last; p++) {
1647         ch = *p;
1648 
1649 #if 0
1650         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1651                        "s:%d in:'%02Xd:%c'", state, ch, ch);
1652 #endif
1653 
1654         switch (state) {
1655 
1656         /* first char */
1657         case sw_start:
1658 
1659             switch (ch) {
1660             case CR:
1661                 ctx->header_end = p;
1662                 state = sw_header_almost_done;
1663                 break;
1664             case LF:
1665                 ctx->header_end = p;
1666                 goto header_done;
1667             default:
1668                 state = sw_name;
1669                 ctx->header_name_start = p;
1670 
1671                 c = (u_char) (ch | 0x20);
1672                 if (c >= 'a' && c <= 'z') {
1673                     break;
1674                 }
1675 
1676                 if (ch >= '0' && ch <= '9') {
1677                     break;
1678                 }
1679 
1680                 return NGX_ERROR;
1681             }
1682             break;
1683 
1684         /* header name */
1685         case sw_name:
1686             c = (u_char) (ch | 0x20);
1687             if (c >= 'a' && c <= 'z') {
1688                 break;
1689             }
1690 
1691             if (ch == ':') {
1692                 ctx->header_name_end = p;
1693                 state = sw_space_before_value;
1694                 break;
1695             }
1696 
1697             if (ch == '-') {
1698                 break;
1699             }
1700 
1701             if (ch >= '0' && ch <= '9') {
1702                 break;
1703             }
1704 
1705             if (ch == CR) {
1706                 ctx->header_name_end = p;
1707                 ctx->header_start = p;
1708                 ctx->header_end = p;
1709                 state = sw_almost_done;
1710                 break;
1711             }
1712 
1713             if (ch == LF) {
1714                 ctx->header_name_end = p;
1715                 ctx->header_start = p;
1716                 ctx->header_end = p;
1717                 goto done;
1718             }
1719 
1720             return NGX_ERROR;
1721 
1722         /* space* before header value */
1723         case sw_space_before_value:
1724             switch (ch) {
1725             case ' ':
1726                 break;
1727             case CR:
1728                 ctx->header_start = p;
1729                 ctx->header_end = p;
1730                 state = sw_almost_done;
1731                 break;
1732             case LF:
1733                 ctx->header_start = p;
1734                 ctx->header_end = p;
1735                 goto done;
1736             default:
1737                 ctx->header_start = p;
1738                 state = sw_value;
1739                 break;
1740             }
1741             break;
1742 
1743         /* header value */
1744         case sw_value:
1745             switch (ch) {
1746             case ' ':
1747                 ctx->header_end = p;
1748                 state = sw_space_after_value;
1749                 break;
1750             case CR:
1751                 ctx->header_end = p;
1752                 state = sw_almost_done;
1753                 break;
1754             case LF:
1755                 ctx->header_end = p;
1756                 goto done;
1757             }
1758             break;
1759 
1760         /* space* before end of header line */
1761         case sw_space_after_value:
1762             switch (ch) {
1763             case ' ':
1764                 break;
1765             case CR:
1766                 state = sw_almost_done;
1767                 break;
1768             case LF:
1769                 goto done;
1770             default:
1771                 state = sw_value;
1772                 break;
1773             }
1774             break;
1775 
1776         /* end of header line */
1777         case sw_almost_done:
1778             switch (ch) {
1779             case LF:
1780                 goto done;
1781             default:
1782                 return NGX_ERROR;
1783             }
1784 
1785         /* end of header */
1786         case sw_header_almost_done:
1787             switch (ch) {
1788             case LF:
1789                 goto header_done;
1790             default:
1791                 return NGX_ERROR;
1792             }
1793         }
1794     }
1795 
1796     ctx->response->pos = p;
1797     ctx->state = state;
1798 
1799     return NGX_AGAIN;
1800 
1801 done:
1802 
1803     ctx->response->pos = p + 1;
1804     ctx->state = sw_start;
1805 
1806     return NGX_OK;
1807 
1808 header_done:
1809 
1810     ctx->response->pos = p + 1;
1811     ctx->state = sw_start;
1812 
1813     return NGX_DONE;
1814 }
1815 
1816 
1817 static ngx_int_t
1818 ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx)
1819 {
1820     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1821                    "ssl ocsp process body");
1822 
1823     if (ctx->done) {
1824         ctx->handler(ctx);
1825         return NGX_DONE;
1826     }
1827 
1828     return NGX_AGAIN;
1829 }
1830 
1831 
1832 static u_char *
1833 ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len)
1834 {
1835     u_char              *p;
1836     ngx_ssl_ocsp_ctx_t  *ctx;
1837 
1838     p = buf;
1839 
1840     if (log->action) {
1841         p = ngx_snprintf(buf, len, " while %s", log->action);
1842         len -= p - buf;
1843         buf = p;
1844     }
1845 
1846     ctx = log->data;
1847 
1848     if (ctx) {
1849         p = ngx_snprintf(buf, len, ", responder: %V", &ctx->host);
1850         len -= p - buf;
1851         buf = p;
1852     }
1853 
1854     if (ctx && ctx->peer.name) {
1855         p = ngx_snprintf(buf, len, ", peer: %V", ctx->peer.name);
1856         len -= p - buf;
1857         buf = p;
1858     }
1859 
1860     if (ctx && ctx->name) {
1861         p = ngx_snprintf(buf, len, ", certificate: \"%s\"", ctx->name);
1862         len -= p - buf;
1863         buf = p;
1864     }
1865 
1866     return p;
1867 }
1868 
1869 
1870 #else
1871 
1872 
1873 ngx_int_t
1874 ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file,
1875     ngx_str_t *responder, ngx_uint_t verify)
1876 {
1877     ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
1878                   "\"ssl_stapling\" ignored, not supported");
1879 
1880     return NGX_OK;
1881 }
1882 
1883 
1884 ngx_int_t
1885 ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
1886     ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)
1887 {
1888     return NGX_OK;
1889 }
1890 
1891 
1892 #endif