/* read/write callback that sends the requests and reads the ocsp response */ void ocsp_callback(int fd, short event, void *arg) { struct iked_ocsp *ocsp = arg; struct iked_socket *sock = ocsp->ocsp_sock; OCSP_RESPONSE *resp = NULL; /* * Only call OCSP_sendreq_nbio() if should_read/write is * either not requested or read/write can be called. */ if ((!BIO_should_read(ocsp->ocsp_cbio) || (event & EV_READ)) && (!BIO_should_write(ocsp->ocsp_cbio) || (event & EV_WRITE)) && OCSP_sendreq_nbio(&resp, ocsp->ocsp_req_ctx) != -1 ) { ocsp_parse_response(ocsp, resp); return; } if (BIO_should_read(ocsp->ocsp_cbio)) event_set(&sock->sock_ev, sock->sock_fd, EV_READ, ocsp_callback, ocsp); else if (BIO_should_write(ocsp->ocsp_cbio)) event_set(&sock->sock_ev, sock->sock_fd, EV_WRITE, ocsp_callback, ocsp); event_add(&sock->sock_ev, NULL); }
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; }
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; }
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; }