OCSP_RESPONSE *OCSP_sendreq_bio (BIO * b, char *path, OCSP_REQUEST * req) { OCSP_RESPONSE *resp = NULL; OCSP_REQ_CTX *ctx; int rv; ctx = OCSP_sendreq_new (b, path, req, -1); if (!ctx) return NULL; do { rv = OCSP_sendreq_nbio (&resp, ctx); } while ((rv == -1) && BIO_should_retry (b)); OCSP_REQ_CTX_free (ctx); if (rv) return resp; return NULL; }
OCSP_REQ_CTX *OCSP_sendreq_new (BIO * io, char *path, OCSP_REQUEST * req, int maxline) { static const char post_hdr[] = "POST %s HTTP/1.0\r\n"; OCSP_REQ_CTX *rctx; rctx = OPENSSL_malloc (sizeof (OCSP_REQ_CTX)); if (!rctx) return NULL; rctx->state = OHS_ERROR; rctx->mem = BIO_new (BIO_s_mem ()); rctx->io = io; rctx->asn1_len = 0; if (maxline > 0) rctx->iobuflen = maxline; else rctx->iobuflen = OCSP_MAX_LINE_LEN; rctx->iobuf = OPENSSL_malloc (rctx->iobuflen); if (!rctx->mem || !rctx->iobuf) goto err; if (!path) path = "/"; if (BIO_printf (rctx->mem, post_hdr, path) <= 0) goto err; if (req && !OCSP_REQ_CTX_set1_req (rctx, req)) goto err; return rctx; err: OCSP_REQ_CTX_free (rctx); return NULL; }
static OCSP_RESPONSE *ocsp_get_response(CLI *c, OCSP_REQUEST *req) { BIO *bio=NULL; OCSP_REQ_CTX *req_ctx=NULL; OCSP_RESPONSE *resp=NULL; int err; /* connect specified OCSP server (responder) */ c->fd=s_socket(c->opt->ocsp_addr.sa.sa_family, SOCK_STREAM, 0, 1, "OCSP: socket (auth_user)"); if(c->fd<0) goto cleanup; if(connect_blocking(c, &c->opt->ocsp_addr, addr_len(&c->opt->ocsp_addr))) goto cleanup; bio=BIO_new_fd(c->fd, BIO_NOCLOSE); if(!bio) goto cleanup; s_log(LOG_DEBUG, "OCSP: server connected"); /* OCSP protocol communication loop */ req_ctx=OCSP_sendreq_new(bio, c->opt->ocsp_path, req, -1); if(!req_ctx) { sslerror("OCSP: OCSP_sendreq_new"); goto cleanup; } while(OCSP_sendreq_nbio(&resp, req_ctx)==-1) { s_poll_init(c->fds); s_poll_add(c->fds, c->fd, BIO_should_read(bio), BIO_should_write(bio)); err=s_poll_wait(c->fds, c->opt->timeout_busy, 0); if(err==-1) sockerror("OCSP: s_poll_wait"); if(err==0) s_log(LOG_INFO, "OCSP: s_poll_wait: TIMEOUTbusy exceeded"); if(err<=0) goto cleanup; } /* s_log(LOG_DEBUG, "OCSP: context state: 0x%x", *(int *)req_ctx); */ /* http://www.mail-archive.com/[email protected]/msg61691.html */ if(!resp) { if(ERR_peek_error()) sslerror("OCSP: OCSP_sendreq_nbio"); else /* OpenSSL error: OCSP_sendreq_nbio does not use OCSPerr */ s_log(LOG_ERR, "OCSP: OCSP_sendreq_nbio: OpenSSL internal error"); } cleanup: if(req_ctx) OCSP_REQ_CTX_free(req_ctx); if(bio) BIO_free_all(bio); if(c->fd>=0) { closesocket(c->fd); c->fd=-1; /* avoid double close on cleanup */ } return resp; }
OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, const char *path, OCSP_REQUEST *req, int maxline) { OCSP_REQ_CTX *rctx = NULL; rctx = OCSP_REQ_CTX_new(io, maxline); if (!rctx) return NULL; if (!OCSP_REQ_CTX_http(rctx, "POST", path)) goto err; if (req && !OCSP_REQ_CTX_set1_req(rctx, req)) goto err; return rctx; err: OCSP_REQ_CTX_free(rctx); return NULL; }
OCSP_REQ_CTX *OCSP_REQ_CTX_new(BIO *io, int maxline) { OCSP_REQ_CTX *rctx; rctx = OPENSSL_malloc(sizeof(OCSP_REQ_CTX)); if (!rctx) return NULL; rctx->state = OHS_ERROR; rctx->max_resp_len = OCSP_MAX_RESP_LENGTH; rctx->mem = BIO_new(BIO_s_mem()); rctx->io = io; rctx->asn1_len = 0; if (maxline > 0) rctx->iobuflen = maxline; else rctx->iobuflen = OCSP_MAX_LINE_LEN; rctx->iobuf = OPENSSL_malloc(rctx->iobuflen); if (!rctx->iobuf || !rctx->mem) { OCSP_REQ_CTX_free(rctx); return NULL; } return rctx; }
/* free ocsp query context */ void ocsp_free(struct iked_ocsp *ocsp) { if (ocsp != NULL) { if (ocsp->ocsp_sock != NULL) { close(ocsp->ocsp_sock->sock_fd); free(ocsp->ocsp_sock); } if (ocsp->ocsp_cbio != NULL) BIO_free_all(ocsp->ocsp_cbio); if (ocsp->ocsp_id != NULL) OCSP_CERTID_free(ocsp->ocsp_id); /* XXX not sure about ownership XXX */ if (ocsp->ocsp_req_ctx != NULL) OCSP_REQ_CTX_free(ocsp->ocsp_req_ctx); else if (ocsp->ocsp_req != NULL) OCSP_REQUEST_free(ocsp->ocsp_req); free(ocsp); } }
NOEXPORT OCSP_RESPONSE *ocsp_get_response(CLI *c, OCSP_REQUEST *req, char *url) { BIO *bio=NULL; OCSP_REQ_CTX *req_ctx=NULL; OCSP_RESPONSE *resp=NULL; int err; char *host=NULL, *port=NULL, *path=NULL; SOCKADDR_UNION addr; int ssl; /* parse the OCSP URL */ if(!OCSP_parse_url(url, &host, &port, &path, &ssl)) { s_log(LOG_ERR, "OCSP: Failed to parse the OCSP URL"); goto cleanup; } if(ssl) { s_log(LOG_ERR, "OCSP: SSL not supported for OCSP" " - additional stunnel service needs to be defined"); goto cleanup; } memset(&addr, 0, sizeof addr); addr.in.sin_family=AF_INET; if(!hostport2addr(&addr, host, port)) { s_log(LOG_ERR, "OCSP: Failed to resolve the OCSP server address"); goto cleanup; } /* connect specified OCSP server (responder) */ c->fd=s_socket(addr.sa.sa_family, SOCK_STREAM, 0, 1, "OCSP: socket"); if(c->fd<0) goto cleanup; if(s_connect(c, &addr, addr_len(&addr))) goto cleanup; bio=BIO_new_fd(c->fd, BIO_NOCLOSE); if(!bio) goto cleanup; s_log(LOG_DEBUG, "OCSP: response retrieved"); /* OCSP protocol communication loop */ req_ctx=OCSP_sendreq_new(bio, path, req, -1); if(!req_ctx) { sslerror("OCSP: OCSP_sendreq_new"); goto cleanup; } while(OCSP_sendreq_nbio(&resp, req_ctx)==-1) { s_poll_init(c->fds); s_poll_add(c->fds, c->fd, BIO_should_read(bio), BIO_should_write(bio)); err=s_poll_wait(c->fds, c->opt->timeout_busy, 0); if(err==-1) sockerror("OCSP: s_poll_wait"); if(err==0) s_log(LOG_INFO, "OCSP: s_poll_wait: TIMEOUTbusy exceeded"); if(err<=0) goto cleanup; } #if 0 s_log(LOG_DEBUG, "OCSP: context state: 0x%x", *(int *)req_ctx); #endif /* http://www.mail-archive.com/[email protected]/msg61691.html */ if(resp) { s_log(LOG_DEBUG, "OCSP: request completed"); } else { if(ERR_peek_error()) sslerror("OCSP: OCSP_sendreq_nbio"); else /* OpenSSL error: OCSP_sendreq_nbio does not use OCSPerr */ s_log(LOG_ERR, "OCSP: OCSP_sendreq_nbio: OpenSSL internal error"); } cleanup: if(req_ctx) OCSP_REQ_CTX_free(req_ctx); if(bio) BIO_free_all(bio); if(c->fd>=0) { closesocket(c->fd); c->fd=-1; /* avoid double close on cleanup */ } if(host) OPENSSL_free(host); if(port) OPENSSL_free(port); if(path) OPENSSL_free(path); return resp; }