Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.19.2 ]​[ nginx-1.18.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_uint_t                   naddrs;
0026     ngx_str_t                    host;
0027     ngx_str_t                    uri;
0028     in_port_t                    port;
0029 
0030     SSL_CTX                     *ssl_ctx;
0031 
0032     X509                        *cert;
0033     X509                        *issuer;
0034     STACK_OF(X509)              *chain;
0035 
0036     u_char                      *name;
0037 
0038     time_t                       valid;
0039     time_t                       refresh;
0040 
0041     unsigned                     verify:1;
0042     unsigned                     loading:1;
0043 } ngx_ssl_stapling_t;
0044 
0045 
0046 typedef struct {
0047     ngx_addr_t                  *addrs;
0048     ngx_uint_t                   naddrs;
0049 
0050     ngx_str_t                    host;
0051     ngx_str_t                    uri;
0052     in_port_t                    port;
0053     ngx_uint_t                   depth;
0054 
0055     ngx_shm_zone_t              *shm_zone;
0056 
0057     ngx_resolver_t              *resolver;
0058     ngx_msec_t                   resolver_timeout;
0059 } ngx_ssl_ocsp_conf_t;
0060 
0061 
0062 typedef struct {
0063     ngx_rbtree_t                 rbtree;
0064     ngx_rbtree_node_t            sentinel;
0065     ngx_queue_t                  expire_queue;
0066 } ngx_ssl_ocsp_cache_t;
0067 
0068 
0069 typedef struct {
0070     ngx_str_node_t               node;
0071     ngx_queue_t                  queue;
0072     int                          status;
0073     time_t                       valid;
0074 } ngx_ssl_ocsp_cache_node_t;
0075 
0076 
0077 typedef struct ngx_ssl_ocsp_ctx_s  ngx_ssl_ocsp_ctx_t;
0078 
0079 
0080 struct ngx_ssl_ocsp_s {
0081     STACK_OF(X509)              *certs;
0082     ngx_uint_t                   ncert;
0083 
0084     int                          cert_status;
0085     ngx_int_t                    status;
0086 
0087     ngx_ssl_ocsp_conf_t         *conf;
0088     ngx_ssl_ocsp_ctx_t          *ctx;
0089 };
0090 
0091 
0092 struct ngx_ssl_ocsp_ctx_s {
0093     SSL_CTX                     *ssl_ctx;
0094 
0095     X509                        *cert;
0096     X509                        *issuer;
0097     STACK_OF(X509)              *chain;
0098 
0099     int                          status;
0100     time_t                       valid;
0101 
0102     u_char                      *name;
0103 
0104     ngx_uint_t                   naddrs;
0105     ngx_uint_t                   naddr;
0106 
0107     ngx_addr_t                  *addrs;
0108     ngx_str_t                    host;
0109     ngx_str_t                    uri;
0110     in_port_t                    port;
0111 
0112     ngx_resolver_t              *resolver;
0113     ngx_msec_t                   resolver_timeout;
0114 
0115     ngx_msec_t                   timeout;
0116 
0117     void                       (*handler)(ngx_ssl_ocsp_ctx_t *ctx);
0118     void                        *data;
0119 
0120     ngx_str_t                    key;
0121     ngx_buf_t                   *request;
0122     ngx_buf_t                   *response;
0123     ngx_peer_connection_t        peer;
0124 
0125     ngx_shm_zone_t              *shm_zone;
0126 
0127     ngx_int_t                  (*process)(ngx_ssl_ocsp_ctx_t *ctx);
0128 
0129     ngx_uint_t                   state;
0130 
0131     ngx_uint_t                   code;
0132     ngx_uint_t                   count;
0133     ngx_uint_t                   flags;
0134     ngx_uint_t                   done;
0135 
0136     u_char                      *header_name_start;
0137     u_char                      *header_name_end;
0138     u_char                      *header_start;
0139     u_char                      *header_end;
0140 
0141     ngx_pool_t                  *pool;
0142     ngx_log_t                   *log;
0143 };
0144 
0145 
0146 static ngx_int_t ngx_ssl_stapling_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl,
0147     X509 *cert, ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify);
0148 static ngx_int_t ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl,
0149     ngx_ssl_stapling_t *staple, ngx_str_t *file);
0150 static ngx_int_t ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl,
0151     ngx_ssl_stapling_t *staple);
0152 static ngx_int_t ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl,
0153     ngx_ssl_stapling_t *staple, ngx_str_t *responder);
0154 
0155 static int ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn,
0156     void *data);
0157 static void ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple);
0158 static void ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx);
0159 
0160 static time_t ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time);
0161 
0162 static void ngx_ssl_stapling_cleanup(void *data);
0163 
0164 static void ngx_ssl_ocsp_validate_next(ngx_connection_t *c);
0165 static void ngx_ssl_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx);
0166 static ngx_int_t ngx_ssl_ocsp_responder(ngx_connection_t *c,
0167     ngx_ssl_ocsp_ctx_t *ctx);
0168 
0169 static ngx_ssl_ocsp_ctx_t *ngx_ssl_ocsp_start(ngx_log_t *log);
0170 static void ngx_ssl_ocsp_done(ngx_ssl_ocsp_ctx_t *ctx);
0171 static void ngx_ssl_ocsp_next(ngx_ssl_ocsp_ctx_t *ctx);
0172 static void ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx);
0173 static void ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve);
0174 static void ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx);
0175 static void ngx_ssl_ocsp_write_handler(ngx_event_t *wev);
0176 static void ngx_ssl_ocsp_read_handler(ngx_event_t *rev);
0177 static void ngx_ssl_ocsp_dummy_handler(ngx_event_t *ev);
0178 
0179 static ngx_int_t ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx);
0180 static ngx_int_t ngx_ssl_ocsp_process_status_line(ngx_ssl_ocsp_ctx_t *ctx);
0181 static ngx_int_t ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t *ctx);
0182 static ngx_int_t ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx);
0183 static ngx_int_t ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx);
0184 static ngx_int_t ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx);
0185 static ngx_int_t ngx_ssl_ocsp_verify(ngx_ssl_ocsp_ctx_t *ctx);
0186 
0187 static ngx_int_t ngx_ssl_ocsp_cache_lookup(ngx_ssl_ocsp_ctx_t *ctx);
0188 static ngx_int_t ngx_ssl_ocsp_cache_store(ngx_ssl_ocsp_ctx_t *ctx);
0189 static ngx_int_t ngx_ssl_ocsp_create_key(ngx_ssl_ocsp_ctx_t *ctx);
0190 
0191 static u_char *ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len);
0192 
0193 
0194 ngx_int_t
0195 ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file,
0196     ngx_str_t *responder, ngx_uint_t verify)
0197 {
0198     X509  *cert;
0199 
0200     for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
0201          cert;
0202          cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index))
0203     {
0204         if (ngx_ssl_stapling_certificate(cf, ssl, cert, file, responder, verify)
0205             != NGX_OK)
0206         {
0207             return NGX_ERROR;
0208         }
0209     }
0210 
0211     SSL_CTX_set_tlsext_status_cb(ssl->ctx, ngx_ssl_certificate_status_callback);
0212 
0213     return NGX_OK;
0214 }
0215 
0216 
0217 static ngx_int_t
0218 ngx_ssl_stapling_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, X509 *cert,
0219     ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify)
0220 {
0221     ngx_int_t            rc;
0222     ngx_pool_cleanup_t  *cln;
0223     ngx_ssl_stapling_t  *staple;
0224 
0225     staple = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_stapling_t));
0226     if (staple == NULL) {
0227         return NGX_ERROR;
0228     }
0229 
0230     cln = ngx_pool_cleanup_add(cf->pool, 0);
0231     if (cln == NULL) {
0232         return NGX_ERROR;
0233     }
0234 
0235     cln->handler = ngx_ssl_stapling_cleanup;
0236     cln->data = staple;
0237 
0238     if (X509_set_ex_data(cert, ngx_ssl_stapling_index, staple) == 0) {
0239         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed");
0240         return NGX_ERROR;
0241     }
0242 
0243 #ifdef SSL_CTRL_SELECT_CURRENT_CERT
0244     /* OpenSSL 1.0.2+ */
0245     SSL_CTX_select_current_cert(ssl->ctx, cert);
0246 #endif
0247 
0248 #ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
0249     /* OpenSSL 1.0.1+ */
0250     SSL_CTX_get_extra_chain_certs(ssl->ctx, &staple->chain);
0251 #else
0252     staple->chain = ssl->ctx->extra_certs;
0253 #endif
0254 
0255     staple->ssl_ctx = ssl->ctx;
0256     staple->timeout = 60000;
0257     staple->verify = verify;
0258     staple->cert = cert;
0259     staple->name = X509_get_ex_data(staple->cert,
0260                                     ngx_ssl_certificate_name_index);
0261 
0262     if (file->len) {
0263         /* use OCSP response from the file */
0264 
0265         if (ngx_ssl_stapling_file(cf, ssl, staple, file) != NGX_OK) {
0266             return NGX_ERROR;
0267         }
0268 
0269         return NGX_OK;
0270     }
0271 
0272     rc = ngx_ssl_stapling_issuer(cf, ssl, staple);
0273 
0274     if (rc == NGX_DECLINED) {
0275         return NGX_OK;
0276     }
0277 
0278     if (rc != NGX_OK) {
0279         return NGX_ERROR;
0280     }
0281 
0282     rc = ngx_ssl_stapling_responder(cf, ssl, staple, responder);
0283 
0284     if (rc == NGX_DECLINED) {
0285         return NGX_OK;
0286     }
0287 
0288     if (rc != NGX_OK) {
0289         return NGX_ERROR;
0290     }
0291 
0292     return NGX_OK;
0293 }
0294 
0295 
0296 static ngx_int_t
0297 ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl,
0298     ngx_ssl_stapling_t *staple, ngx_str_t *file)
0299 {
0300     BIO            *bio;
0301     int             len;
0302     u_char         *p, *buf;
0303     OCSP_RESPONSE  *response;
0304 
0305     if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) {
0306         return NGX_ERROR;
0307     }
0308 
0309     bio = BIO_new_file((char *) file->data, "rb");
0310     if (bio == NULL) {
0311         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0312                       "BIO_new_file(\"%s\") failed", file->data);
0313         return NGX_ERROR;
0314     }
0315 
0316     response = d2i_OCSP_RESPONSE_bio(bio, NULL);
0317     if (response == NULL) {
0318         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0319                       "d2i_OCSP_RESPONSE_bio(\"%s\") failed", file->data);
0320         BIO_free(bio);
0321         return NGX_ERROR;
0322     }
0323 
0324     len = i2d_OCSP_RESPONSE(response, NULL);
0325     if (len <= 0) {
0326         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0327                       "i2d_OCSP_RESPONSE(\"%s\") failed", file->data);
0328         goto failed;
0329     }
0330 
0331     buf = ngx_alloc(len, ssl->log);
0332     if (buf == NULL) {
0333         goto failed;
0334     }
0335 
0336     p = buf;
0337     len = i2d_OCSP_RESPONSE(response, &p);
0338     if (len <= 0) {
0339         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0340                       "i2d_OCSP_RESPONSE(\"%s\") failed", file->data);
0341         ngx_free(buf);
0342         goto failed;
0343     }
0344 
0345     OCSP_RESPONSE_free(response);
0346     BIO_free(bio);
0347 
0348     staple->staple.data = buf;
0349     staple->staple.len = len;
0350     staple->valid = NGX_MAX_TIME_T_VALUE;
0351 
0352     return NGX_OK;
0353 
0354 failed:
0355 
0356     OCSP_RESPONSE_free(response);
0357     BIO_free(bio);
0358 
0359     return NGX_ERROR;
0360 }
0361 
0362 
0363 static ngx_int_t
0364 ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl,
0365     ngx_ssl_stapling_t *staple)
0366 {
0367     int              i, n, rc;
0368     X509            *cert, *issuer;
0369     X509_STORE      *store;
0370     X509_STORE_CTX  *store_ctx;
0371 
0372     cert = staple->cert;
0373 
0374     n = sk_X509_num(staple->chain);
0375 
0376     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
0377                    "SSL get issuer: %d extra certs", n);
0378 
0379     for (i = 0; i < n; i++) {
0380         issuer = sk_X509_value(staple->chain, i);
0381         if (X509_check_issued(issuer, cert) == X509_V_OK) {
0382 #if OPENSSL_VERSION_NUMBER >= 0x10100001L
0383             X509_up_ref(issuer);
0384 #else
0385             CRYPTO_add(&issuer->references, 1, CRYPTO_LOCK_X509);
0386 #endif
0387 
0388             ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
0389                            "SSL get issuer: found %p in extra certs", issuer);
0390 
0391             staple->issuer = issuer;
0392 
0393             return NGX_OK;
0394         }
0395     }
0396 
0397     store = SSL_CTX_get_cert_store(ssl->ctx);
0398     if (store == NULL) {
0399         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0400                       "SSL_CTX_get_cert_store() failed");
0401         return NGX_ERROR;
0402     }
0403 
0404     store_ctx = X509_STORE_CTX_new();
0405     if (store_ctx == NULL) {
0406         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0407                       "X509_STORE_CTX_new() failed");
0408         return NGX_ERROR;
0409     }
0410 
0411     if (X509_STORE_CTX_init(store_ctx, store, NULL, NULL) == 0) {
0412         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0413                       "X509_STORE_CTX_init() failed");
0414         X509_STORE_CTX_free(store_ctx);
0415         return NGX_ERROR;
0416     }
0417 
0418     rc = X509_STORE_CTX_get1_issuer(&issuer, store_ctx, cert);
0419 
0420     if (rc == -1) {
0421         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0422                       "X509_STORE_CTX_get1_issuer() failed");
0423         X509_STORE_CTX_free(store_ctx);
0424         return NGX_ERROR;
0425     }
0426 
0427     if (rc == 0) {
0428         ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
0429                       "\"ssl_stapling\" ignored, "
0430                       "issuer certificate not found for certificate \"%s\"",
0431                       staple->name);
0432         X509_STORE_CTX_free(store_ctx);
0433         return NGX_DECLINED;
0434     }
0435 
0436     X509_STORE_CTX_free(store_ctx);
0437 
0438     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
0439                    "SSL get issuer: found %p in cert store", issuer);
0440 
0441     staple->issuer = issuer;
0442 
0443     return NGX_OK;
0444 }
0445 
0446 
0447 static ngx_int_t
0448 ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl,
0449     ngx_ssl_stapling_t *staple, ngx_str_t *responder)
0450 {
0451     char                      *s;
0452     ngx_str_t                  rsp;
0453     ngx_url_t                  u;
0454     STACK_OF(OPENSSL_STRING)  *aia;
0455 
0456     if (responder->len == 0) {
0457 
0458         /* extract OCSP responder URL from certificate */
0459 
0460         aia = X509_get1_ocsp(staple->cert);
0461         if (aia == NULL) {
0462             ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
0463                           "\"ssl_stapling\" ignored, "
0464                           "no OCSP responder URL in the certificate \"%s\"",
0465                           staple->name);
0466             return NGX_DECLINED;
0467         }
0468 
0469 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
0470         s = sk_OPENSSL_STRING_value(aia, 0);
0471 #else
0472         s = sk_value(aia, 0);
0473 #endif
0474         if (s == NULL) {
0475             ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
0476                           "\"ssl_stapling\" ignored, "
0477                           "no OCSP responder URL in the certificate \"%s\"",
0478                           staple->name);
0479             X509_email_free(aia);
0480             return NGX_DECLINED;
0481         }
0482 
0483         responder = &rsp;
0484 
0485         responder->len = ngx_strlen(s);
0486         responder->data = ngx_palloc(cf->pool, responder->len);
0487         if (responder->data == NULL) {
0488             X509_email_free(aia);
0489             return NGX_ERROR;
0490         }
0491 
0492         ngx_memcpy(responder->data, s, responder->len);
0493         X509_email_free(aia);
0494     }
0495 
0496     ngx_memzero(&u, sizeof(ngx_url_t));
0497 
0498     u.url = *responder;
0499     u.default_port = 80;
0500     u.uri_part = 1;
0501 
0502     if (u.url.len > 7
0503         && ngx_strncasecmp(u.url.data, (u_char *) "http://", 7) == 0)
0504     {
0505         u.url.len -= 7;
0506         u.url.data += 7;
0507 
0508     } else {
0509         ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
0510                       "\"ssl_stapling\" ignored, "
0511                       "invalid URL prefix in OCSP responder \"%V\" "
0512                       "in the certificate \"%s\"",
0513                       &u.url, staple->name);
0514         return NGX_DECLINED;
0515     }
0516 
0517     if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
0518         if (u.err) {
0519             ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
0520                           "\"ssl_stapling\" ignored, "
0521                           "%s in OCSP responder \"%V\" "
0522                           "in the certificate \"%s\"",
0523                           u.err, &u.url, staple->name);
0524             return NGX_DECLINED;
0525         }
0526 
0527         return NGX_ERROR;
0528     }
0529 
0530     staple->addrs = u.addrs;
0531     staple->naddrs = u.naddrs;
0532     staple->host = u.host;
0533     staple->uri = u.uri;
0534     staple->port = u.port;
0535 
0536     if (staple->uri.len == 0) {
0537         ngx_str_set(&staple->uri, "/");
0538     }
0539 
0540     return NGX_OK;
0541 }
0542 
0543 
0544 ngx_int_t
0545 ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
0546     ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)
0547 {
0548     X509                *cert;
0549     ngx_ssl_stapling_t  *staple;
0550 
0551     for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
0552          cert;
0553          cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index))
0554     {
0555         staple = X509_get_ex_data(cert, ngx_ssl_stapling_index);
0556         staple->resolver = resolver;
0557         staple->resolver_timeout = resolver_timeout;
0558     }
0559 
0560     return NGX_OK;
0561 }
0562 
0563 
0564 static int
0565 ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn, void *data)
0566 {
0567     int                  rc;
0568     X509                *cert;
0569     u_char              *p;
0570     ngx_connection_t    *c;
0571     ngx_ssl_stapling_t  *staple;
0572 
0573     c = ngx_ssl_get_connection(ssl_conn);
0574 
0575     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
0576                    "SSL certificate status callback");
0577 
0578     rc = SSL_TLSEXT_ERR_NOACK;
0579 
0580     cert = SSL_get_certificate(ssl_conn);
0581 
0582     if (cert == NULL) {
0583         return rc;
0584     }
0585 
0586     staple = X509_get_ex_data(cert, ngx_ssl_stapling_index);
0587 
0588     if (staple == NULL) {
0589         return rc;
0590     }
0591 
0592     if (staple->staple.len
0593         && staple->valid >= ngx_time())
0594     {
0595         /* we have to copy ocsp response as OpenSSL will free it by itself */
0596 
0597         p = OPENSSL_malloc(staple->staple.len);
0598         if (p == NULL) {
0599             ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "OPENSSL_malloc() failed");
0600             return SSL_TLSEXT_ERR_NOACK;
0601         }
0602 
0603         ngx_memcpy(p, staple->staple.data, staple->staple.len);
0604 
0605         SSL_set_tlsext_status_ocsp_resp(ssl_conn, p, staple->staple.len);
0606 
0607         rc = SSL_TLSEXT_ERR_OK;
0608     }
0609 
0610     ngx_ssl_stapling_update(staple);
0611 
0612     return rc;
0613 }
0614 
0615 
0616 static void
0617 ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple)
0618 {
0619     ngx_ssl_ocsp_ctx_t  *ctx;
0620 
0621     if (staple->host.len == 0
0622         || staple->loading || staple->refresh >= ngx_time())
0623     {
0624         return;
0625     }
0626 
0627     staple->loading = 1;
0628 
0629     ctx = ngx_ssl_ocsp_start(ngx_cycle->log);
0630     if (ctx == NULL) {
0631         return;
0632     }
0633 
0634     ctx->ssl_ctx = staple->ssl_ctx;
0635     ctx->cert = staple->cert;
0636     ctx->issuer = staple->issuer;
0637     ctx->chain = staple->chain;
0638     ctx->name = staple->name;
0639     ctx->flags = (staple->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY);
0640 
0641     ctx->addrs = staple->addrs;
0642     ctx->naddrs = staple->naddrs;
0643     ctx->host = staple->host;
0644     ctx->uri = staple->uri;
0645     ctx->port = staple->port;
0646     ctx->timeout = staple->timeout;
0647 
0648     ctx->resolver = staple->resolver;
0649     ctx->resolver_timeout = staple->resolver_timeout;
0650 
0651     ctx->handler = ngx_ssl_stapling_ocsp_handler;
0652     ctx->data = staple;
0653 
0654     ngx_ssl_ocsp_request(ctx);
0655 
0656     return;
0657 }
0658 
0659 
0660 static void
0661 ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
0662 {
0663     time_t               now;
0664     ngx_str_t            response;
0665     ngx_ssl_stapling_t  *staple;
0666 
0667     staple = ctx->data;
0668     now = ngx_time();
0669 
0670     if (ngx_ssl_ocsp_verify(ctx) != NGX_OK) {
0671         goto error;
0672     }
0673 
0674     if (ctx->status != V_OCSP_CERTSTATUS_GOOD) {
0675         ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
0676                       "certificate status \"%s\" in the OCSP response",
0677                       OCSP_cert_status_str(ctx->status));
0678         goto error;
0679     }
0680 
0681     /* copy the response to memory not in ctx->pool */
0682 
0683     response.len = ctx->response->last - ctx->response->pos;
0684     response.data = ngx_alloc(response.len, ctx->log);
0685 
0686     if (response.data == NULL) {
0687         goto error;
0688     }
0689 
0690     ngx_memcpy(response.data, ctx->response->pos, response.len);
0691 
0692     if (staple->staple.data) {
0693         ngx_free(staple->staple.data);
0694     }
0695 
0696     staple->staple = response;
0697     staple->valid = ctx->valid;
0698 
0699     /*
0700      * refresh before the response expires,
0701      * but not earlier than in 5 minutes, and at least in an hour
0702      */
0703 
0704     staple->loading = 0;
0705     staple->refresh = ngx_max(ngx_min(ctx->valid - 300, now + 3600), now + 300);
0706 
0707     ngx_ssl_ocsp_done(ctx);
0708     return;
0709 
0710 error:
0711 
0712     staple->loading = 0;
0713     staple->refresh = now + 300;
0714 
0715     ngx_ssl_ocsp_done(ctx);
0716 }
0717 
0718 
0719 static time_t
0720 ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time)
0721 {
0722     BIO     *bio;
0723     char    *value;
0724     size_t   len;
0725     time_t   time;
0726 
0727     /*
0728      * OpenSSL doesn't provide a way to convert ASN1_GENERALIZEDTIME
0729      * into time_t.  To do this, we use ASN1_GENERALIZEDTIME_print(),
0730      * which uses the "MMM DD HH:MM:SS YYYY [GMT]" format (e.g.,
0731      * "Feb  3 00:55:52 2015 GMT"), and parse the result.
0732      */
0733 
0734     bio = BIO_new(BIO_s_mem());
0735     if (bio == NULL) {
0736         return NGX_ERROR;
0737     }
0738 
0739     /* fake weekday prepended to match C asctime() format */
0740 
0741     BIO_write(bio, "Tue ", sizeof("Tue ") - 1);
0742     ASN1_GENERALIZEDTIME_print(bio, asn1time);
0743     len = BIO_get_mem_data(bio, &value);
0744 
0745     time = ngx_parse_http_time((u_char *) value, len);
0746 
0747     BIO_free(bio);
0748 
0749     return time;
0750 }
0751 
0752 
0753 static void
0754 ngx_ssl_stapling_cleanup(void *data)
0755 {
0756     ngx_ssl_stapling_t  *staple = data;
0757 
0758     if (staple->issuer) {
0759         X509_free(staple->issuer);
0760     }
0761 
0762     if (staple->staple.data) {
0763         ngx_free(staple->staple.data);
0764     }
0765 }
0766 
0767 
0768 ngx_int_t
0769 ngx_ssl_ocsp(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *responder,
0770     ngx_uint_t depth, ngx_shm_zone_t *shm_zone)
0771 {
0772     ngx_url_t             u;
0773     ngx_ssl_ocsp_conf_t  *ocf;
0774 
0775     ocf = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_ocsp_conf_t));
0776     if (ocf == NULL) {
0777         return NGX_ERROR;
0778     }
0779 
0780     ocf->depth = depth;
0781     ocf->shm_zone = shm_zone;
0782 
0783     if (responder->len) {
0784         ngx_memzero(&u, sizeof(ngx_url_t));
0785 
0786         u.url = *responder;
0787         u.default_port = 80;
0788         u.uri_part = 1;
0789 
0790         if (u.url.len > 7
0791             && ngx_strncasecmp(u.url.data, (u_char *) "http://", 7) == 0)
0792         {
0793             u.url.len -= 7;
0794             u.url.data += 7;
0795 
0796         } else {
0797             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
0798                           "invalid URL prefix in OCSP responder \"%V\" "
0799                           "in \"ssl_ocsp_responder\"", &u.url);
0800             return NGX_ERROR;
0801         }
0802 
0803         if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
0804             if (u.err) {
0805                 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
0806                               "%s in OCSP responder \"%V\" "
0807                               "in \"ssl_ocsp_responder\"", u.err, &u.url);
0808             }
0809 
0810             return NGX_ERROR;
0811         }
0812 
0813         ocf->addrs = u.addrs;
0814         ocf->naddrs = u.naddrs;
0815         ocf->host = u.host;
0816         ocf->uri = u.uri;
0817         ocf->port = u.port;
0818     }
0819 
0820     if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_ocsp_index, ocf) == 0) {
0821         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
0822                       "SSL_CTX_set_ex_data() failed");
0823         return NGX_ERROR;
0824     }
0825 
0826     return NGX_OK;
0827 }
0828 
0829 
0830 ngx_int_t
0831 ngx_ssl_ocsp_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
0832     ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)
0833 {
0834     ngx_ssl_ocsp_conf_t  *ocf;
0835 
0836     ocf = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_ocsp_index);
0837     ocf->resolver = resolver;
0838     ocf->resolver_timeout = resolver_timeout;
0839 
0840     return NGX_OK;
0841 }
0842 
0843 
0844 ngx_int_t
0845 ngx_ssl_ocsp_validate(ngx_connection_t *c)
0846 {
0847     X509                 *cert;
0848     SSL_CTX              *ssl_ctx;
0849     ngx_int_t             rc;
0850     X509_STORE           *store;
0851     X509_STORE_CTX       *store_ctx;
0852     STACK_OF(X509)       *chain;
0853     ngx_ssl_ocsp_t       *ocsp;
0854     ngx_ssl_ocsp_conf_t  *ocf;
0855 
0856     if (c->ssl->in_ocsp) {
0857         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
0858             return NGX_ERROR;
0859         }
0860 
0861         if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
0862             return NGX_ERROR;
0863         }
0864 
0865         return NGX_AGAIN;
0866     }
0867 
0868     ssl_ctx = SSL_get_SSL_CTX(c->ssl->connection);
0869 
0870     ocf = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_ocsp_index);
0871     if (ocf == NULL) {
0872         return NGX_OK;
0873     }
0874 
0875     if (SSL_get_verify_result(c->ssl->connection) != X509_V_OK) {
0876         return NGX_OK;
0877     }
0878 
0879     cert = SSL_get_peer_certificate(c->ssl->connection);
0880     if (cert == NULL) {
0881         return NGX_OK;
0882     }
0883 
0884     ocsp = ngx_pcalloc(c->pool, sizeof(ngx_ssl_ocsp_t));
0885     if (ocsp == NULL) {
0886         X509_free(cert);
0887         return NGX_ERROR;
0888     }
0889 
0890     c->ssl->ocsp = ocsp;
0891 
0892     ocsp->status = NGX_AGAIN;
0893     ocsp->cert_status = V_OCSP_CERTSTATUS_GOOD;
0894     ocsp->conf = ocf;
0895 
0896 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined LIBRESSL_VERSION_NUMBER)
0897 
0898     ocsp->certs = SSL_get0_verified_chain(c->ssl->connection);
0899 
0900     if (ocsp->certs) {
0901         ocsp->certs = X509_chain_up_ref(ocsp->certs);
0902         if (ocsp->certs == NULL) {
0903             X509_free(cert);
0904             return NGX_ERROR;
0905         }
0906     }
0907 
0908 #endif
0909 
0910     if (ocsp->certs == NULL) {
0911         store = SSL_CTX_get_cert_store(ssl_ctx);
0912         if (store == NULL) {
0913             ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
0914                           "SSL_CTX_get_cert_store() failed");
0915             X509_free(cert);
0916             return NGX_ERROR;
0917         }
0918 
0919         store_ctx = X509_STORE_CTX_new();
0920         if (store_ctx == NULL) {
0921             ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
0922                           "X509_STORE_CTX_new() failed");
0923             X509_free(cert);
0924             return NGX_ERROR;
0925         }
0926 
0927         chain = SSL_get_peer_cert_chain(c->ssl->connection);
0928 
0929         if (X509_STORE_CTX_init(store_ctx, store, cert, chain) == 0) {
0930             ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
0931                           "X509_STORE_CTX_init() failed");
0932             X509_STORE_CTX_free(store_ctx);
0933             X509_free(cert);
0934             return NGX_ERROR;
0935         }
0936 
0937         rc = X509_verify_cert(store_ctx);
0938         if (rc <= 0) {
0939             ngx_ssl_error(NGX_LOG_ERR, c->log, 0, "X509_verify_cert() failed");
0940             X509_STORE_CTX_free(store_ctx);
0941             X509_free(cert);
0942             return NGX_ERROR;
0943         }
0944 
0945         ocsp->certs = X509_STORE_CTX_get1_chain(store_ctx);
0946         if (ocsp->certs == NULL) {
0947             ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
0948                           "X509_STORE_CTX_get1_chain() failed");
0949             X509_STORE_CTX_free(store_ctx);
0950             X509_free(cert);
0951             return NGX_ERROR;
0952         }
0953 
0954         X509_STORE_CTX_free(store_ctx);
0955     }
0956 
0957     X509_free(cert);
0958 
0959     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
0960                    "ssl ocsp validate, certs:%d", sk_X509_num(ocsp->certs));
0961 
0962     ngx_ssl_ocsp_validate_next(c);
0963 
0964     if (ocsp->status == NGX_AGAIN) {
0965         c->ssl->in_ocsp = 1;
0966         return NGX_AGAIN;
0967     }
0968 
0969     return NGX_OK;
0970 }
0971 
0972 
0973 static void
0974 ngx_ssl_ocsp_validate_next(ngx_connection_t *c)
0975 {
0976     ngx_int_t             rc;
0977     ngx_uint_t            n;
0978     ngx_ssl_ocsp_t       *ocsp;
0979     ngx_ssl_ocsp_ctx_t   *ctx;
0980     ngx_ssl_ocsp_conf_t  *ocf;
0981 
0982     ocsp = c->ssl->ocsp;
0983     ocf = ocsp->conf;
0984 
0985     n = sk_X509_num(ocsp->certs);
0986 
0987     for ( ;; ) {
0988 
0989         if (ocsp->ncert == n - 1 || (ocf->depth == 2 && ocsp->ncert == 1)) {
0990             ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
0991                            "ssl ocsp validated, certs:%ui", ocsp->ncert);
0992             rc = NGX_OK;
0993             goto done;
0994         }
0995 
0996         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
0997                        "ssl ocsp validate cert:%ui", ocsp->ncert);
0998 
0999         ctx = ngx_ssl_ocsp_start(c->log);
1000         if (ctx == NULL) {
1001             rc = NGX_ERROR;
1002             goto done;
1003         }
1004 
1005         ocsp->ctx = ctx;
1006 
1007         ctx->ssl_ctx = SSL_get_SSL_CTX(c->ssl->connection);
1008         ctx->cert = sk_X509_value(ocsp->certs, ocsp->ncert);
1009         ctx->issuer = sk_X509_value(ocsp->certs, ocsp->ncert + 1);
1010         ctx->chain = ocsp->certs;
1011 
1012         ctx->resolver = ocf->resolver;
1013         ctx->resolver_timeout = ocf->resolver_timeout;
1014 
1015         ctx->handler = ngx_ssl_ocsp_handler;
1016         ctx->data = c;
1017 
1018         ctx->shm_zone = ocf->shm_zone;
1019 
1020         ctx->addrs = ocf->addrs;
1021         ctx->naddrs = ocf->naddrs;
1022         ctx->host = ocf->host;
1023         ctx->uri = ocf->uri;
1024         ctx->port = ocf->port;
1025 
1026         rc = ngx_ssl_ocsp_responder(c, ctx);
1027         if (rc != NGX_OK) {
1028             goto done;
1029         }
1030 
1031         if (ctx->uri.len == 0) {
1032             ngx_str_set(&ctx->uri, "/");
1033         }
1034 
1035         ocsp->ncert++;
1036 
1037         rc = ngx_ssl_ocsp_cache_lookup(ctx);
1038 
1039         if (rc == NGX_ERROR) {
1040             goto done;
1041         }
1042 
1043         if (rc == NGX_DECLINED) {
1044             break;
1045         }
1046 
1047         /* rc == NGX_OK */
1048 
1049         if (ctx->status != V_OCSP_CERTSTATUS_GOOD) {
1050             ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1051                            "ssl ocsp cached status \"%s\"",
1052                            OCSP_cert_status_str(ctx->status));
1053             ocsp->cert_status = ctx->status;
1054             goto done;
1055         }
1056 
1057         ocsp->ctx = NULL;
1058         ngx_ssl_ocsp_done(ctx);
1059     }
1060 
1061     ngx_ssl_ocsp_request(ctx);
1062     return;
1063 
1064 done:
1065 
1066     ocsp->status = rc;
1067 
1068     if (c->ssl->in_ocsp) {
1069         c->ssl->handshaked = 1;
1070         c->ssl->handler(c);
1071     }
1072 }
1073 
1074 
1075 static void
1076 ngx_ssl_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
1077 {
1078     ngx_int_t          rc;
1079     ngx_ssl_ocsp_t    *ocsp;
1080     ngx_connection_t  *c;
1081 
1082     c = ctx->data;
1083     ocsp = c->ssl->ocsp;
1084     ocsp->ctx = NULL;
1085 
1086     rc = ngx_ssl_ocsp_verify(ctx);
1087     if (rc != NGX_OK) {
1088         goto done;
1089     }
1090 
1091     rc = ngx_ssl_ocsp_cache_store(ctx);
1092     if (rc != NGX_OK) {
1093         goto done;
1094     }
1095 
1096     if (ctx->status != V_OCSP_CERTSTATUS_GOOD) {
1097         ocsp->cert_status = ctx->status;
1098         goto done;
1099     }
1100 
1101     ngx_ssl_ocsp_done(ctx);
1102 
1103     ngx_ssl_ocsp_validate_next(c);
1104 
1105     return;
1106 
1107 done:
1108 
1109     ocsp->status = rc;
1110     ngx_ssl_ocsp_done(ctx);
1111 
1112     if (c->ssl->in_ocsp) {
1113         c->ssl->handshaked = 1;
1114         c->ssl->handler(c);
1115     }
1116 }
1117 
1118 
1119 static ngx_int_t
1120 ngx_ssl_ocsp_responder(ngx_connection_t *c, ngx_ssl_ocsp_ctx_t *ctx)
1121 {
1122     char                      *s;
1123     ngx_str_t                  responder;
1124     ngx_url_t                  u;
1125     STACK_OF(OPENSSL_STRING)  *aia;
1126 
1127     if (ctx->host.len) {
1128         return NGX_OK;
1129     }
1130 
1131     /* extract OCSP responder URL from certificate */
1132 
1133     aia = X509_get1_ocsp(ctx->cert);
1134     if (aia == NULL) {
1135         ngx_log_error(NGX_LOG_ERR, c->log, 0,
1136                       "no OCSP responder URL in certificate");
1137         return NGX_ERROR;
1138     }
1139 
1140 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
1141     s = sk_OPENSSL_STRING_value(aia, 0);
1142 #else
1143     s = sk_value(aia, 0);
1144 #endif
1145     if (s == NULL) {
1146         ngx_log_error(NGX_LOG_ERR, c->log, 0,
1147                       "no OCSP responder URL in certificate");
1148         X509_email_free(aia);
1149         return NGX_ERROR;
1150     }
1151 
1152     responder.len = ngx_strlen(s);
1153     responder.data = ngx_palloc(ctx->pool, responder.len);
1154     if (responder.data == NULL) {
1155         X509_email_free(aia);
1156         return NGX_ERROR;
1157     }
1158 
1159     ngx_memcpy(responder.data, s, responder.len);
1160     X509_email_free(aia);
1161 
1162     ngx_memzero(&u, sizeof(ngx_url_t));
1163 
1164     u.url = responder;
1165     u.default_port = 80;
1166     u.uri_part = 1;
1167     u.no_resolve = 1;
1168 
1169     if (u.url.len > 7
1170         && ngx_strncasecmp(u.url.data, (u_char *) "http://", 7) == 0)
1171     {
1172         u.url.len -= 7;
1173         u.url.data += 7;
1174 
1175     } else {
1176         ngx_log_error(NGX_LOG_ERR, c->log, 0,
1177                       "invalid URL prefix in OCSP responder \"%V\" "
1178                       "in certificate", &u.url);
1179         return NGX_ERROR;
1180     }
1181 
1182     if (ngx_parse_url(ctx->pool, &u) != NGX_OK) {
1183         if (u.err) {
1184             ngx_log_error(NGX_LOG_ERR, c->log, 0,
1185                           "%s in OCSP responder \"%V\" in certificate",
1186                           u.err, &u.url);
1187         }
1188 
1189         return NGX_ERROR;
1190     }
1191 
1192     if (u.host.len == 0) {
1193         ngx_log_error(NGX_LOG_ERR, c->log, 0,
1194                       "empty host in OCSP responder in certificate");
1195         return NGX_ERROR;
1196     }
1197 
1198     ctx->addrs = u.addrs;
1199     ctx->naddrs = u.naddrs;
1200     ctx->host = u.host;
1201     ctx->uri = u.uri;
1202     ctx->port = u.port;
1203 
1204     return NGX_OK;
1205 }
1206 
1207 
1208 ngx_int_t
1209 ngx_ssl_ocsp_get_status(ngx_connection_t *c, const char **s)
1210 {
1211     ngx_ssl_ocsp_t  *ocsp;
1212 
1213     ocsp = c->ssl->ocsp;
1214     if (ocsp == NULL) {
1215         return NGX_OK;
1216     }
1217 
1218     if (ocsp->status == NGX_ERROR) {
1219         *s = "certificate status request failed";
1220         return NGX_DECLINED;
1221     }
1222 
1223     switch (ocsp->cert_status) {
1224 
1225     case V_OCSP_CERTSTATUS_GOOD:
1226         return NGX_OK;
1227 
1228     case V_OCSP_CERTSTATUS_REVOKED:
1229         *s = "certificate revoked";
1230         break;
1231 
1232     default: /* V_OCSP_CERTSTATUS_UNKNOWN */
1233         *s = "certificate status unknown";
1234     }
1235 
1236     return NGX_DECLINED;
1237 }
1238 
1239 
1240 void
1241 ngx_ssl_ocsp_cleanup(ngx_connection_t *c)
1242 {
1243     ngx_ssl_ocsp_t  *ocsp;
1244 
1245     ocsp = c->ssl->ocsp;
1246     if (ocsp == NULL) {
1247         return;
1248     }
1249 
1250     if (ocsp->ctx) {
1251         ngx_ssl_ocsp_done(ocsp->ctx);
1252         ocsp->ctx = NULL;
1253     }
1254 
1255     if (ocsp->certs) {
1256         sk_X509_pop_free(ocsp->certs, X509_free);
1257         ocsp->certs = NULL;
1258     }
1259 }
1260 
1261 
1262 static ngx_ssl_ocsp_ctx_t *
1263 ngx_ssl_ocsp_start(ngx_log_t *log)
1264 {
1265     ngx_pool_t          *pool;
1266     ngx_ssl_ocsp_ctx_t  *ctx;
1267 
1268     pool = ngx_create_pool(2048, log);
1269     if (pool == NULL) {
1270         return NULL;
1271     }
1272 
1273     ctx = ngx_pcalloc(pool, sizeof(ngx_ssl_ocsp_ctx_t));
1274     if (ctx == NULL) {
1275         ngx_destroy_pool(pool);
1276         return NULL;
1277     }
1278 
1279     log = ngx_palloc(pool, sizeof(ngx_log_t));
1280     if (log == NULL) {
1281         ngx_destroy_pool(pool);
1282         return NULL;
1283     }
1284 
1285     ctx->pool = pool;
1286 
1287     *log = *ctx->pool->log;
1288 
1289     ctx->pool->log = log;
1290     ctx->log = log;
1291 
1292     log->handler = ngx_ssl_ocsp_log_error;
1293     log->data = ctx;
1294     log->action = "requesting certificate status";
1295 
1296     return ctx;
1297 }
1298 
1299 
1300 static void
1301 ngx_ssl_ocsp_done(ngx_ssl_ocsp_ctx_t *ctx)
1302 {
1303     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1304                    "ssl ocsp done");
1305 
1306     if (ctx->peer.connection) {
1307         ngx_close_connection(ctx->peer.connection);
1308     }
1309 
1310     ngx_destroy_pool(ctx->pool);
1311 }
1312 
1313 
1314 static void
1315 ngx_ssl_ocsp_error(ngx_ssl_ocsp_ctx_t *ctx)
1316 {
1317     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1318                    "ssl ocsp error");
1319 
1320     ctx->code = 0;
1321     ctx->handler(ctx);
1322 }
1323 
1324 
1325 static void
1326 ngx_ssl_ocsp_next(ngx_ssl_ocsp_ctx_t *ctx)
1327 {
1328     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1329                    "ssl ocsp next");
1330 
1331     if (++ctx->naddr >= ctx->naddrs) {
1332         ngx_ssl_ocsp_error(ctx);
1333         return;
1334     }
1335 
1336     ctx->request->pos = ctx->request->start;
1337 
1338     if (ctx->response) {
1339         ctx->response->last = ctx->response->pos;
1340     }
1341 
1342     if (ctx->peer.connection) {
1343         ngx_close_connection(ctx->peer.connection);
1344         ctx->peer.connection = NULL;
1345     }
1346 
1347     ctx->state = 0;
1348     ctx->count = 0;
1349     ctx->done = 0;
1350 
1351     ngx_ssl_ocsp_connect(ctx);
1352 }
1353 
1354 
1355 static void
1356 ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx)
1357 {
1358     ngx_resolver_ctx_t  *resolve, temp;
1359 
1360     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1361                    "ssl ocsp request");
1362 
1363     if (ngx_ssl_ocsp_create_request(ctx) != NGX_OK) {
1364         ngx_ssl_ocsp_error(ctx);
1365         return;
1366     }
1367 
1368     if (ctx->resolver) {
1369         /* resolve OCSP responder hostname */
1370 
1371         temp.name = ctx->host;
1372 
1373         resolve = ngx_resolve_start(ctx->resolver, &temp);
1374         if (resolve == NULL) {
1375             ngx_ssl_ocsp_error(ctx);
1376             return;
1377         }
1378 
1379         if (resolve == NGX_NO_RESOLVER) {
1380             if (ctx->naddrs == 0) {
1381                 ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1382                               "no resolver defined to resolve %V", &ctx->host);
1383 
1384                 ngx_ssl_ocsp_error(ctx);
1385                 return;
1386             }
1387 
1388             ngx_log_error(NGX_LOG_WARN, ctx->log, 0,
1389                           "no resolver defined to resolve %V", &ctx->host);
1390             goto connect;
1391         }
1392 
1393         resolve->name = ctx->host;
1394         resolve->handler = ngx_ssl_ocsp_resolve_handler;
1395         resolve->data = ctx;
1396         resolve->timeout = ctx->resolver_timeout;
1397 
1398         if (ngx_resolve_name(resolve) != NGX_OK) {
1399             ngx_ssl_ocsp_error(ctx);
1400             return;
1401         }
1402 
1403         return;
1404     }
1405 
1406 connect:
1407 
1408     ngx_ssl_ocsp_connect(ctx);
1409 }
1410 
1411 
1412 static void
1413 ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve)
1414 {
1415     ngx_ssl_ocsp_ctx_t *ctx = resolve->data;
1416 
1417     u_char           *p;
1418     size_t            len;
1419     socklen_t         socklen;
1420     ngx_uint_t        i;
1421     struct sockaddr  *sockaddr;
1422 
1423     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1424                    "ssl ocsp resolve handler");
1425 
1426     if (resolve->state) {
1427         ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1428                       "%V could not be resolved (%i: %s)",
1429                       &resolve->name, resolve->state,
1430                       ngx_resolver_strerror(resolve->state));
1431         goto failed;
1432     }
1433 
1434 #if (NGX_DEBUG)
1435     {
1436     u_char     text[NGX_SOCKADDR_STRLEN];
1437     ngx_str_t  addr;
1438 
1439     addr.data = text;
1440 
1441     for (i = 0; i < resolve->naddrs; i++) {
1442         addr.len = ngx_sock_ntop(resolve->addrs[i].sockaddr,
1443                                  resolve->addrs[i].socklen,
1444                                  text, NGX_SOCKADDR_STRLEN, 0);
1445 
1446         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1447                        "name was resolved to %V", &addr);
1448 
1449     }
1450     }
1451 #endif
1452 
1453     ctx->naddrs = resolve->naddrs;
1454     ctx->addrs = ngx_pcalloc(ctx->pool, ctx->naddrs * sizeof(ngx_addr_t));
1455 
1456     if (ctx->addrs == NULL) {
1457         goto failed;
1458     }
1459 
1460     for (i = 0; i < resolve->naddrs; i++) {
1461 
1462         socklen = resolve->addrs[i].socklen;
1463 
1464         sockaddr = ngx_palloc(ctx->pool, socklen);
1465         if (sockaddr == NULL) {
1466             goto failed;
1467         }
1468 
1469         ngx_memcpy(sockaddr, resolve->addrs[i].sockaddr, socklen);
1470         ngx_inet_set_port(sockaddr, ctx->port);
1471 
1472         ctx->addrs[i].sockaddr = sockaddr;
1473         ctx->addrs[i].socklen = socklen;
1474 
1475         p = ngx_pnalloc(ctx->pool, NGX_SOCKADDR_STRLEN);
1476         if (p == NULL) {
1477             goto failed;
1478         }
1479 
1480         len = ngx_sock_ntop(sockaddr, socklen, p, NGX_SOCKADDR_STRLEN, 1);
1481 
1482         ctx->addrs[i].name.len = len;
1483         ctx->addrs[i].name.data = p;
1484     }
1485 
1486     ngx_resolve_name_done(resolve);
1487 
1488     ngx_ssl_ocsp_connect(ctx);
1489     return;
1490 
1491 failed:
1492 
1493     ngx_resolve_name_done(resolve);
1494     ngx_ssl_ocsp_error(ctx);
1495 }
1496 
1497 
1498 static void
1499 ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx)
1500 {
1501     ngx_int_t    rc;
1502     ngx_addr_t  *addr;
1503 
1504     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1505                    "ssl ocsp connect %ui/%ui", ctx->naddr, ctx->naddrs);
1506 
1507     addr = &ctx->addrs[ctx->naddr];
1508 
1509     ctx->peer.sockaddr = addr->sockaddr;
1510     ctx->peer.socklen = addr->socklen;
1511     ctx->peer.name = &addr->name;
1512     ctx->peer.get = ngx_event_get_peer;
1513     ctx->peer.log = ctx->log;
1514     ctx->peer.log_error = NGX_ERROR_ERR;
1515 
1516     rc = ngx_event_connect_peer(&ctx->peer);
1517 
1518     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1519                    "ssl ocsp connect peer done");
1520 
1521     if (rc == NGX_ERROR) {
1522         ngx_ssl_ocsp_error(ctx);
1523         return;
1524     }
1525 
1526     if (rc == NGX_BUSY || rc == NGX_DECLINED) {
1527         ngx_ssl_ocsp_next(ctx);
1528         return;
1529     }
1530 
1531     ctx->peer.connection->data = ctx;
1532     ctx->peer.connection->pool = ctx->pool;
1533 
1534     ctx->peer.connection->read->handler = ngx_ssl_ocsp_read_handler;
1535     ctx->peer.connection->write->handler = ngx_ssl_ocsp_write_handler;
1536 
1537     ctx->process = ngx_ssl_ocsp_process_status_line;
1538 
1539     if (ctx->timeout) {
1540         ngx_add_timer(ctx->peer.connection->read, ctx->timeout);
1541         ngx_add_timer(ctx->peer.connection->write, ctx->timeout);
1542     }
1543 
1544     if (rc == NGX_OK) {
1545         ngx_ssl_ocsp_write_handler(ctx->peer.connection->write);
1546         return;
1547     }
1548 }
1549 
1550 
1551 static void
1552 ngx_ssl_ocsp_write_handler(ngx_event_t *wev)
1553 {
1554     ssize_t              n, size;
1555     ngx_connection_t    *c;
1556     ngx_ssl_ocsp_ctx_t  *ctx;
1557 
1558     c = wev->data;
1559     ctx = c->data;
1560 
1561     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, wev->log, 0,
1562                    "ssl ocsp write handler");
1563 
1564     if (wev->timedout) {
1565         ngx_log_error(NGX_LOG_ERR, wev->log, NGX_ETIMEDOUT,
1566                       "OCSP responder timed out");
1567         ngx_ssl_ocsp_next(ctx);
1568         return;
1569     }
1570 
1571     size = ctx->request->last - ctx->request->pos;
1572 
1573     n = ngx_send(c, ctx->request->pos, size);
1574 
1575     if (n == NGX_ERROR) {
1576         ngx_ssl_ocsp_next(ctx);
1577         return;
1578     }
1579 
1580     if (n > 0) {
1581         ctx->request->pos += n;
1582 
1583         if (n == size) {
1584             wev->handler = ngx_ssl_ocsp_dummy_handler;
1585 
1586             if (wev->timer_set) {
1587                 ngx_del_timer(wev);
1588             }
1589 
1590             if (ngx_handle_write_event(wev, 0) != NGX_OK) {
1591                 ngx_ssl_ocsp_error(ctx);
1592             }
1593 
1594             return;
1595         }
1596     }
1597 
1598     if (!wev->timer_set && ctx->timeout) {
1599         ngx_add_timer(wev, ctx->timeout);
1600     }
1601 }
1602 
1603 
1604 static void
1605 ngx_ssl_ocsp_read_handler(ngx_event_t *rev)
1606 {
1607     ssize_t              n, size;
1608     ngx_int_t            rc;
1609     ngx_connection_t    *c;
1610     ngx_ssl_ocsp_ctx_t  *ctx;
1611 
1612     c = rev->data;
1613     ctx = c->data;
1614 
1615     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, rev->log, 0,
1616                    "ssl ocsp read handler");
1617 
1618     if (rev->timedout) {
1619         ngx_log_error(NGX_LOG_ERR, rev->log, NGX_ETIMEDOUT,
1620                       "OCSP responder timed out");
1621         ngx_ssl_ocsp_next(ctx);
1622         return;
1623     }
1624 
1625     if (ctx->response == NULL) {
1626         ctx->response = ngx_create_temp_buf(ctx->pool, 16384);
1627         if (ctx->response == NULL) {
1628             ngx_ssl_ocsp_error(ctx);
1629             return;
1630         }
1631     }
1632 
1633     for ( ;; ) {
1634 
1635         size = ctx->response->end - ctx->response->last;
1636 
1637         n = ngx_recv(c, ctx->response->last, size);
1638 
1639         if (n > 0) {
1640             ctx->response->last += n;
1641 
1642             rc = ctx->process(ctx);
1643 
1644             if (rc == NGX_ERROR) {
1645                 ngx_ssl_ocsp_next(ctx);
1646                 return;
1647             }
1648 
1649             continue;
1650         }
1651 
1652         if (n == NGX_AGAIN) {
1653 
1654             if (ngx_handle_read_event(rev, 0) != NGX_OK) {
1655                 ngx_ssl_ocsp_error(ctx);
1656             }
1657 
1658             return;
1659         }
1660 
1661         break;
1662     }
1663 
1664     ctx->done = 1;
1665 
1666     rc = ctx->process(ctx);
1667 
1668     if (rc == NGX_DONE) {
1669         /* ctx->handler() was called */
1670         return;
1671     }
1672 
1673     ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1674                   "OCSP responder prematurely closed connection");
1675 
1676     ngx_ssl_ocsp_next(ctx);
1677 }
1678 
1679 
1680 static void
1681 ngx_ssl_ocsp_dummy_handler(ngx_event_t *ev)
1682 {
1683     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0,
1684                    "ssl ocsp dummy handler");
1685 }
1686 
1687 
1688 static ngx_int_t
1689 ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx)
1690 {
1691     int            len;
1692     u_char        *p;
1693     uintptr_t      escape;
1694     ngx_str_t      binary, base64;
1695     ngx_buf_t     *b;
1696     OCSP_CERTID   *id;
1697     OCSP_REQUEST  *ocsp;
1698 
1699     ocsp = OCSP_REQUEST_new();
1700     if (ocsp == NULL) {
1701         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1702                       "OCSP_REQUEST_new() failed");
1703         return NGX_ERROR;
1704     }
1705 
1706     id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
1707     if (id == NULL) {
1708         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1709                       "OCSP_cert_to_id() failed");
1710         goto failed;
1711     }
1712 
1713     if (OCSP_request_add0_id(ocsp, id) == NULL) {
1714         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1715                       "OCSP_request_add0_id() failed");
1716         OCSP_CERTID_free(id);
1717         goto failed;
1718     }
1719 
1720     len = i2d_OCSP_REQUEST(ocsp, NULL);
1721     if (len <= 0) {
1722         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
1723                       "i2d_OCSP_REQUEST() failed");
1724         goto failed;
1725     }
1726 
1727     binary.len = len;
1728     binary.data = ngx_palloc(ctx->pool, len);
1729     if (binary.data == NULL) {
1730         goto failed;
1731     }
1732 
1733     p = binary.data;
1734     len = i2d_OCSP_REQUEST(ocsp, &p);
1735     if (len <= 0) {
1736         ngx_ssl_error(NGX_LOG_EMERG, ctx->log, 0,
1737                       "i2d_OCSP_REQUEST() failed");
1738         goto failed;
1739     }
1740 
1741     base64.len = ngx_base64_encoded_length(binary.len);
1742     base64.data = ngx_palloc(ctx->pool, base64.len);
1743     if (base64.data == NULL) {
1744         goto failed;
1745     }
1746 
1747     ngx_encode_base64(&base64, &binary);
1748 
1749     escape = ngx_escape_uri(NULL, base64.data, base64.len,
1750                             NGX_ESCAPE_URI_COMPONENT);
1751 
1752     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1753                    "ssl ocsp request length %z, escape %d",
1754                    base64.len, (int) escape);
1755 
1756     len = sizeof("GET ") - 1 + ctx->uri.len + sizeof("/") - 1
1757           + base64.len + 2 * escape + sizeof(" HTTP/1.0" CRLF) - 1
1758           + sizeof("Host: ") - 1 + ctx->host.len + sizeof(CRLF) - 1
1759           + sizeof(CRLF) - 1;
1760 
1761     b = ngx_create_temp_buf(ctx->pool, len);
1762     if (b == NULL) {
1763         goto failed;
1764     }
1765 
1766     p = b->last;
1767 
1768     p = ngx_cpymem(p, "GET ", sizeof("GET ") - 1);
1769     p = ngx_cpymem(p, ctx->uri.data, ctx->uri.len);
1770 
1771     if (ctx->uri.data[ctx->uri.len - 1] != '/') {
1772         *p++ = '/';
1773     }
1774 
1775     if (escape == 0) {
1776         p = ngx_cpymem(p, base64.data, base64.len);
1777 
1778     } else {
1779         p = (u_char *) ngx_escape_uri(p, base64.data, base64.len,
1780                                       NGX_ESCAPE_URI_COMPONENT);
1781     }
1782 
1783     p = ngx_cpymem(p, " HTTP/1.0" CRLF, sizeof(" HTTP/1.0" CRLF) - 1);
1784     p = ngx_cpymem(p, "Host: ", sizeof("Host: ") - 1);
1785     p = ngx_cpymem(p, ctx->host.data, ctx->host.len);
1786     *p++ = CR; *p++ = LF;
1787 
1788     /* add "\r\n" at the header end */
1789     *p++ = CR; *p++ = LF;
1790 
1791     b->last = p;
1792     ctx->request = b;
1793 
1794     OCSP_REQUEST_free(ocsp);
1795 
1796     return NGX_OK;
1797 
1798 failed:
1799 
1800     OCSP_REQUEST_free(ocsp);
1801 
1802     return NGX_ERROR;
1803 }
1804 
1805 
1806 static ngx_int_t
1807 ngx_ssl_ocsp_process_status_line(ngx_ssl_ocsp_ctx_t *ctx)
1808 {
1809     ngx_int_t  rc;
1810 
1811     rc = ngx_ssl_ocsp_parse_status_line(ctx);
1812 
1813     if (rc == NGX_OK) {
1814         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1815                        "ssl ocsp status %ui \"%*s\"",
1816                        ctx->code,
1817                        ctx->header_end - ctx->header_start,
1818                        ctx->header_start);
1819 
1820         ctx->process = ngx_ssl_ocsp_process_headers;
1821         return ctx->process(ctx);
1822     }
1823 
1824     if (rc == NGX_AGAIN) {
1825         return NGX_AGAIN;
1826     }
1827 
1828     /* rc == NGX_ERROR */
1829 
1830     ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
1831                   "OCSP responder sent invalid response");
1832 
1833     return NGX_ERROR;
1834 }
1835 
1836 
1837 static ngx_int_t
1838 ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t *ctx)
1839 {
1840     u_char      ch;
1841     u_char     *p;
1842     ngx_buf_t  *b;
1843     enum {
1844         sw_start = 0,
1845         sw_H,
1846         sw_HT,
1847         sw_HTT,
1848         sw_HTTP,
1849         sw_first_major_digit,
1850         sw_major_digit,
1851         sw_first_minor_digit,
1852         sw_minor_digit,
1853         sw_status,
1854         sw_space_after_status,
1855         sw_status_text,
1856         sw_almost_done
1857     } state;
1858 
1859     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
1860                    "ssl ocsp process status line");
1861 
1862     state = ctx->state;
1863     b = ctx->response;
1864 
1865     for (p = b->pos; p < b->last; p++) {
1866         ch = *p;
1867 
1868         switch (state) {
1869 
1870         /* "HTTP/" */
1871         case sw_start:
1872             switch (ch) {
1873             case 'H':
1874                 state = sw_H;
1875                 break;
1876             default:
1877                 return NGX_ERROR;
1878             }
1879             break;
1880 
1881         case sw_H:
1882             switch (ch) {
1883             case 'T':
1884                 state = sw_HT;
1885                 break;
1886             default:
1887                 return NGX_ERROR;
1888             }
1889             break;
1890 
1891         case sw_HT:
1892             switch (ch) {
1893             case 'T':
1894                 state = sw_HTT;
1895                 break;
1896             default:
1897                 return NGX_ERROR;
1898             }
1899             break;
1900 
1901         case sw_HTT:
1902             switch (ch) {
1903             case 'P':
1904                 state = sw_HTTP;
1905                 break;
1906             default:
1907                 return NGX_ERROR;
1908             }
1909             break;
1910 
1911         case sw_HTTP:
1912             switch (ch) {
1913             case '/':
1914                 state = sw_first_major_digit;
1915                 break;
1916             default:
1917                 return NGX_ERROR;
1918             }
1919             break;
1920 
1921         /* the first digit of major HTTP version */
1922         case sw_first_major_digit:
1923             if (ch < '1' || ch > '9') {
1924                 return NGX_ERROR;
1925             }
1926 
1927             state = sw_major_digit;
1928             break;
1929 
1930         /* the major HTTP version or dot */
1931         case sw_major_digit:
1932             if (ch == '.') {
1933                 state = sw_first_minor_digit;
1934                 break;
1935             }
1936 
1937             if (ch < '0' || ch > '9') {
1938                 return NGX_ERROR;
1939             }
1940 
1941             break;
1942 
1943         /* the first digit of minor HTTP version */
1944         case sw_first_minor_digit:
1945             if (ch < '0' || ch > '9') {
1946                 return NGX_ERROR;
1947             }
1948 
1949             state = sw_minor_digit;
1950             break;
1951 
1952         /* the minor HTTP version or the end of the request line */
1953         case sw_minor_digit:
1954             if (ch == ' ') {
1955                 state = sw_status;
1956                 break;
1957             }
1958 
1959             if (ch < '0' || ch > '9') {
1960                 return NGX_ERROR;
1961             }
1962 
1963             break;
1964 
1965         /* HTTP status code */
1966         case sw_status:
1967             if (ch == ' ') {
1968                 break;
1969             }
1970 
1971             if (ch < '0' || ch > '9') {
1972                 return NGX_ERROR;
1973             }
1974 
1975             ctx->code = ctx->code * 10 + (ch - '0');
1976 
1977             if (++ctx->count == 3) {
1978                 state = sw_space_after_status;
1979                 ctx->header_start = p - 2;
1980             }
1981 
1982             break;
1983 
1984         /* space or end of line */
1985         case sw_space_after_status:
1986             switch (ch) {
1987             case ' ':
1988                 state = sw_status_text;
1989                 break;
1990             case '.':                    /* IIS may send 403.1, 403.2, etc */
1991                 state = sw_status_text;
1992                 break;
1993             case CR:
1994                 state = sw_almost_done;
1995                 break;
1996             case LF:
1997                 ctx->header_end = p;
1998                 goto done;
1999             default:
2000                 return NGX_ERROR;
2001             }
2002             break;
2003 
2004         /* any text until end of line */
2005         case sw_status_text:
2006             switch (ch) {
2007             case CR:
2008                 state = sw_almost_done;
2009                 break;
2010             case LF:
2011                 ctx->header_end = p;
2012                 goto done;
2013             }
2014             break;
2015 
2016         /* end of status line */
2017         case sw_almost_done:
2018             switch (ch) {
2019             case LF:
2020                 ctx->header_end = p - 1;
2021                 goto done;
2022             default:
2023                 return NGX_ERROR;
2024             }
2025         }
2026     }
2027 
2028     b->pos = p;
2029     ctx->state = state;
2030 
2031     return NGX_AGAIN;
2032 
2033 done:
2034 
2035     b->pos = p + 1;
2036     ctx->state = sw_start;
2037 
2038     return NGX_OK;
2039 }
2040 
2041 
2042 static ngx_int_t
2043 ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx)
2044 {
2045     size_t     len;
2046     ngx_int_t  rc;
2047 
2048     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
2049                    "ssl ocsp process headers");
2050 
2051     for ( ;; ) {
2052         rc = ngx_ssl_ocsp_parse_header_line(ctx);
2053 
2054         if (rc == NGX_OK) {
2055 
2056             ngx_log_debug4(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
2057                            "ssl ocsp header \"%*s: %*s\"",
2058                            ctx->header_name_end - ctx->header_name_start,
2059                            ctx->header_name_start,
2060                            ctx->header_end - ctx->header_start,
2061                            ctx->header_start);
2062 
2063             len = ctx->header_name_end - ctx->header_name_start;
2064 
2065             if (len == sizeof("Content-Type") - 1
2066                 && ngx_strncasecmp(ctx->header_name_start,
2067                                    (u_char *) "Content-Type",
2068                                    sizeof("Content-Type") - 1)
2069                    == 0)
2070             {
2071                 len = ctx->header_end - ctx->header_start;
2072 
2073                 if (len != sizeof("application/ocsp-response") - 1
2074                     || ngx_strncasecmp(ctx->header_start,
2075                                        (u_char *) "application/ocsp-response",
2076                                        sizeof("application/ocsp-response") - 1)
2077                        != 0)
2078                 {
2079                     ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
2080                                   "OCSP responder sent invalid "
2081                                   "\"Content-Type\" header: \"%*s\"",
2082                                   ctx->header_end - ctx->header_start,
2083                                   ctx->header_start);
2084                     return NGX_ERROR;
2085                 }
2086 
2087                 continue;
2088             }
2089 
2090             /* TODO: honor Content-Length */
2091 
2092             continue;
2093         }
2094 
2095         if (rc == NGX_DONE) {
2096             break;
2097         }
2098 
2099         if (rc == NGX_AGAIN) {
2100             return NGX_AGAIN;
2101         }
2102 
2103         /* rc == NGX_ERROR */
2104 
2105         ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
2106                       "OCSP responder sent invalid response");
2107 
2108         return NGX_ERROR;
2109     }
2110 
2111     ctx->process = ngx_ssl_ocsp_process_body;
2112     return ctx->process(ctx);
2113 }
2114 
2115 
2116 static ngx_int_t
2117 ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx)
2118 {
2119     u_char  c, ch, *p;
2120     enum {
2121         sw_start = 0,
2122         sw_name,
2123         sw_space_before_value,
2124         sw_value,
2125         sw_space_after_value,
2126         sw_almost_done,
2127         sw_header_almost_done
2128     } state;
2129 
2130     state = ctx->state;
2131 
2132     for (p = ctx->response->pos; p < ctx->response->last; p++) {
2133         ch = *p;
2134 
2135 #if 0
2136         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
2137                        "s:%d in:'%02Xd:%c'", state, ch, ch);
2138 #endif
2139 
2140         switch (state) {
2141 
2142         /* first char */
2143         case sw_start:
2144 
2145             switch (ch) {
2146             case CR:
2147                 ctx->header_end = p;
2148                 state = sw_header_almost_done;
2149                 break;
2150             case LF:
2151                 ctx->header_end = p;
2152                 goto header_done;
2153             default:
2154                 state = sw_name;
2155                 ctx->header_name_start = p;
2156 
2157                 c = (u_char) (ch | 0x20);
2158                 if (c >= 'a' && c <= 'z') {
2159                     break;
2160                 }
2161 
2162                 if (ch >= '0' && ch <= '9') {
2163                     break;
2164                 }
2165 
2166                 return NGX_ERROR;
2167             }
2168             break;
2169 
2170         /* header name */
2171         case sw_name:
2172             c = (u_char) (ch | 0x20);
2173             if (c >= 'a' && c <= 'z') {
2174                 break;
2175             }
2176 
2177             if (ch == ':') {
2178                 ctx->header_name_end = p;
2179                 state = sw_space_before_value;
2180                 break;
2181             }
2182 
2183             if (ch == '-') {
2184                 break;
2185             }
2186 
2187             if (ch >= '0' && ch <= '9') {
2188                 break;
2189             }
2190 
2191             if (ch == CR) {
2192                 ctx->header_name_end = p;
2193                 ctx->header_start = p;
2194                 ctx->header_end = p;
2195                 state = sw_almost_done;
2196                 break;
2197             }
2198 
2199             if (ch == LF) {
2200                 ctx->header_name_end = p;
2201                 ctx->header_start = p;
2202                 ctx->header_end = p;
2203                 goto done;
2204             }
2205 
2206             return NGX_ERROR;
2207 
2208         /* space* before header value */
2209         case sw_space_before_value:
2210             switch (ch) {
2211             case ' ':
2212                 break;
2213             case CR:
2214                 ctx->header_start = p;
2215                 ctx->header_end = p;
2216                 state = sw_almost_done;
2217                 break;
2218             case LF:
2219                 ctx->header_start = p;
2220                 ctx->header_end = p;
2221                 goto done;
2222             default:
2223                 ctx->header_start = p;
2224                 state = sw_value;
2225                 break;
2226             }
2227             break;
2228 
2229         /* header value */
2230         case sw_value:
2231             switch (ch) {
2232             case ' ':
2233                 ctx->header_end = p;
2234                 state = sw_space_after_value;
2235                 break;
2236             case CR:
2237                 ctx->header_end = p;
2238                 state = sw_almost_done;
2239                 break;
2240             case LF:
2241                 ctx->header_end = p;
2242                 goto done;
2243             }
2244             break;
2245 
2246         /* space* before end of header line */
2247         case sw_space_after_value:
2248             switch (ch) {
2249             case ' ':
2250                 break;
2251             case CR:
2252                 state = sw_almost_done;
2253                 break;
2254             case LF:
2255                 goto done;
2256             default:
2257                 state = sw_value;
2258                 break;
2259             }
2260             break;
2261 
2262         /* end of header line */
2263         case sw_almost_done:
2264             switch (ch) {
2265             case LF:
2266                 goto done;
2267             default:
2268                 return NGX_ERROR;
2269             }
2270 
2271         /* end of header */
2272         case sw_header_almost_done:
2273             switch (ch) {
2274             case LF:
2275                 goto header_done;
2276             default:
2277                 return NGX_ERROR;
2278             }
2279         }
2280     }
2281 
2282     ctx->response->pos = p;
2283     ctx->state = state;
2284 
2285     return NGX_AGAIN;
2286 
2287 done:
2288 
2289     ctx->response->pos = p + 1;
2290     ctx->state = sw_start;
2291 
2292     return NGX_OK;
2293 
2294 header_done:
2295 
2296     ctx->response->pos = p + 1;
2297     ctx->state = sw_start;
2298 
2299     return NGX_DONE;
2300 }
2301 
2302 
2303 static ngx_int_t
2304 ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx)
2305 {
2306     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
2307                    "ssl ocsp process body");
2308 
2309     if (ctx->done) {
2310         ctx->handler(ctx);
2311         return NGX_DONE;
2312     }
2313 
2314     return NGX_AGAIN;
2315 }
2316 
2317 
2318 static ngx_int_t
2319 ngx_ssl_ocsp_verify(ngx_ssl_ocsp_ctx_t *ctx)
2320 {
2321     int                    n;
2322     size_t                 len;
2323     X509_STORE            *store;
2324     const u_char          *p;
2325     OCSP_CERTID           *id;
2326     OCSP_RESPONSE         *ocsp;
2327     OCSP_BASICRESP        *basic;
2328     ASN1_GENERALIZEDTIME  *thisupdate, *nextupdate;
2329 
2330     ocsp = NULL;
2331     basic = NULL;
2332     id = NULL;
2333 
2334     if (ctx->code != 200) {
2335         goto error;
2336     }
2337 
2338     /* check the response */
2339 
2340     len = ctx->response->last - ctx->response->pos;
2341     p = ctx->response->pos;
2342 
2343     ocsp = d2i_OCSP_RESPONSE(NULL, &p, len);
2344     if (ocsp == NULL) {
2345         ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
2346                       "d2i_OCSP_RESPONSE() failed");
2347         goto error;
2348     }
2349 
2350     n = OCSP_response_status(ocsp);
2351 
2352     if (n != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
2353         ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
2354                       "OCSP response not successful (%d: %s)",
2355                       n, OCSP_response_status_str(n));
2356         goto error;
2357     }
2358 
2359     basic = OCSP_response_get1_basic(ocsp);
2360     if (basic == NULL) {
2361         ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
2362                       "OCSP_response_get1_basic() failed");
2363         goto error;
2364     }
2365 
2366     store = SSL_CTX_get_cert_store(ctx->ssl_ctx);
2367     if (store == NULL) {
2368         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
2369                       "SSL_CTX_get_cert_store() failed");
2370         goto error;
2371     }
2372 
2373     if (OCSP_basic_verify(basic, ctx->chain, store, ctx->flags) != 1) {
2374         ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
2375                       "OCSP_basic_verify() failed");
2376         goto error;
2377     }
2378 
2379     id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
2380     if (id == NULL) {
2381         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
2382                       "OCSP_cert_to_id() failed");
2383         goto error;
2384     }
2385 
2386     if (OCSP_resp_find_status(basic, id, &ctx->status, NULL, NULL,
2387                               &thisupdate, &nextupdate)
2388         != 1)
2389     {
2390         ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
2391                       "certificate status not found in the OCSP response");
2392         goto error;
2393     }
2394 
2395     if (OCSP_check_validity(thisupdate, nextupdate, 300, -1) != 1) {
2396         ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
2397                       "OCSP_check_validity() failed");
2398         goto error;
2399     }
2400 
2401     if (nextupdate) {
2402         ctx->valid = ngx_ssl_stapling_time(nextupdate);
2403         if (ctx->valid == (time_t) NGX_ERROR) {
2404             ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
2405                           "invalid nextUpdate time in certificate status");
2406             goto error;
2407         }
2408 
2409     } else {
2410         ctx->valid = NGX_MAX_TIME_T_VALUE;
2411     }
2412 
2413     OCSP_CERTID_free(id);
2414     OCSP_BASICRESP_free(basic);
2415     OCSP_RESPONSE_free(ocsp);
2416 
2417     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
2418                    "ssl ocsp response, %s, %uz",
2419                    OCSP_cert_status_str(ctx->status), len);
2420 
2421     return NGX_OK;
2422 
2423 error:
2424 
2425     if (id) {
2426         OCSP_CERTID_free(id);
2427     }
2428 
2429     if (basic) {
2430         OCSP_BASICRESP_free(basic);
2431     }
2432 
2433     if (ocsp) {
2434         OCSP_RESPONSE_free(ocsp);
2435     }
2436 
2437     return NGX_ERROR;
2438 }
2439 
2440 
2441 ngx_int_t
2442 ngx_ssl_ocsp_cache_init(ngx_shm_zone_t *shm_zone, void *data)
2443 {
2444     size_t                 len;
2445     ngx_slab_pool_t       *shpool;
2446     ngx_ssl_ocsp_cache_t  *cache;
2447 
2448     if (data) {
2449         shm_zone->data = data;
2450         return NGX_OK;
2451     }
2452 
2453     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
2454 
2455     if (shm_zone->shm.exists) {
2456         shm_zone->data = shpool->data;
2457         return NGX_OK;
2458     }
2459 
2460     cache = ngx_slab_alloc(shpool, sizeof(ngx_ssl_ocsp_cache_t));
2461     if (cache == NULL) {
2462         return NGX_ERROR;
2463     }
2464 
2465     shpool->data = cache;
2466     shm_zone->data = cache;
2467 
2468     ngx_rbtree_init(&cache->rbtree, &cache->sentinel,
2469                     ngx_str_rbtree_insert_value);
2470 
2471     ngx_queue_init(&cache->expire_queue);
2472 
2473     len = sizeof(" in OCSP cache \"\"") + shm_zone->shm.name.len;
2474 
2475     shpool->log_ctx = ngx_slab_alloc(shpool, len);
2476     if (shpool->log_ctx == NULL) {
2477         return NGX_ERROR;
2478     }
2479 
2480     ngx_sprintf(shpool->log_ctx, " in OCSP cache \"%V\"%Z",
2481                 &shm_zone->shm.name);
2482 
2483     shpool->log_nomem = 0;
2484 
2485     return NGX_OK;
2486 }
2487 
2488 
2489 static ngx_int_t
2490 ngx_ssl_ocsp_cache_lookup(ngx_ssl_ocsp_ctx_t *ctx)
2491 {
2492     uint32_t                    hash;
2493     ngx_shm_zone_t             *shm_zone;
2494     ngx_slab_pool_t            *shpool;
2495     ngx_ssl_ocsp_cache_t       *cache;
2496     ngx_ssl_ocsp_cache_node_t  *node;
2497 
2498     shm_zone = ctx->shm_zone;
2499 
2500     if (shm_zone == NULL) {
2501         return NGX_DECLINED;
2502     }
2503 
2504     if (ngx_ssl_ocsp_create_key(ctx) != NGX_OK) {
2505         return NGX_ERROR;
2506     }
2507 
2508     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0, "ssl ocsp cache lookup");
2509 
2510     cache = shm_zone->data;
2511     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
2512     hash = ngx_hash_key(ctx->key.data, ctx->key.len);
2513 
2514     ngx_shmtx_lock(&shpool->mutex);
2515 
2516     node = (ngx_ssl_ocsp_cache_node_t *)
2517                ngx_str_rbtree_lookup(&cache->rbtree, &ctx->key, hash);
2518 
2519     if (node) {
2520         if (node->valid > ngx_time()) {
2521             ctx->status = node->status;
2522             ngx_shmtx_unlock(&shpool->mutex);
2523 
2524             ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
2525                            "ssl ocsp cache hit, %s",
2526                            OCSP_cert_status_str(ctx->status));
2527 
2528             return NGX_OK;
2529         }
2530 
2531         ngx_queue_remove(&node->queue);
2532         ngx_rbtree_delete(&cache->rbtree, &node->node.node);
2533         ngx_slab_free_locked(shpool, node);
2534 
2535         ngx_shmtx_unlock(&shpool->mutex);
2536 
2537         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
2538                        "ssl ocsp cache expired");
2539 
2540         return NGX_DECLINED;
2541     }
2542 
2543     ngx_shmtx_unlock(&shpool->mutex);
2544 
2545     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0, "ssl ocsp cache miss");
2546 
2547     return NGX_DECLINED;
2548 }
2549 
2550 
2551 static ngx_int_t
2552 ngx_ssl_ocsp_cache_store(ngx_ssl_ocsp_ctx_t *ctx)
2553 {
2554     time_t                      now, valid;
2555     uint32_t                    hash;
2556     ngx_queue_t                *q;
2557     ngx_shm_zone_t             *shm_zone;
2558     ngx_slab_pool_t            *shpool;
2559     ngx_ssl_ocsp_cache_t       *cache;
2560     ngx_ssl_ocsp_cache_node_t  *node;
2561 
2562     shm_zone = ctx->shm_zone;
2563 
2564     if (shm_zone == NULL) {
2565         return NGX_OK;
2566     }
2567 
2568     valid = ctx->valid;
2569 
2570     now = ngx_time();
2571 
2572     if (valid < now) {
2573         return NGX_OK;
2574     }
2575 
2576     if (valid == NGX_MAX_TIME_T_VALUE) {
2577         valid = now + 3600;
2578     }
2579 
2580     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
2581                    "ssl ocsp cache store, valid:%T", valid - now);
2582 
2583     cache = shm_zone->data;
2584     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
2585     hash = ngx_hash_key(ctx->key.data, ctx->key.len);
2586 
2587     ngx_shmtx_lock(&shpool->mutex);
2588 
2589     node = ngx_slab_calloc_locked(shpool,
2590                              sizeof(ngx_ssl_ocsp_cache_node_t) + ctx->key.len);
2591     if (node == NULL) {
2592 
2593         if (!ngx_queue_empty(&cache->expire_queue)) {
2594             q = ngx_queue_last(&cache->expire_queue);
2595             node = ngx_queue_data(q, ngx_ssl_ocsp_cache_node_t, queue);
2596 
2597             ngx_rbtree_delete(&cache->rbtree, &node->node.node);
2598             ngx_queue_remove(q);
2599             ngx_slab_free_locked(shpool, node);
2600 
2601             node = ngx_slab_alloc_locked(shpool,
2602                              sizeof(ngx_ssl_ocsp_cache_node_t) + ctx->key.len);
2603         }
2604 
2605         if (node == NULL) {
2606             ngx_shmtx_unlock(&shpool->mutex);
2607             ngx_log_error(NGX_LOG_ALERT, ctx->log, 0,
2608                           "could not allocate new entry%s", shpool->log_ctx);
2609             return NGX_ERROR;
2610         }
2611     }
2612 
2613     node->node.str.len = ctx->key.len;
2614     node->node.str.data = (u_char *) node + sizeof(ngx_ssl_ocsp_cache_node_t);
2615     ngx_memcpy(node->node.str.data, ctx->key.data, ctx->key.len);
2616     node->node.node.key = hash;
2617     node->status = ctx->status;
2618     node->valid = valid;
2619 
2620     ngx_rbtree_insert(&cache->rbtree, &node->node.node);
2621     ngx_queue_insert_head(&cache->expire_queue, &node->queue);
2622 
2623     ngx_shmtx_unlock(&shpool->mutex);
2624 
2625     return NGX_OK;
2626 }
2627 
2628 
2629 static ngx_int_t
2630 ngx_ssl_ocsp_create_key(ngx_ssl_ocsp_ctx_t *ctx)
2631 {
2632     u_char        *p;
2633     X509_NAME     *name;
2634     ASN1_INTEGER  *serial;
2635 
2636     p = ngx_pnalloc(ctx->pool, 60);
2637     if (p == NULL) {
2638         return NGX_ERROR;
2639     }
2640 
2641     ctx->key.data = p;
2642     ctx->key.len = 60;
2643 
2644     name = X509_get_subject_name(ctx->issuer);
2645     if (X509_NAME_digest(name, EVP_sha1(), p, NULL) == 0) {
2646         return NGX_ERROR;
2647     }
2648 
2649     p += 20;
2650 
2651     if (X509_pubkey_digest(ctx->issuer, EVP_sha1(), p, NULL) == 0) {
2652         return NGX_ERROR;
2653     }
2654 
2655     p += 20;
2656 
2657     serial = X509_get_serialNumber(ctx->cert);
2658     if (serial->length > 20) {
2659         return NGX_ERROR;
2660     }
2661 
2662     p = ngx_cpymem(p, serial->data, serial->length);
2663     ngx_memzero(p, 20 - serial->length);
2664 
2665 #if (NGX_DEBUG)
2666     {
2667         u_char  buf[120];
2668 
2669         ngx_hex_dump(buf, ctx->key.data, ctx->key.len);
2670 
2671         ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
2672                        "ssl ocsp key %*s", sizeof(buf), buf);
2673     }
2674 #endif
2675 
2676     return NGX_OK;
2677 }
2678 
2679 
2680 static u_char *
2681 ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len)
2682 {
2683     u_char              *p;
2684     ngx_ssl_ocsp_ctx_t  *ctx;
2685 
2686     p = buf;
2687 
2688     if (log->action) {
2689         p = ngx_snprintf(buf, len, " while %s", log->action);
2690         len -= p - buf;
2691         buf = p;
2692     }
2693 
2694     ctx = log->data;
2695 
2696     if (ctx) {
2697         p = ngx_snprintf(buf, len, ", responder: %V", &ctx->host);
2698         len -= p - buf;
2699         buf = p;
2700     }
2701 
2702     if (ctx && ctx->peer.name) {
2703         p = ngx_snprintf(buf, len, ", peer: %V", ctx->peer.name);
2704         len -= p - buf;
2705         buf = p;
2706     }
2707 
2708     if (ctx && ctx->name) {
2709         p = ngx_snprintf(buf, len, ", certificate: \"%s\"", ctx->name);
2710         len -= p - buf;
2711         buf = p;
2712     }
2713 
2714     return p;
2715 }
2716 
2717 
2718 #else
2719 
2720 
2721 ngx_int_t
2722 ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file,
2723     ngx_str_t *responder, ngx_uint_t verify)
2724 {
2725     ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
2726                   "\"ssl_stapling\" ignored, not supported");
2727 
2728     return NGX_OK;
2729 }
2730 
2731 
2732 ngx_int_t
2733 ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
2734     ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)
2735 {
2736     return NGX_OK;
2737 }
2738 
2739 
2740 ngx_int_t
2741 ngx_ssl_ocsp(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *responder,
2742     ngx_uint_t depth, ngx_shm_zone_t *shm_zone)
2743 {
2744     ngx_log_error(NGX_LOG_EMERG, ssl->log, 0,
2745                   "\"ssl_ocsp\" is not supported on this platform");
2746 
2747     return NGX_ERROR;
2748 }
2749 
2750 
2751 ngx_int_t
2752 ngx_ssl_ocsp_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
2753     ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)
2754 {
2755     return NGX_OK;
2756 }
2757 
2758 
2759 ngx_int_t
2760 ngx_ssl_ocsp_validate(ngx_connection_t *c)
2761 {
2762     return NGX_OK;
2763 }
2764 
2765 
2766 ngx_int_t
2767 ngx_ssl_ocsp_get_status(ngx_connection_t *c, const char **s)
2768 {
2769     return NGX_OK;
2770 }
2771 
2772 
2773 void
2774 ngx_ssl_ocsp_cleanup(ngx_connection_t *c)
2775 {
2776 }
2777 
2778 
2779 ngx_int_t
2780 ngx_ssl_ocsp_cache_init(ngx_shm_zone_t *shm_zone, void *data)
2781 {
2782     return NGX_OK;
2783 }
2784 
2785 
2786 #endif