"Fossies" - the Fresh Open Source Software Archive

Member "hitch-1.5.2/src/ocsp.c" (27 Aug 2019, 16841 Bytes) of package /linux/www/hitch-1.5.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ocsp.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.4.6_vs_1.4.8.

    1 /**
    2   * Copyright 2016 Varnish Software
    3   *
    4   * Redistribution and use in source and binary forms, with or without
    5   * modification, are permitted provided that the following conditions
    6   * are met:
    7   *
    8   *    1. Redistributions of source code must retain the above
    9   *       copyright notice, this list of conditions and the following
   10   *       disclaimer.
   11   *
   12   *    2. Redistributions in binary form must reproduce the above
   13   *       copyright notice, this list of conditions and the following
   14   *       disclaimer in the documentation and/or other materials
   15   *       provided with the distribution.
   16   *
   17   * THIS SOFTWARE IS PROVIDED BY BUMP TECHNOLOGIES, INC. ``AS IS'' AND
   18   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
   19   * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
   20   * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BUMP
   21   * TECHNOLOGIES, INC. OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
   22   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   23   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   24   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   25   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   26   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   27   * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
   28   * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   29   *
   30   */
   31 
   32 #include <sys/select.h>
   33 #include <sys/socket.h>
   34 
   35 #include <unistd.h>
   36 
   37 #include "logging.h"
   38 #include "hitch.h"
   39 #include "ocsp.h"
   40 #include "configuration.h"
   41 
   42 /* hitch.c */
   43 extern hitch_config *CONFIG;
   44 extern struct ev_loop *loop;
   45 
   46 void
   47 HOCSP_free(sslstaple **staple)
   48 {
   49     if (*staple == NULL)
   50         return;
   51     free((*staple)->staple);
   52     FREE_OBJ(*staple);
   53     *staple = NULL;
   54 }
   55 
   56 
   57 int
   58 HOCSP_verify(sslctx *sc, OCSP_RESPONSE *resp, double *nextupd)
   59 {
   60     OCSP_BASICRESP *br = NULL;
   61     X509_STORE *store;
   62     STACK_OF(X509) *chain = NULL;
   63     OCSP_CERTID *cid = NULL;
   64     int status = -1, reason;
   65     ASN1_GENERALIZEDTIME *asn_nextupd = NULL;
   66     X509 *issuer;
   67     int i;
   68     int do_verify = sc->staple_vfy;
   69     int verify_flags = OCSP_TRUSTOTHER;
   70 
   71     if (sc->staple_vfy < 0)
   72         do_verify = CONFIG->OCSP_VFY;
   73 
   74     if (!do_verify)
   75         verify_flags |= OCSP_NOVERIFY;
   76 
   77     store = SSL_CTX_get_cert_store(sc->ctx);
   78     AN(store);
   79 
   80 #ifdef SSL_CTRL_GET_CHAIN_CERTS
   81     AN(SSL_CTX_get0_chain_certs(sc->ctx, &chain));
   82 #else
   83     chain = sc->ctx->extra_certs;
   84 #endif
   85     br = OCSP_response_get1_basic(resp);
   86     if (br == NULL) {
   87         ERR("{core} OCSP_response_get1_basic failed (cert: %s)\n",
   88             sc->filename);
   89         goto err;
   90     }
   91     i = OCSP_basic_verify(br, chain, store, verify_flags);
   92     if (i <= 0) {
   93         log_ssl_error(NULL, "{core} Staple verification failed "
   94             "for cert %s\n", sc->filename);
   95         goto err;
   96     }
   97 
   98     issuer = Find_issuer(sc->x509, chain);
   99     if (issuer == NULL) {
  100         ERR("{core} Unable to find issuer for cert %s\n.",
  101             sc->filename);
  102         goto err;
  103     }
  104 
  105     cid = OCSP_cert_to_id(NULL, sc->x509, issuer);
  106     if (cid == NULL) {
  107         ERR("{core} OCSP_cert_to_id failed\n");
  108         goto err;
  109     }
  110 
  111     if (OCSP_resp_find_status(br, cid, &status, &reason,
  112         NULL, NULL, &asn_nextupd) != 1) {
  113         ERR("{core} OCSP_resp_find_status failed: Unable to "
  114             "find OCSP response with a matching certificate id\n");
  115         goto err;
  116     }
  117 
  118     if (status != V_OCSP_CERTSTATUS_GOOD) {
  119         ERR("{core} Certificate %s has status %s\n", sc->filename,
  120             OCSP_cert_status_str(status));
  121         if (status == V_OCSP_CERTSTATUS_REVOKED)
  122             ERR("{core} Certificate %s revocation reason: %s\n",
  123                 sc->filename, OCSP_crl_reason_str(reason));
  124         goto err;
  125     }
  126 
  127     if (asn_nextupd != NULL)
  128         *nextupd = asn1_gentime_parse(asn_nextupd);
  129     else {
  130         *nextupd = -1.0;
  131     }
  132 
  133     OCSP_CERTID_free(cid);
  134     OCSP_BASICRESP_free(br);
  135     return (0);
  136 
  137 err:
  138     if (cid != NULL)
  139         OCSP_CERTID_free(cid);
  140     if (br != NULL)
  141         OCSP_BASICRESP_free(br);
  142     return (1);
  143 }
  144 
  145 #ifndef OPENSSL_NO_TLSEXT
  146 int
  147 HOCSP_staple_cb(SSL *ssl, void *priv)
  148 {
  149     sslstaple *staple;
  150     unsigned char *buf;
  151     CAST_OBJ_NOTNULL(staple, priv, SSLSTAPLE_MAGIC);
  152 
  153     if (staple->nextupd != -1 &&
  154         staple->nextupd < Time_now()) {
  155         return (SSL_TLSEXT_ERR_NOACK);
  156     }
  157 
  158     /* SSL_set_tlsext_status_ocsp_resp will issue a free() on the
  159      * provided input, so we need to pass a copy. */
  160     buf = malloc(staple->len);
  161     AN(buf);
  162     memcpy(buf, staple->staple, staple->len);
  163 
  164     if (SSL_set_tlsext_status_ocsp_resp(ssl,
  165         buf, staple->len) == 1)
  166         return (SSL_TLSEXT_ERR_OK);
  167     else
  168         free(buf);
  169 
  170     return (SSL_TLSEXT_ERR_NOACK);
  171 }
  172 #endif
  173 
  174 
  175 int
  176 HOCSP_init_resp(sslctx *sc, OCSP_RESPONSE *resp)
  177 {
  178     sslstaple *staple = NULL;
  179     int len, i;
  180     unsigned char *tmp, *buf;
  181 
  182     i = OCSP_response_status(resp);
  183     if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
  184         ERR("{core} Error: OCSP response for cert %s has status %s\n",
  185             sc->filename, OCSP_response_status_str(i));
  186         goto err;
  187     }
  188 
  189     len = i2d_OCSP_RESPONSE(resp, NULL);
  190     if (len < 0) {
  191         log_ssl_error(NULL, "{core} i2d_OCSP_RESPONSE");
  192         goto err;
  193     }
  194     buf = malloc(len);
  195     AN(buf);
  196     tmp = buf;
  197     i = i2d_OCSP_RESPONSE(resp, &tmp);
  198     assert(i > 0);
  199 
  200     ALLOC_OBJ(staple, SSLSTAPLE_MAGIC);
  201     AN(staple);
  202     staple->staple = buf;
  203     staple->len = len;
  204 
  205     if (HOCSP_verify(sc, resp, &staple->nextupd) != 0) {
  206         goto err;
  207     }
  208 
  209     if (!SSL_CTX_set_tlsext_status_cb(sc->ctx, HOCSP_staple_cb)) {
  210         ERR("Error configuring status callback.\n");
  211         goto err;
  212     } else if (!SSL_CTX_set_tlsext_status_arg(sc->ctx, staple)) {
  213         ERR("Error setting status callback argument.\n");
  214         goto err;
  215     }
  216 
  217     if (sc->staple != NULL)
  218         HOCSP_free(&sc->staple);
  219     sc->staple = staple;
  220     return (0);
  221 
  222 err:
  223     if (staple != NULL)
  224         HOCSP_free(&staple);
  225     return (1);
  226 }
  227 
  228 
  229 static void
  230 hocsp_stat_cb(struct ev_loop *loop, ev_stat *w, int revents)
  231 {
  232     sslctx *sc;
  233     sslstaple *oldstaple;
  234 
  235     (void) revents;
  236     (void) loop;
  237     CAST_OBJ_NOTNULL(sc, w->data, SSLCTX_MAGIC);
  238 
  239     if (w->attr.st_nlink) {
  240         oldstaple = sc->staple;
  241         sc->staple = NULL;
  242         AN(sc->staple_fn);
  243 
  244         if (HOCSP_init_file(sc->staple_fn, sc, 1) != 0) {
  245             sc->staple = oldstaple;
  246             return;
  247         }
  248 
  249         HOCSP_free(&oldstaple);
  250         LOG("{core} Loaded cached OCSP staple for cert '%s'\n",
  251             sc->filename);
  252     }
  253 }
  254 
  255 void
  256 HOCSP_ev_stat(sslctx *sc)
  257 {
  258     char *fn;
  259     STACK_OF(OPENSSL_STRING) *sk_uri = NULL;
  260     AN(sc->x509);
  261     sk_uri = X509_get1_ocsp(sc->x509);
  262 
  263     if (sk_uri == NULL
  264        || sk_OPENSSL_STRING_num(sk_uri) == 0) {
  265         goto err;
  266     }
  267 
  268     fn = HOCSP_fn(sc->filename);
  269     if (fn == NULL)
  270         goto err;
  271 
  272     free(sc->staple_fn);
  273     sc->staple_fn = fn;
  274     sc->ev_staple = malloc(sizeof *sc->ev_staple);
  275     AN(sc->ev_staple);
  276     sc->ev_staple->data = sc;
  277     ev_stat_init(sc->ev_staple, hocsp_stat_cb, fn, 0);
  278 
  279 err:
  280     if (sk_uri != NULL)
  281         X509_email_free(sk_uri);
  282 }
  283 
  284 static OCSP_REQUEST *
  285 hocsp_mkreq(ocspquery *oq)
  286 {
  287     OCSP_REQUEST *req;
  288     OCSP_CERTID *cid;
  289     STACK_OF(X509) *chain = NULL;
  290     X509 *issuer;
  291 
  292     CHECK_OBJ_NOTNULL(oq, OCSPQUERY_MAGIC);
  293     CHECK_OBJ_NOTNULL(oq->sctx, SSLCTX_MAGIC);
  294 
  295 #ifdef SSL_CTRL_GET_CHAIN_CERTS
  296     AN(SSL_CTX_get0_chain_certs(oq->sctx->ctx, &chain));
  297 #else
  298     chain = oq->sctx->ctx->extra_certs;
  299 #endif
  300     issuer = Find_issuer(oq->sctx->x509, chain);
  301     if (issuer == NULL) {
  302         ERR("{ocsp} Unable to find issuer for cert %s\n.",
  303             oq->sctx->filename);
  304         return (NULL);
  305     }
  306 
  307     cid = OCSP_cert_to_id(NULL, oq->sctx->x509, issuer);
  308     if (cid == NULL) {
  309         ERR("{ocsp} OCSP_cert_to_id failed for cert %s\n",
  310             oq->sctx->filename);
  311         return (NULL);
  312     }
  313 
  314     req = OCSP_REQUEST_new();
  315     if (req == NULL) {
  316         ERR("{ocsp} OCSP_REQUEST_new failed\n");
  317         OCSP_CERTID_free(cid);
  318         return (NULL);
  319     }
  320 
  321     if (OCSP_request_add0_id(req, cid) == NULL) {
  322         ERR("{ocsp} OCSP_request_add0_id failed\n");
  323         OCSP_CERTID_free(cid);
  324         OCSP_REQUEST_free(req);
  325         return (NULL);
  326     }
  327 
  328     return (req);
  329 }
  330 
  331 
  332 /* Save a downloaded staple to the file system.
  333  * Process: OCSP child  */
  334 static int
  335 hocsp_proc_persist(sslctx *sc)
  336 {
  337     char *dstfile = NULL;
  338     int fd = -1;
  339     struct vsb *tmpfn;
  340 
  341     CHECK_OBJ_NOTNULL(sc, SSLCTX_MAGIC);
  342     CHECK_OBJ_NOTNULL(sc->staple, SSLSTAPLE_MAGIC);
  343     dstfile = HOCSP_fn(sc->filename);
  344     if (dstfile == NULL)
  345         return (1);
  346 
  347     (void)umask(027);
  348 
  349     tmpfn = VSB_new_auto();
  350     AN(tmpfn);
  351     VSB_printf(tmpfn, "%s.XXXXXX", dstfile);
  352     VSB_finish(tmpfn);
  353     fd = mkstemp(VSB_data(tmpfn));
  354     if (fd < 0) {
  355         if (errno == EACCES)
  356             ERR("{ocsp} Error: ocsp-dir '%s' is not "
  357                 "writable for the configured user\n",
  358                 CONFIG->OCSP_DIR);
  359         else
  360             ERR("{ocsp} hocsp_proc_persist: mkstemp: %s: %s\n",
  361                 VSB_data(tmpfn), strerror(errno));
  362         goto err;
  363     }
  364 
  365     if (write(fd, sc->staple->staple, sc->staple->len) != sc->staple->len) {
  366         ERR("{ocsp} hocsp_proc_persist: write: %s\n", strerror(errno));
  367         (void) close(fd);
  368         goto err;
  369     }
  370 
  371     if(close(fd) != 0) {
  372         ERR("{ocsp} hocsp_proc_persist: close: %s\n", strerror(errno));
  373         goto err;
  374     }
  375 
  376     if (rename(VSB_data(tmpfn), dstfile) != 0) {
  377         ERR("{ocsp} hocsp_proc_persist: rename: %s: %s\n",
  378             strerror(errno), dstfile);
  379         goto err;
  380     }
  381 
  382     /* worker procs notified via ev_stat (inotify/stat) */
  383 
  384     VSB_delete(tmpfn);
  385     free(dstfile);
  386     return (0);
  387 
  388 err:
  389     unlink(VSB_data(tmpfn));
  390     VSB_delete(tmpfn);
  391     free(dstfile);
  392     return (1);
  393 }
  394 
  395 
  396 int
  397 HOCSP_init_file(const char *ocspfn, sslctx *sc, int is_cached)
  398 {
  399     BIO *bio;
  400     OCSP_RESPONSE *resp;
  401 
  402     if (ocspfn == NULL) {
  403         return (1);
  404     }
  405 
  406     bio = BIO_new_file(ocspfn, "r");
  407     if (bio == NULL) {
  408         if (is_cached)
  409             return (1);
  410         ERR("Error loading status file '%s'\n", ocspfn);
  411         return (1);
  412     }
  413 
  414     resp = d2i_OCSP_RESPONSE_bio(bio, NULL);
  415     BIO_free(bio);
  416     if (resp == NULL) {
  417         ERR("Error parsing OCSP staple in '%s'\n", ocspfn);
  418         return (1);
  419     }
  420 
  421     if (HOCSP_init_resp(sc, resp) != 0)
  422         goto err;
  423 
  424     CHECK_OBJ_NOTNULL(sc->staple, SSLSTAPLE_MAGIC);
  425     OCSP_RESPONSE_free(resp);
  426     return (0);
  427 
  428 err:
  429     if (resp != NULL)
  430         OCSP_RESPONSE_free(resp);
  431     return (1);
  432 }
  433 
  434 
  435 char *
  436 HOCSP_fn(const char *certfn)
  437 {
  438     EVP_MD_CTX *mdctx = NULL;
  439     unsigned char md_val[EVP_MAX_MD_SIZE];
  440     unsigned int i, md_len;
  441     struct vsb *vsb;
  442     char *res;
  443 
  444     if (CONFIG->OCSP_DIR == NULL) {
  445         ERR("{ocsp} Error: OCSP directory not specified.\n");
  446         return (NULL);
  447     }
  448 
  449     mdctx = EVP_MD_CTX_create();
  450     if (mdctx == NULL) {
  451         ERR("{ocsp} EVP_MD_CTX_create failed\n");
  452         goto err;
  453     }
  454     if (EVP_DigestInit_ex(mdctx, EVP_md5(), NULL) != 1) {
  455         ERR("{ocsp} EVP_DigestInit_ex in ocsp_fn() failed\n");
  456         goto err;
  457     }
  458     if (EVP_DigestUpdate(mdctx, certfn, strlen(certfn)) != 1) {
  459         ERR("{ocsp} EVP_DigestUpdate in ocsp_fn() failed\n");
  460         goto err;
  461     }
  462     if (EVP_DigestFinal_ex(mdctx, md_val, &md_len) != 1) {
  463         ERR("{ocsp} EVP_DigestFinal_ex in ocsp_fn() failed\n");
  464         goto err;
  465     }
  466 
  467     EVP_MD_CTX_destroy(mdctx);
  468 
  469     vsb = VSB_new_auto();
  470     AN(vsb);
  471     VSB_cat(vsb, CONFIG->OCSP_DIR);
  472     VSB_putc(vsb, '/');
  473     for (i = 0; i < md_len; i++)
  474         VSB_printf(vsb, "%02x", md_val[i]);
  475     VSB_finish(vsb);
  476     res = strdup(VSB_data(vsb));
  477     AN(res);
  478     VSB_delete(vsb);
  479     return (res);
  480 
  481 err:
  482     if (mdctx != NULL)
  483         EVP_MD_CTX_destroy(mdctx);
  484     return (NULL);
  485 }
  486 
  487 static void hocsp_query_responder(struct ev_loop *loop, ev_timer *w, int revents);
  488 
  489 
  490 /* Start a per-sslctx evloop timer that downloads the OCSP staple.
  491  * Process: OCSP child  */
  492 void
  493 HOCSP_mktask(sslctx *sc, ocspquery *oq, double refresh_hint)
  494 {
  495     double refresh = -1.0;
  496     double tnow;
  497     STACK_OF(OPENSSL_STRING) *sk_uri;
  498 
  499     tnow = Time_now();
  500 
  501     if (sc->staple != NULL) {
  502         CHECK_OBJ_NOTNULL(sc->staple, SSLSTAPLE_MAGIC);
  503         if (sc->staple->nextupd > 0) {
  504             refresh = sc->staple->nextupd - tnow - 600;
  505             if (refresh < 0)
  506                 refresh = 0.0;
  507         } else
  508             refresh = CONFIG->OCSP_REFRESH_INTERVAL;
  509     } else {
  510         AN(sc->x509);
  511         sk_uri = X509_get1_ocsp(sc->x509);
  512         if (sk_uri == NULL || sk_OPENSSL_STRING_num(sk_uri) == 0) {
  513             LOG("{ocsp} Note: No OCSP responder URI found "
  514                 "for cert %s\n", sc->filename);
  515             if (sk_uri != NULL)
  516                 X509_email_free(sk_uri);
  517             return;
  518         }
  519         /* schedule for immediate retrieval */
  520         X509_email_free(sk_uri);
  521         refresh = 0.0;
  522     }
  523 
  524     if (refresh < refresh_hint)
  525         refresh = refresh_hint;
  526 
  527     if (oq == NULL)
  528         ALLOC_OBJ(oq, OCSPQUERY_MAGIC);
  529 
  530     CHECK_OBJ_NOTNULL(oq, OCSPQUERY_MAGIC);
  531     oq->sctx = sc;
  532 
  533     assert(refresh >= 0.0);
  534     ev_timer_init(&oq->ev_t_refresh,
  535         hocsp_query_responder, refresh, 0.);
  536     oq->ev_t_refresh.data = oq;
  537     ev_timer_start(loop, &oq->ev_t_refresh);
  538 
  539     LOG("{ocsp} Refresh of OCSP staple for %s scheduled in "
  540         "%.0lf seconds\n", sc->filename, refresh);
  541 }
  542 
  543 
  544 
  545 static void
  546 hocsp_query_responder(struct ev_loop *loop, ev_timer *w, int revents)
  547 {
  548     ocspquery *oq;
  549     OCSP_REQUEST *req = NULL;
  550     OCSP_REQ_CTX *rctx = NULL;
  551     STACK_OF(OPENSSL_STRING) *sk_uri;
  552     char *host = NULL, *port = NULL, *path = NULL;
  553     int https = 0;
  554     BIO *cbio = NULL, *sbio;
  555     SSL_CTX *ctx = NULL;
  556     OCSP_RESPONSE *resp = NULL;
  557     double resp_tmo;
  558     fd_set fds;
  559     struct timeval tv;
  560     int n, fd;
  561     double refresh_hint = 60;
  562 
  563     (void) loop;
  564     (void) revents;
  565 
  566     CAST_OBJ_NOTNULL(oq, w->data, OCSPQUERY_MAGIC);
  567 
  568     sk_uri = X509_get1_ocsp(oq->sctx->x509);
  569     AN(sk_uri);
  570 
  571     AN(OCSP_parse_url(sk_OPENSSL_STRING_value(sk_uri, 0),
  572         &host, &port, &path, &https));
  573     X509_email_free(sk_uri);
  574 
  575     req = hocsp_mkreq(oq);
  576     if (req == NULL) {
  577         /* If we weren't able to create a request, there is no
  578          * use in scheduling a retry. */
  579         FREE_OBJ(oq);
  580         goto err;
  581     }
  582 
  583     /* printf("host: %s port: %s path: %s ssl: %d\n", */
  584     /*     host, port, path, https); */
  585 
  586     cbio = BIO_new_connect(host);
  587     if (cbio == NULL) {
  588         refresh_hint = 60;
  589         goto retry;
  590     }
  591 
  592     if (port == NULL) {
  593         if (https)
  594             port = "443";
  595         else
  596             port = "80";
  597     }
  598     AN(BIO_set_conn_port(cbio, port));
  599 
  600     if (https) {
  601         ctx = SSL_CTX_new(SSLv23_client_method());
  602         AN(ctx);
  603         SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
  604         SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3);
  605         SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
  606         sbio = BIO_new_ssl(ctx, 1);
  607         if (sbio == NULL) {
  608             ERR("{ocsp} BIO_new_ssl failed: %s\n", strerror(errno));
  609             refresh_hint = 60;
  610             goto retry;
  611         }
  612         cbio = BIO_push(sbio, cbio);
  613         AN(cbio);
  614     }
  615 
  616     /* set non-blocking */
  617     BIO_set_nbio(cbio, 1);
  618     n = BIO_do_connect(cbio);
  619     if (n <= 0 && !BIO_should_retry(cbio)) {
  620         ERR("{ocsp} Error connecting to %s:%s\n", host, port);
  621         refresh_hint = 300;
  622         goto retry;
  623     }
  624 
  625     assert(BIO_get_fd(cbio, &fd) >= 0);
  626 
  627     if (n <= 0) {
  628         FD_ZERO(&fds);
  629         FD_SET(fd, &fds);
  630         tv.tv_sec = CONFIG->OCSP_CONN_TMO;
  631         tv.tv_usec = (CONFIG->OCSP_CONN_TMO - tv.tv_sec) * 1e6;
  632         n = select(fd + 1, NULL, (void *) &fds, NULL, &tv);
  633         if (n == 0) {
  634             /* connect timeout */
  635             ERR("{ocsp} Error: Connection to %s:%s timed out. "
  636                 "Hit parameter 'ocsp-connect-tmo"
  637                 " [current value: %.3fs]\n",
  638                 host, port, CONFIG->OCSP_CONN_TMO);
  639             refresh_hint = 300;
  640             goto retry;
  641         } else if (n < 0) {
  642             ERR("{ocsp} Error: Connecting to %s:%s failed: "
  643                 "select: %s\n",
  644                 host, port, strerror(errno));
  645             refresh_hint = 300;
  646             goto retry;
  647         }
  648     }
  649 
  650     rctx = OCSP_sendreq_new(cbio, path, NULL, 0);
  651     if (rctx == NULL) {
  652         ERR("{ocsp} OCSP_sendreq_new failed\n");
  653         refresh_hint = 60;
  654         goto retry;
  655     }
  656     if (OCSP_REQ_CTX_add1_header(rctx, "Host", host) == 0) {
  657         ERR("{ocsp} OCSP_REQ_CTX_add1_header failed\n");
  658         refresh_hint = 60;
  659         goto retry;
  660     }
  661     if (OCSP_REQ_CTX_set1_req(rctx, req) == 0) {
  662         ERR("{ocsp} OCSP_REQ_CTX_set1_req failed\n");
  663         refresh_hint = 60;
  664         goto retry;
  665     }
  666 
  667     resp_tmo = Time_now() + CONFIG->OCSP_RESP_TMO;
  668     while (1) {
  669         double tnow;
  670         n = OCSP_sendreq_nbio(&resp, rctx);
  671         if (n == 0) {
  672             /* this is an error, and we can't continue */
  673             ERR("{ocsp} OCSP_sendreq_nbio failed for %s:%s.\n",
  674                 host, port);
  675             refresh_hint = 300;
  676             goto retry;
  677         } else if (n == 1) {
  678             /* complete */
  679             break;
  680         }
  681 
  682         FD_ZERO(&fds);
  683         FD_SET(fd, &fds);
  684 
  685         tnow = Time_now();
  686         tv.tv_sec = resp_tmo - tnow;
  687         tv.tv_usec = ((resp_tmo - tnow) - tv.tv_sec) * 1e6;
  688 
  689         if (BIO_should_read(cbio))
  690             n = select(fd + 1, (void *) &fds, NULL, NULL, &tv);
  691         else if (BIO_should_write(cbio))
  692             n = select(fd + 1, NULL, (void *) &fds, NULL, &tv);
  693         else {
  694             /* BIO_should_io_special? */
  695             refresh_hint = 300;
  696             goto retry;
  697         }
  698 
  699         if (n == -1) {
  700             if (errno == EINTR)
  701                 continue;
  702             ERR("{ocsp} Error: Transmission failed:"
  703                 " select: %s\n", strerror(errno));
  704             refresh_hint = 300;
  705             goto retry;
  706         }
  707 
  708         if (n == 0) {
  709             /* timeout */
  710             ERR("{ocsp} Error: Transmission timeout for %s:%s. "
  711                 "Consider increasing parameter 'ocsp-resp-tmo'"
  712                 " [current value: %.3fs]\n",
  713                 host, port, CONFIG->OCSP_RESP_TMO);
  714             refresh_hint = 300;
  715             goto retry;
  716         }
  717     }
  718 
  719     if (resp == NULL) {
  720         /* fetch failed.  Retry later. */
  721         refresh_hint = 600.0;
  722     } else {
  723         if (HOCSP_init_resp(oq->sctx, resp) == 0) {
  724             LOG("{ocsp} Retrieved new staple for cert %s\n",
  725                 oq->sctx->filename);
  726             if (hocsp_proc_persist(oq->sctx) != 0) {
  727                 refresh_hint = 300;
  728                 goto retry;
  729             }
  730         } else {
  731             refresh_hint = 300;
  732             goto retry;
  733         }
  734     }
  735 
  736 retry:
  737     HOCSP_mktask(oq->sctx, oq, refresh_hint);
  738 err:
  739     if (rctx)
  740         OCSP_REQ_CTX_free(rctx);
  741     if (req)
  742         OCSP_REQUEST_free(req);
  743     if (resp)
  744         OCSP_RESPONSE_free(resp);
  745     if (cbio)
  746         BIO_free_all(cbio);
  747     if (ctx)
  748         SSL_CTX_free(ctx);
  749 }
  750