Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.15.12 ]​[ nginx-1.16.0 ]​

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, "rb");
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 
0515     if (cert == NULL) {
0516         return rc;
0517     }
0518 
0519     staple = X509_get_ex_data(cert, ngx_ssl_stapling_index);
0520 
0521     if (staple == NULL) {
0522         return rc;
0523     }
0524 
0525     if (staple->staple.len
0526         && staple->valid >= ngx_time())
0527     {
0528         /* we have to copy ocsp response as OpenSSL will free it by itself */
0529 
0530         p = OPENSSL_malloc(staple->staple.len);
0531         if (p == NULL) {
0532             ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "OPENSSL_malloc() failed");
0533             return SSL_TLSEXT_ERR_NOACK;
0534         }
0535 
0536         ngx_memcpy(p, staple->staple.data, staple->staple.len);
0537 
0538         SSL_set_tlsext_status_ocsp_resp(ssl_conn, p, staple->staple.len);
0539 
0540         rc = SSL_TLSEXT_ERR_OK;
0541     }
0542 
0543     ngx_ssl_stapling_update(staple);
0544 
0545     return rc;
0546 }
0547 
0548 
0549 static void
0550 ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple)
0551 {
0552     ngx_ssl_ocsp_ctx_t  *ctx;
0553 
0554     if (staple->host.len == 0
0555         || staple->loading || staple->refresh >= ngx_time())
0556     {
0557         return;
0558     }
0559 
0560     staple->loading = 1;
0561 
0562     ctx = ngx_ssl_ocsp_start();
0563     if (ctx == NULL) {
0564         return;
0565     }
0566 
0567     ctx->cert = staple->cert;
0568     ctx->issuer = staple->issuer;
0569     ctx->name = staple->name;
0570 
0571     ctx->addrs = staple->addrs;
0572     ctx->host = staple->host;
0573     ctx->uri = staple->uri;
0574     ctx->port = staple->port;
0575     ctx->timeout = staple->timeout;
0576 
0577     ctx->resolver = staple->resolver;
0578     ctx->resolver_timeout = staple->resolver_timeout;
0579 
0580     ctx->handler = ngx_ssl_stapling_ocsp_handler;
0581     ctx->data = staple;
0582 
0583     ngx_ssl_ocsp_request(ctx);
0584 
0585     return;
0586 }
0587 
0588 
0589 static void
0590 ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
0591 {
0592 #if OPENSSL_VERSION_NUMBER >= 0x0090707fL
0593     const
0594 #endif
0595     u_char                *p;
0596     int                    n;
0597     size_t                 len;
0598     time_t                 now, valid;
0599     ngx_str_t              response;
0600     X509_STORE            *store;
0601     STACK_OF(X509)        *chain;
0602     OCSP_CERTID           *id;
0603     OCSP_RESPONSE         *ocsp;
0604     OCSP_BASICRESP        *basic;
0605     ngx_ssl_stapling_t    *staple;
0606     ASN1_GENERALIZEDTIME  *thisupdate, *nextupdate;
0607 
0608     staple = ctx->data;
0609     now = ngx_time();
0610     ocsp = NULL;
0611     basic = NULL;
0612     id = NULL;
0613 
0614     if (ctx->code != 200) {
0615         goto error;
0616     }
0617 
0618     /* check the response */
0619 
0620     len = ctx->response->last - ctx->response->pos;
0621     p = ctx->response->pos;
0622 
0623     ocsp = d2i_OCSP_RESPONSE(NULL, &p, len);
0624     if (ocsp == NULL) {
0625         ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
0626                       "d2i_OCSP_RESPONSE() failed");
0627         goto error;
0628     }
0629 
0630     n = OCSP_response_status(ocsp);
0631 
0632     if (n != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
0633         ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
0634                       "OCSP response not successful (%d: %s)",
0635                       n, OCSP_response_status_str(n));
0636         goto error;
0637     }
0638 
0639     basic = OCSP_response_get1_basic(ocsp);
0640     if (basic == NULL) {
0641         ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
0642                       "OCSP_response_get1_basic() failed");
0643         goto error;
0644     }
0645 
0646     store = SSL_CTX_get_cert_store(staple->ssl_ctx);
0647     if (store == NULL) {
0648         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
0649                       "SSL_CTX_get_cert_store() failed");
0650         goto error;
0651     }
0652 
0653 #ifdef SSL_CTRL_SELECT_CURRENT_CERT
0654     /* OpenSSL 1.0.2+ */
0655     SSL_CTX_select_current_cert(staple->ssl_ctx, ctx->cert);
0656 #endif
0657 
0658 #ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
0659     /* OpenSSL 1.0.1+ */
0660     SSL_CTX_get_extra_chain_certs(staple->ssl_ctx, &chain);
0661 #else
0662     chain = staple->ssl_ctx->extra_certs;
0663 #endif
0664 
0665     if (OCSP_basic_verify(basic, chain, store,
0666                           staple->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY)
0667         != 1)
0668     {
0669         ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
0670                       "OCSP_basic_verify() failed");
0671         goto error;
0672     }
0673 
0674     id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
0675     if (id == NULL) {
0676         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
0677                       "OCSP_cert_to_id() failed");
0678         goto error;
0679     }
0680 
0681     if (OCSP_resp_find_status(basic, id, &n, NULL, NULL,
0682                               &thisupdate, &nextupdate)
0683         != 1)
0684     {
0685         ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
0686                       "certificate status not found in the OCSP response");
0687         goto error;
0688     }
0689 
0690     if (n != V_OCSP_CERTSTATUS_GOOD) {
0691         ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
0692                       "certificate status \"%s\" in the OCSP response",
0693                       OCSP_cert_status_str(n));
0694         goto error;
0695     }
0696 
0697     if (OCSP_check_validity(thisupdate, nextupdate, 300, -1) != 1) {
0698         ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
0699                       "OCSP_check_validity() failed");
0700         goto error;
0701     }
0702 
0703     if (nextupdate) {
0704         valid = ngx_ssl_stapling_time(nextupdate);
0705         if (valid == (time_t) NGX_ERROR) {
0706             ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
0707                           "invalid nextUpdate time in certificate status");
0708             goto error;
0709         }
0710 
0711     } else {
0712         valid = NGX_MAX_TIME_T_VALUE;
0713     }
0714 
0715     OCSP_CERTID_free(id);
0716     OCSP_BASICRESP_free(basic);
0717     OCSP_RESPONSE_free(ocsp);
0718 
0719     id = NULL;
0720     basic = NULL;
0721     ocsp = NULL;
0722 
0723     /* copy the response to memory not in ctx->pool */
0724 
0725     response.len = len;
0726     response.data = ngx_alloc(response.len, ctx->log);
0727 
0728     if (response.data == NULL) {
0729         goto error;
0730     }
0731 
0732     ngx_memcpy(response.data, ctx->response->pos, response.len);
0733 
0734     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
0735                    "ssl ocsp response, %s, %uz",
0736                    OCSP_cert_status_str(n), response.len);
0737 
0738     if (staple->staple.data) {
0739         ngx_free(staple->staple.data);
0740     }
0741 
0742     staple->staple = response;
0743     staple->valid = valid;
0744 
0745     /*
0746      * refresh before the response expires,
0747      * but not earlier than in 5 minutes, and at least in an hour
0748      */
0749 
0750     staple->loading = 0;
0751     staple->refresh = ngx_max(ngx_min(valid - 300, now + 3600), now + 300);
0752 
0753     ngx_ssl_ocsp_done(ctx);
0754     return;
0755 
0756 error:
0757 
0758     staple->loading = 0;
0759     staple->refresh = now + 300;
0760 
0761     if (id) {
0762         OCSP_CERTID_free(id);
0763     }
0764 
0765     if (basic) {
0766         OCSP_BASICRESP_free(basic);
0767     }
0768 
0769     if (ocsp) {
0770         OCSP_RESPONSE_free(ocsp);
0771     }
0772 
0773     ngx_ssl_ocsp_done(ctx);
0774 }
0775 
0776 
0777 static time_t
0778 ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time)
0779 {
0780     BIO     *bio;
0781     char    *value;
0782     size_t   len;
0783     time_t   time;
0784 
0785     /*
0786      * OpenSSL doesn't provide a way to convert ASN1_GENERALIZEDTIME
0787      * into time_t.  To do this, we use ASN1_GENERALIZEDTIME_print(),
0788      * which uses the "MMM DD HH:MM:SS YYYY [GMT]" format (e.g.,
0789      * "Feb  3 00:55:52 2015 GMT"), and parse the result.
0790      */
0791 
0792     bio = BIO_new(BIO_s_mem());
0793     if (bio == NULL) {
0794         return NGX_ERROR;
0795     }
0796 
0797     /* fake weekday prepended to match C asctime() format */
0798 
0799     BIO_write(bio, "Tue ", sizeof("Tue ") - 1);
0800     ASN1_GENERALIZEDTIME_print(bio, asn1time);
0801     len = BIO_get_mem_data(bio, &value);
0802 
0803     time = ngx_parse_http_time((u_char *) value, len);
0804 
0805     BIO_free(bio);
0806 
0807     return time;
0808 }
0809 
0810 
0811 static void
0812 ngx_ssl_stapling_cleanup(void *data)
0813 {
0814     ngx_ssl_stapling_t  *staple = data;
0815 
0816     if (staple->issuer) {
0817         X509_free(staple->issuer);
0818     }
0819 
0820     if (staple->staple.data) {
0821         ngx_free(staple->staple.data);
0822     }
0823 }
0824 
0825 
0826 static ngx_ssl_ocsp_ctx_t *
0827 ngx_ssl_ocsp_start(void)
0828 {
0829     ngx_log_t           *log;
0830     ngx_pool_t          *pool;
0831     ngx_ssl_ocsp_ctx_t  *ctx;
0832 
0833     pool = ngx_create_pool(2048, ngx_cycle->log);
0834     if (pool == NULL) {
0835         return NULL;
0836     }
0837 
0838     ctx = ngx_pcalloc(pool, sizeof(ngx_ssl_ocsp_ctx_t));
0839     if (ctx == NULL) {
0840         ngx_destroy_pool(pool);
0841         return NULL;
0842     }
0843 
0844     log = ngx_palloc(pool, sizeof(ngx_log_t));
0845     if (log == NULL) {
0846         ngx_destroy_pool(pool);
0847         return NULL;
0848     }
0849 
0850     ctx->pool = pool;
0851 
0852     *log = *ctx->pool->log;
0853 
0854     ctx->pool->log = log;
0855     ctx->log = log;
0856 
0857     log->handler = ngx_ssl_ocsp_log_error;
0858     log->data = ctx;
0859     log->action = "requesting certificate status";
0860 
0861     return ctx;
0862 }
0863 
0864 
0865 static void
0866 ngx_ssl_ocsp_done(ngx_ssl_ocsp_ctx_t *ctx)
0867 {
0868     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
0869                    "ssl ocsp done");
0870 
0871     if (ctx->peer.connection) {
0872         ngx_close_connection(ctx->peer.connection);
0873     }
0874 
0875     ngx_destroy_pool(ctx->pool);
0876 }
0877 
0878 
0879 static void
0880 ngx_ssl_ocsp_error(ngx_ssl_ocsp_ctx_t *ctx)
0881 {
0882     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
0883                    "ssl ocsp error");
0884 
0885     ctx->code = 0;
0886     ctx->handler(ctx);
0887 }
0888 
0889 
0890 static void
0891 ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx)
0892 {
0893     ngx_resolver_ctx_t  *resolve, temp;
0894 
0895     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
0896                    "ssl ocsp request");
0897 
0898     if (ngx_ssl_ocsp_create_request(ctx) != NGX_OK) {
0899         ngx_ssl_ocsp_error(ctx);
0900         return;
0901     }
0902 
0903     if (ctx->resolver) {
0904         /* resolve OCSP responder hostname */
0905 
0906         temp.name = ctx->host;
0907 
0908         resolve = ngx_resolve_start(ctx->resolver, &temp);
0909         if (resolve == NULL) {
0910             ngx_ssl_ocsp_error(ctx);
0911             return;
0912         }
0913 
0914         if (resolve == NGX_NO_RESOLVER) {
0915             ngx_log_error(NGX_LOG_WARN, ctx->log, 0,
0916                           "no resolver defined to resolve %V", &ctx->host);
0917             goto connect;
0918         }
0919 
0920         resolve->name = ctx->host;
0921         resolve->handler = ngx_ssl_ocsp_resolve_handler;
0922         resolve->data = ctx;
0923         resolve->timeout = ctx->resolver_timeout;
0924 
0925         if (ngx_resolve_name(resolve) != NGX_OK) {
0926             ngx_ssl_ocsp_error(ctx);
0927             return;
0928         }
0929 
0930         return;
0931     }
0932 
0933 connect:
0934 
0935     ngx_ssl_ocsp_connect(ctx);
0936 }
0937 
0938 
0939 static void
0940 ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve)
0941 {
0942     ngx_ssl_ocsp_ctx_t *ctx = resolve->data;
0943 
0944     u_char           *p;
0945     size_t            len;
0946     socklen_t         socklen;
0947     ngx_uint_t        i;
0948     struct sockaddr  *sockaddr;
0949 
0950     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
0951                    "ssl ocsp resolve handler");
0952 
0953     if (resolve->state) {
0954         ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
0955                       "%V could not be resolved (%i: %s)",
0956                       &resolve->name, resolve->state,
0957                       ngx_resolver_strerror(resolve->state));
0958         goto failed;
0959     }
0960 
0961 #if (NGX_DEBUG)
0962     {
0963     u_char     text[NGX_SOCKADDR_STRLEN];
0964     ngx_str_t  addr;
0965 
0966     addr.data = text;
0967 
0968     for (i = 0; i < resolve->naddrs; i++) {
0969         addr.len = ngx_sock_ntop(resolve->addrs[i].sockaddr,
0970                                  resolve->addrs[i].socklen,
0971                                  text, NGX_SOCKADDR_STRLEN, 0);
0972 
0973         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
0974                        "name was resolved to %V", &addr);
0975 
0976     }
0977     }
0978 #endif
0979 
0980     ctx->naddrs = resolve->naddrs;
0981     ctx->addrs = ngx_pcalloc(ctx->pool, ctx->naddrs * sizeof(ngx_addr_t));
0982 
0983     if (ctx->addrs == NULL) {
0984         goto failed;
0985     }
0986 
0987     for (i = 0; i < resolve->naddrs; i++) {
0988 
0989         socklen = resolve->addrs[i].socklen;
0990 
0991         sockaddr = ngx_palloc(ctx->pool, socklen);
0992         if (sockaddr == NULL) {
0993             goto failed;
0994         }
0995 
0996         ngx_memcpy(sockaddr, resolve->addrs[i].sockaddr, socklen);
0997         ngx_inet_set_port(sockaddr, ctx->port);
0998 
0999         ctx->addrs[i].sockaddr = sockaddr;
1000         ctx->addrs[i].socklen = socklen;
1001 
1002         p = ngx_pnalloc(ctx->pool, NGX_SOCKADDR_STRLEN);
1003         if (p == NULL) {
1004             goto failed;
1005         }
1006 
1007         len = ngx_sock_ntop(sockaddr, socklen, p, NGX_SOCKADDR_STRLEN, 1);
1008 
1009         ctx->addrs[i].name.len = len;
1010         ctx->addrs[i].name.data = p;
1011     }
1012 
1013     ngx_resolve_name_done(resolve);
1014 
1015     ngx_ssl_ocsp_connect(ctx);
1016     return;
1017 
1018 failed:
1019 
1020     ngx_resolve_name_done(resolve);
1021     ngx_ssl_ocsp_error(ctx);
1022 }
1023 
1024 
1025 static void
1026 ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx)
1027 {
1028     ngx_int_t  rc;
1029 
1030     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1031                    "ssl ocsp connect");
1032 
1033     /* TODO: use all ip addresses */
1034 
1035     ctx->peer.sockaddr = ctx->addrs[0].sockaddr;
1036     ctx->peer.socklen = ctx->addrs[0].socklen;
1037     ctx->peer.name = &ctx->addrs[0].name;
1038     ctx->peer.get = ngx_event_get_peer;
1039     ctx->peer.log = ctx->log;
1040     ctx->peer.log_error = NGX_ERROR_ERR;
1041 
1042     rc = ngx_event_connect_peer(&ctx->peer);
1043 
1044     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1045                    "ssl ocsp connect peer done");
1046 
1047     if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
1048         ngx_ssl_ocsp_error(ctx);
1049         return;
1050     }
1051 
1052     ctx->peer.connection->data = ctx;
1053     ctx->peer.connection->pool = ctx->pool;
1054 
1055     ctx->peer.connection->read->handler = ngx_ssl_ocsp_read_handler;
1056     ctx->peer.connection->write->handler = ngx_ssl_ocsp_write_handler;
1057 
1058     ctx->process = ngx_ssl_ocsp_process_status_line;
1059 
1060     ngx_add_timer(ctx->peer.connection->read, ctx->timeout);
1061     ngx_add_timer(ctx->peer.connection->write, ctx->timeout);
1062 
1063     if (rc == NGX_OK) {
1064         ngx_ssl_ocsp_write_handler(ctx->peer.connection->write);
1065         return;
1066     }
1067 }
1068 
1069 
1070 static void
1071 ngx_ssl_ocsp_write_handler(ngx_event_t *wev)
1072 {
1073     ssize_t              n, size;
1074     ngx_connection_t    *c;
1075     ngx_ssl_ocsp_ctx_t  *ctx;
1076 
1077     c = wev->data;
1078     ctx = c->data;
1079 
1080     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, wev->log, 0,
1081                    "ssl ocsp write handler");
1082 
1083     if (wev->timedout) {
1084         ngx_log_error(NGX_LOG_ERR, wev->log, NGX_ETIMEDOUT,
1085                       "OCSP responder timed out");
1086         ngx_ssl_ocsp_error(ctx);
1087         return;
1088     }
1089 
1090     size = ctx->request->last - ctx->request->pos;
1091 
1092     n = ngx_send(c, ctx->request->pos, size);
1093 
1094     if (n == NGX_ERROR) {
1095         ngx_ssl_ocsp_error(ctx);
1096         return;
1097     }
1098 
1099     if (n > 0) {
1100         ctx->request->pos += n;
1101 
1102         if (n == size) {
1103             wev->handler = ngx_ssl_ocsp_dummy_handler;
1104 
1105             if (wev->timer_set) {
1106                 ngx_del_timer(wev);
1107             }
1108 
1109             if (ngx_handle_write_event(wev, 0) != NGX_OK) {
1110                 ngx_ssl_ocsp_error(ctx);
1111             }
1112 
1113             return;
1114         }
1115     }
1116 
1117     if (!wev->timer_set) {
1118         ngx_add_timer(wev, ctx->timeout);
1119     }
1120 }
1121 
1122 
1123 static void
1124 ngx_ssl_ocsp_read_handler(ngx_event_t *rev)
1125 {
1126     ssize_t              n, size;
1127     ngx_int_t            rc;
1128     ngx_connection_t    *c;
1129     ngx_ssl_ocsp_ctx_t  *ctx;
1130 
1131     c = rev->data;
1132     ctx = c->data;
1133 
1134     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, rev->log, 0,
1135                    "ssl ocsp read handler");
1136 
1137     if (rev->timedout) {
1138         ngx_log_error(NGX_LOG_ERR, rev->log, NGX_ETIMEDOUT,
1139                       "OCSP responder timed out");
1140         ngx_ssl_ocsp_error(ctx);
1141         return;
1142     }
1143 
1144     if (ctx->response == NULL) {
1145         ctx->response = ngx_create_temp_buf(ctx->pool, 16384);
1146         if (ctx->response == NULL) {
1147             ngx_ssl_ocsp_error(ctx);
1148             return;
1149         }
1150     }
1151 
1152     for ( ;; ) {
1153 
1154         size = ctx->response->end - ctx->response->last;
1155 
1156         n = ngx_recv(c, ctx->response->last, size);
1157 
1158         if (n > 0) {
1159             ctx->response->last += n;
1160 
1161             rc = ctx->process(ctx);
1162 
1163             if (rc == NGX_ERROR) {
1164                 ngx_ssl_ocsp_error(ctx);
1165                 return;
1166             }
1167 
1168             continue;
1169         }
1170 
1171         if (n == NGX_AGAIN) {
1172 
1173             if (ngx_handle_read_event(rev, 0) != NGX_OK) {
1174                 ngx_ssl_ocsp_error(ctx);
1175             }
1176 
1177             return;
1178         }
1179 
1180         break;
1181     }
1182 
1183     ctx->done = 1;
1184 
1185     rc = ctx->process(ctx);
1186 
1187     if (rc == NGX_DONE) {
1188         /* ctx->handler() was called */
1189         return;
1190     }
1191 
1192     ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1193                   "OCSP responder prematurely closed connection");
1194 
1195     ngx_ssl_ocsp_error(ctx);
1196 }
1197 
1198 
1199 static void
1200 ngx_ssl_ocsp_dummy_handler(ngx_event_t *ev)
1201 {
1202     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0,
1203                    "ssl ocsp dummy handler");
1204 }
1205 
1206 
1207 static ngx_int_t
1208 ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx)
1209 {
1210     int            len;
1211     u_char        *p;
1212     uintptr_t      escape;
1213     ngx_str_t      binary, base64;
1214     ngx_buf_t     *b;
1215     OCSP_CERTID   *id;
1216     OCSP_REQUEST  *ocsp;
1217 
1218     ocsp = OCSP_REQUEST_new();
1219     if (ocsp == NULL) {
1220         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1221                       "OCSP_REQUEST_new() failed");
1222         return NGX_ERROR;
1223     }
1224 
1225     id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
1226     if (id == NULL) {
1227         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1228                       "OCSP_cert_to_id() failed");
1229         goto failed;
1230     }
1231 
1232     if (OCSP_request_add0_id(ocsp, id) == NULL) {
1233         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1234                       "OCSP_request_add0_id() failed");
1235         OCSP_CERTID_free(id);
1236         goto failed;
1237     }
1238 
1239     len = i2d_OCSP_REQUEST(ocsp, NULL);
1240     if (len <= 0) {
1241         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1242                       "i2d_OCSP_REQUEST() failed");
1243         goto failed;
1244     }
1245 
1246     binary.len = len;
1247     binary.data = ngx_palloc(ctx->pool, len);
1248     if (binary.data == NULL) {
1249         goto failed;
1250     }
1251 
1252     p = binary.data;
1253     len = i2d_OCSP_REQUEST(ocsp, &p);
1254     if (len <= 0) {
1255         ngx_ssl_error(NGX_LOG_EMERG, ctx->log, 0,
1256                       "i2d_OCSP_REQUEST() failed");
1257         goto failed;
1258     }
1259 
1260     base64.len = ngx_base64_encoded_length(binary.len);
1261     base64.data = ngx_palloc(ctx->pool, base64.len);
1262     if (base64.data == NULL) {
1263         goto failed;
1264     }
1265 
1266     ngx_encode_base64(&base64, &binary);
1267 
1268     escape = ngx_escape_uri(NULL, base64.data, base64.len,
1269                             NGX_ESCAPE_URI_COMPONENT);
1270 
1271     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1272                    "ssl ocsp request length %z, escape %d",
1273                    base64.len, (int) escape);
1274 
1275     len = sizeof("GET ") - 1 + ctx->uri.len + sizeof("/") - 1
1276           + base64.len + 2 * escape + sizeof(" HTTP/1.0" CRLF) - 1
1277           + sizeof("Host: ") - 1 + ctx->host.len + sizeof(CRLF) - 1
1278           + sizeof(CRLF) - 1;
1279 
1280     b = ngx_create_temp_buf(ctx->pool, len);
1281     if (b == NULL) {
1282         goto failed;
1283     }
1284 
1285     p = b->last;
1286 
1287     p = ngx_cpymem(p, "GET ", sizeof("GET ") - 1);
1288     p = ngx_cpymem(p, ctx->uri.data, ctx->uri.len);
1289 
1290     if (ctx->uri.data[ctx->uri.len - 1] != '/') {
1291         *p++ = '/';
1292     }
1293 
1294     if (escape == 0) {
1295         p = ngx_cpymem(p, base64.data, base64.len);
1296 
1297     } else {
1298         p = (u_char *) ngx_escape_uri(p, base64.data, base64.len,
1299                                       NGX_ESCAPE_URI_COMPONENT);
1300     }
1301 
1302     p = ngx_cpymem(p, " HTTP/1.0" CRLF, sizeof(" HTTP/1.0" CRLF) - 1);
1303     p = ngx_cpymem(p, "Host: ", sizeof("Host: ") - 1);
1304     p = ngx_cpymem(p, ctx->host.data, ctx->host.len);
1305     *p++ = CR; *p++ = LF;
1306 
1307     /* add "\r\n" at the header end */
1308     *p++ = CR; *p++ = LF;
1309 
1310     b->last = p;
1311     ctx->request = b;
1312 
1313     OCSP_REQUEST_free(ocsp);
1314 
1315     return NGX_OK;
1316 
1317 failed:
1318 
1319     OCSP_REQUEST_free(ocsp);
1320 
1321     return NGX_ERROR;
1322 }
1323 
1324 
1325 static ngx_int_t
1326 ngx_ssl_ocsp_process_status_line(ngx_ssl_ocsp_ctx_t *ctx)
1327 {
1328     ngx_int_t  rc;
1329 
1330     rc = ngx_ssl_ocsp_parse_status_line(ctx);
1331 
1332     if (rc == NGX_OK) {
1333         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1334                        "ssl ocsp status %ui \"%*s\"",
1335                        ctx->code,
1336                        ctx->header_end - ctx->header_start,
1337                        ctx->header_start);
1338 
1339         ctx->process = ngx_ssl_ocsp_process_headers;
1340         return ctx->process(ctx);
1341     }
1342 
1343     if (rc == NGX_AGAIN) {
1344         return NGX_AGAIN;
1345     }
1346 
1347     /* rc == NGX_ERROR */
1348 
1349     ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1350                   "OCSP responder sent invalid response");
1351 
1352     return NGX_ERROR;
1353 }
1354 
1355 
1356 static ngx_int_t
1357 ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t *ctx)
1358 {
1359     u_char      ch;
1360     u_char     *p;
1361     ngx_buf_t  *b;
1362     enum {
1363         sw_start = 0,
1364         sw_H,
1365         sw_HT,
1366         sw_HTT,
1367         sw_HTTP,
1368         sw_first_major_digit,
1369         sw_major_digit,
1370         sw_first_minor_digit,
1371         sw_minor_digit,
1372         sw_status,
1373         sw_space_after_status,
1374         sw_status_text,
1375         sw_almost_done
1376     } state;
1377 
1378     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1379                    "ssl ocsp process status line");
1380 
1381     state = ctx->state;
1382     b = ctx->response;
1383 
1384     for (p = b->pos; p < b->last; p++) {
1385         ch = *p;
1386 
1387         switch (state) {
1388 
1389         /* "HTTP/" */
1390         case sw_start:
1391             switch (ch) {
1392             case 'H':
1393                 state = sw_H;
1394                 break;
1395             default:
1396                 return NGX_ERROR;
1397             }
1398             break;
1399 
1400         case sw_H:
1401             switch (ch) {
1402             case 'T':
1403                 state = sw_HT;
1404                 break;
1405             default:
1406                 return NGX_ERROR;
1407             }
1408             break;
1409 
1410         case sw_HT:
1411             switch (ch) {
1412             case 'T':
1413                 state = sw_HTT;
1414                 break;
1415             default:
1416                 return NGX_ERROR;
1417             }
1418             break;
1419 
1420         case sw_HTT:
1421             switch (ch) {
1422             case 'P':
1423                 state = sw_HTTP;
1424                 break;
1425             default:
1426                 return NGX_ERROR;
1427             }
1428             break;
1429 
1430         case sw_HTTP:
1431             switch (ch) {
1432             case '/':
1433                 state = sw_first_major_digit;
1434                 break;
1435             default:
1436                 return NGX_ERROR;
1437             }
1438             break;
1439 
1440         /* the first digit of major HTTP version */
1441         case sw_first_major_digit:
1442             if (ch < '1' || ch > '9') {
1443                 return NGX_ERROR;
1444             }
1445 
1446             state = sw_major_digit;
1447             break;
1448 
1449         /* the major HTTP version or dot */
1450         case sw_major_digit:
1451             if (ch == '.') {
1452                 state = sw_first_minor_digit;
1453                 break;
1454             }
1455 
1456             if (ch < '0' || ch > '9') {
1457                 return NGX_ERROR;
1458             }
1459 
1460             break;
1461 
1462         /* the first digit of minor HTTP version */
1463         case sw_first_minor_digit:
1464             if (ch < '0' || ch > '9') {
1465                 return NGX_ERROR;
1466             }
1467 
1468             state = sw_minor_digit;
1469             break;
1470 
1471         /* the minor HTTP version or the end of the request line */
1472         case sw_minor_digit:
1473             if (ch == ' ') {
1474                 state = sw_status;
1475                 break;
1476             }
1477 
1478             if (ch < '0' || ch > '9') {
1479                 return NGX_ERROR;
1480             }
1481 
1482             break;
1483 
1484         /* HTTP status code */
1485         case sw_status:
1486             if (ch == ' ') {
1487                 break;
1488             }
1489 
1490             if (ch < '0' || ch > '9') {
1491                 return NGX_ERROR;
1492             }
1493 
1494             ctx->code = ctx->code * 10 + (ch - '0');
1495 
1496             if (++ctx->count == 3) {
1497                 state = sw_space_after_status;
1498                 ctx->header_start = p - 2;
1499             }
1500 
1501             break;
1502 
1503         /* space or end of line */
1504         case sw_space_after_status:
1505             switch (ch) {
1506             case ' ':
1507                 state = sw_status_text;
1508                 break;
1509             case '.':                    /* IIS may send 403.1, 403.2, etc */
1510                 state = sw_status_text;
1511                 break;
1512             case CR:
1513                 state = sw_almost_done;
1514                 break;
1515             case LF:
1516                 ctx->header_end = p;
1517                 goto done;
1518             default:
1519                 return NGX_ERROR;
1520             }
1521             break;
1522 
1523         /* any text until end of line */
1524         case sw_status_text:
1525             switch (ch) {
1526             case CR:
1527                 state = sw_almost_done;
1528                 break;
1529             case LF:
1530                 ctx->header_end = p;
1531                 goto done;
1532             }
1533             break;
1534 
1535         /* end of status line */
1536         case sw_almost_done:
1537             switch (ch) {
1538             case LF:
1539                 ctx->header_end = p - 1;
1540                 goto done;
1541             default:
1542                 return NGX_ERROR;
1543             }
1544         }
1545     }
1546 
1547     b->pos = p;
1548     ctx->state = state;
1549 
1550     return NGX_AGAIN;
1551 
1552 done:
1553 
1554     b->pos = p + 1;
1555     ctx->state = sw_start;
1556 
1557     return NGX_OK;
1558 }
1559 
1560 
1561 static ngx_int_t
1562 ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx)
1563 {
1564     size_t     len;
1565     ngx_int_t  rc;
1566 
1567     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1568                    "ssl ocsp process headers");
1569 
1570     for ( ;; ) {
1571         rc = ngx_ssl_ocsp_parse_header_line(ctx);
1572 
1573         if (rc == NGX_OK) {
1574 
1575             ngx_log_debug4(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1576                            "ssl ocsp header \"%*s: %*s\"",
1577                            ctx->header_name_end - ctx->header_name_start,
1578                            ctx->header_name_start,
1579                            ctx->header_end - ctx->header_start,
1580                            ctx->header_start);
1581 
1582             len = ctx->header_name_end - ctx->header_name_start;
1583 
1584             if (len == sizeof("Content-Type") - 1
1585                 && ngx_strncasecmp(ctx->header_name_start,
1586                                    (u_char *) "Content-Type",
1587                                    sizeof("Content-Type") - 1)
1588                    == 0)
1589             {
1590                 len = ctx->header_end - ctx->header_start;
1591 
1592                 if (len != sizeof("application/ocsp-response") - 1
1593                     || ngx_strncasecmp(ctx->header_start,
1594                                        (u_char *) "application/ocsp-response",
1595                                        sizeof("application/ocsp-response") - 1)
1596                        != 0)
1597                 {
1598                     ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1599                                   "OCSP responder sent invalid "
1600                                   "\"Content-Type\" header: \"%*s\"",
1601                                   ctx->header_end - ctx->header_start,
1602                                   ctx->header_start);
1603                     return NGX_ERROR;
1604                 }
1605 
1606                 continue;
1607             }
1608 
1609             /* TODO: honor Content-Length */
1610 
1611             continue;
1612         }
1613 
1614         if (rc == NGX_DONE) {
1615             break;
1616         }
1617 
1618         if (rc == NGX_AGAIN) {
1619             return NGX_AGAIN;
1620         }
1621 
1622         /* rc == NGX_ERROR */
1623 
1624         ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1625                       "OCSP responder sent invalid response");
1626 
1627         return NGX_ERROR;
1628     }
1629 
1630     ctx->process = ngx_ssl_ocsp_process_body;
1631     return ctx->process(ctx);
1632 }
1633 
1634 
1635 static ngx_int_t
1636 ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx)
1637 {
1638     u_char  c, ch, *p;
1639     enum {
1640         sw_start = 0,
1641         sw_name,
1642         sw_space_before_value,
1643         sw_value,
1644         sw_space_after_value,
1645         sw_almost_done,
1646         sw_header_almost_done
1647     } state;
1648 
1649     state = ctx->state;
1650 
1651     for (p = ctx->response->pos; p < ctx->response->last; p++) {
1652         ch = *p;
1653 
1654 #if 0
1655         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1656                        "s:%d in:'%02Xd:%c'", state, ch, ch);
1657 #endif
1658 
1659         switch (state) {
1660 
1661         /* first char */
1662         case sw_start:
1663 
1664             switch (ch) {
1665             case CR:
1666                 ctx->header_end = p;
1667                 state = sw_header_almost_done;
1668                 break;
1669             case LF:
1670                 ctx->header_end = p;
1671                 goto header_done;
1672             default:
1673                 state = sw_name;
1674                 ctx->header_name_start = p;
1675 
1676                 c = (u_char) (ch | 0x20);
1677                 if (c >= 'a' && c <= 'z') {
1678                     break;
1679                 }
1680 
1681                 if (ch >= '0' && ch <= '9') {
1682                     break;
1683                 }
1684 
1685                 return NGX_ERROR;
1686             }
1687             break;
1688 
1689         /* header name */
1690         case sw_name:
1691             c = (u_char) (ch | 0x20);
1692             if (c >= 'a' && c <= 'z') {
1693                 break;
1694             }
1695 
1696             if (ch == ':') {
1697                 ctx->header_name_end = p;
1698                 state = sw_space_before_value;
1699                 break;
1700             }
1701 
1702             if (ch == '-') {
1703                 break;
1704             }
1705 
1706             if (ch >= '0' && ch <= '9') {
1707                 break;
1708             }
1709 
1710             if (ch == CR) {
1711                 ctx->header_name_end = p;
1712                 ctx->header_start = p;
1713                 ctx->header_end = p;
1714                 state = sw_almost_done;
1715                 break;
1716             }
1717 
1718             if (ch == LF) {
1719                 ctx->header_name_end = p;
1720                 ctx->header_start = p;
1721                 ctx->header_end = p;
1722                 goto done;
1723             }
1724 
1725             return NGX_ERROR;
1726 
1727         /* space* before header value */
1728         case sw_space_before_value:
1729             switch (ch) {
1730             case ' ':
1731                 break;
1732             case CR:
1733                 ctx->header_start = p;
1734                 ctx->header_end = p;
1735                 state = sw_almost_done;
1736                 break;
1737             case LF:
1738                 ctx->header_start = p;
1739                 ctx->header_end = p;
1740                 goto done;
1741             default:
1742                 ctx->header_start = p;
1743                 state = sw_value;
1744                 break;
1745             }
1746             break;
1747 
1748         /* header value */
1749         case sw_value:
1750             switch (ch) {
1751             case ' ':
1752                 ctx->header_end = p;
1753                 state = sw_space_after_value;
1754                 break;
1755             case CR:
1756                 ctx->header_end = p;
1757                 state = sw_almost_done;
1758                 break;
1759             case LF:
1760                 ctx->header_end = p;
1761                 goto done;
1762             }
1763             break;
1764 
1765         /* space* before end of header line */
1766         case sw_space_after_value:
1767             switch (ch) {
1768             case ' ':
1769                 break;
1770             case CR:
1771                 state = sw_almost_done;
1772                 break;
1773             case LF:
1774                 goto done;
1775             default:
1776                 state = sw_value;
1777                 break;
1778             }
1779             break;
1780 
1781         /* end of header line */
1782         case sw_almost_done:
1783             switch (ch) {
1784             case LF:
1785                 goto done;
1786             default:
1787                 return NGX_ERROR;
1788             }
1789 
1790         /* end of header */
1791         case sw_header_almost_done:
1792             switch (ch) {
1793             case LF:
1794                 goto header_done;
1795             default:
1796                 return NGX_ERROR;
1797             }
1798         }
1799     }
1800 
1801     ctx->response->pos = p;
1802     ctx->state = state;
1803 
1804     return NGX_AGAIN;
1805 
1806 done:
1807 
1808     ctx->response->pos = p + 1;
1809     ctx->state = sw_start;
1810 
1811     return NGX_OK;
1812 
1813 header_done:
1814 
1815     ctx->response->pos = p + 1;
1816     ctx->state = sw_start;
1817 
1818     return NGX_DONE;
1819 }
1820 
1821 
1822 static ngx_int_t
1823 ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx)
1824 {
1825     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1826                    "ssl ocsp process body");
1827 
1828     if (ctx->done) {
1829         ctx->handler(ctx);
1830         return NGX_DONE;
1831     }
1832 
1833     return NGX_AGAIN;
1834 }
1835 
1836 
1837 static u_char *
1838 ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len)
1839 {
1840     u_char              *p;
1841     ngx_ssl_ocsp_ctx_t  *ctx;
1842 
1843     p = buf;
1844 
1845     if (log->action) {
1846         p = ngx_snprintf(buf, len, " while %s", log->action);
1847         len -= p - buf;
1848         buf = p;
1849     }
1850 
1851     ctx = log->data;
1852 
1853     if (ctx) {
1854         p = ngx_snprintf(buf, len, ", responder: %V", &ctx->host);
1855         len -= p - buf;
1856         buf = p;
1857     }
1858 
1859     if (ctx && ctx->peer.name) {
1860         p = ngx_snprintf(buf, len, ", peer: %V", ctx->peer.name);
1861         len -= p - buf;
1862         buf = p;
1863     }
1864 
1865     if (ctx && ctx->name) {
1866         p = ngx_snprintf(buf, len, ", certificate: \"%s\"", ctx->name);
1867         len -= p - buf;
1868         buf = p;
1869     }
1870 
1871     return p;
1872 }
1873 
1874 
1875 #else
1876 
1877 
1878 ngx_int_t
1879 ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file,
1880     ngx_str_t *responder, ngx_uint_t verify)
1881 {
1882     ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
1883                   "\"ssl_stapling\" ignored, not supported");
1884 
1885     return NGX_OK;
1886 }
1887 
1888 
1889 ngx_int_t
1890 ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
1891     ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)
1892 {
1893     return NGX_OK;
1894 }
1895 
1896 
1897 #endif