/* validate the certifcate stored in 'data' by querying the ocsp-responder */ int ocsp_validate_cert(struct iked *env, struct iked_static_id *id, void *data, size_t len, struct iked_sahdr sh, uint8_t type) { struct iked_ocsp_entry *ioe; struct iked_ocsp *ocsp; BIO *rawcert = NULL, *bissuer = NULL; X509 *cert = NULL, *issuer = NULL; if ((ioe = calloc(1, sizeof(*ioe))) == NULL) return (-1); if ((ocsp = calloc(1, sizeof(*ocsp))) == NULL) { free(ioe); return (-1); } ocsp->ocsp_env = env; ocsp->ocsp_sh = sh; ocsp->ocsp_type = type; if ((rawcert = BIO_new_mem_buf(data, len)) == NULL || (cert = d2i_X509_bio(rawcert, NULL)) == NULL || (bissuer = BIO_new_file(IKED_OCSP_ISSUER, "r")) == NULL || (issuer = PEM_read_bio_X509(bissuer, NULL, NULL, NULL)) == NULL || (ocsp->ocsp_cbio = BIO_new(BIO_s_socket())) == NULL || (ocsp->ocsp_req = OCSP_REQUEST_new()) == NULL || !(ocsp->ocsp_id = OCSP_cert_to_id(NULL, cert, issuer)) || !OCSP_request_add0_id(ocsp->ocsp_req, ocsp->ocsp_id)) goto err; BIO_free(rawcert); BIO_free(bissuer); X509_free(cert); X509_free(issuer); ioe->ioe_ocsp = ocsp; TAILQ_INSERT_TAIL(&env->sc_ocsp, ioe, ioe_entry); /* request connection to ocsp-responder */ proc_compose_imsg(&env->sc_ps, PROC_PARENT, -1, IMSG_OCSP_FD, -1, NULL, 0); return (0); err: ca_sslerror(__func__); free(ioe); if (rawcert != NULL) BIO_free(rawcert); if (cert != NULL) X509_free(cert); if (bissuer != NULL) BIO_free(bissuer); if (issuer != NULL) X509_free(issuer); ocsp_validate_finish(ocsp, 0); /* failed */ return (-1); }
/* * OCSP::Resquest */ static VALUE ossl_ocspreq_alloc(VALUE klass) { OCSP_REQUEST *req; VALUE obj; if (!(req = OCSP_REQUEST_new())) ossl_raise(eOCSPError, NULL); WrapOCSPReq(klass, obj, req); return obj; }
/* Create an OCSP request for the given certificate; returning the * certificate ID in *certid and *issuer on success. Returns the * request object on success, or NULL on error. */ static OCSP_REQUEST *create_request(X509_STORE_CTX *ctx, X509 *cert, OCSP_CERTID **certid, server_rec *s, apr_pool_t *p, SSLSrvConfigRec *sc) { OCSP_REQUEST *req = OCSP_REQUEST_new(); *certid = OCSP_cert_to_id(NULL, cert, ctx->current_issuer); if (!*certid || !OCSP_request_add0_id(req, *certid)) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01921) "could not retrieve certificate id"); ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); return NULL; } if (sc->server->ocsp_use_request_nonce != FALSE) { OCSP_request_add1_nonce(req, 0, -1); } return req; }
int SslOcspStapling::getRequestData(unsigned char *pReqData) { int len = -1; OCSP_REQUEST *ocsp; OCSP_CERTID *id; if (m_pCertId == NULL) return LS_FAIL; ocsp = OCSP_REQUEST_new(); if (ocsp == NULL) return LS_FAIL; id = OCSP_CERTID_dup(m_pCertId); if (OCSP_request_add0_id(ocsp, id) != NULL) { len = i2d_OCSP_REQUEST(ocsp, &pReqData); if (len > 0) *pReqData = 0; } OCSP_REQUEST_free(ocsp); return len; }
/* * This function sends a OCSP request to a defined OCSP responder * and checks the OCSP response for correctness. */ static int ocsp_check(X509_STORE *store, X509 *issuer_cert, X509 *client_cert, EAP_TLS_CONF *conf) { OCSP_CERTID *certid; OCSP_REQUEST *req; OCSP_RESPONSE *resp; OCSP_BASICRESP *bresp = NULL; char *host = NULL; char *port = NULL; char *path = NULL; int use_ssl = -1; BIO *cbio; int ocsp_ok; int status; /* * Create OCSP Request */ certid = OCSP_cert_to_id(NULL, client_cert, issuer_cert); req = OCSP_REQUEST_new(); OCSP_request_add0_id(req, certid); OCSP_request_add1_nonce(req, NULL, 8); /* * Send OCSP Request and get OCSP Response */ /* Get OCSP responder URL */ if(conf->ocsp_override_url) { OCSP_parse_url(conf->ocsp_url, &host, &port, &path, &use_ssl); } else { ocsp_parse_cert_url(client_cert, &host, &port, &path, &use_ssl); } DEBUG2("[ocsp] --> Responder URL = http://%s:%s%s", host, port, path); /* Setup BIO socket to OCSP responder */ cbio = BIO_new_connect(host); BIO_set_conn_port(cbio, port); BIO_do_connect(cbio); /* Send OCSP request and wait for response */ resp = OCSP_sendreq_bio(cbio, path, req); if(resp==0) { radlog(L_ERR, "Error: Couldn't get OCSP response"); ocsp_ok = 0; goto ocsp_end; } /* Verify OCSP response */ status = OCSP_response_status(resp); if(status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { radlog(L_ERR, "Error: OCSP response status: %s", OCSP_response_status_str(status)); ocsp_ok = 0; goto ocsp_end; } bresp = OCSP_response_get1_basic(resp); if(OCSP_check_nonce(req, bresp)!=1) { radlog(L_ERR, "Error: OCSP response has wrong nonce value"); ocsp_ok = 0; goto ocsp_end; } if(OCSP_basic_verify(bresp, NULL, store, 0)!=1){ radlog(L_ERR, "Error: Couldn't verify OCSP basic response"); ocsp_ok = 0; goto ocsp_end; } ocsp_ok = 1; ocsp_end: /* Free OCSP Stuff */ OCSP_REQUEST_free(req); OCSP_RESPONSE_free(resp); free(host); free(port); free(path); BIO_free_all(cbio); OCSP_BASICRESP_free(bresp); if (ocsp_ok) { DEBUG2("[ocsp] --> Certificate is valid!"); } else { DEBUG2("[ocsp] --> Certificate has been expired/revoked!"); } return ocsp_ok; }
static ngx_int_t ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx) { int len; u_char *p; uintptr_t escape; ngx_str_t binary, base64; ngx_buf_t *b; OCSP_CERTID *id; OCSP_REQUEST *ocsp; ocsp = OCSP_REQUEST_new(); if (ocsp == NULL) { ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0, "OCSP_REQUEST_new() failed"); return NGX_ERROR; } id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer); if (id == NULL) { ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0, "OCSP_cert_to_id() failed"); goto failed; } if (OCSP_request_add0_id(ocsp, id) == NULL) { ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0, "OCSP_request_add0_id() failed"); OCSP_CERTID_free(id); goto failed; } len = i2d_OCSP_REQUEST(ocsp, NULL); if (len <= 0) { ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0, "i2d_OCSP_REQUEST() failed"); goto failed; } binary.len = len; binary.data = ngx_palloc(ctx->pool, len); if (binary.data == NULL) { goto failed; } p = binary.data; len = i2d_OCSP_REQUEST(ocsp, &p); if (len <= 0) { ngx_ssl_error(NGX_LOG_EMERG, ctx->log, 0, "i2d_OCSP_REQUEST() failed"); goto failed; } base64.len = ngx_base64_encoded_length(binary.len); base64.data = ngx_palloc(ctx->pool, base64.len); if (base64.data == NULL) { goto failed; } ngx_encode_base64(&base64, &binary); escape = ngx_escape_uri(NULL, base64.data, base64.len, NGX_ESCAPE_URI_COMPONENT); ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0, "ssl ocsp request length %z, escape %d", base64.len, (int) escape); len = sizeof("GET ") - 1 + ctx->uri.len + sizeof("/") - 1 + base64.len + 2 * escape + sizeof(" HTTP/1.0" CRLF) - 1 + sizeof("Host: ") - 1 + ctx->host.len + sizeof(CRLF) - 1 + sizeof(CRLF) - 1; b = ngx_create_temp_buf(ctx->pool, len); if (b == NULL) { goto failed; } p = b->last; p = ngx_cpymem(p, "GET ", sizeof("GET ") - 1); p = ngx_cpymem(p, ctx->uri.data, ctx->uri.len); if (ctx->uri.data[ctx->uri.len - 1] != '/') { *p++ = '/'; } if (escape == 0) { p = ngx_cpymem(p, base64.data, base64.len); } else { p = (u_char *) ngx_escape_uri(p, base64.data, base64.len, NGX_ESCAPE_URI_COMPONENT); } p = ngx_cpymem(p, " HTTP/1.0" CRLF, sizeof(" HTTP/1.0" CRLF) - 1); p = ngx_cpymem(p, "Host: ", sizeof("Host: ") - 1); p = ngx_cpymem(p, ctx->host.data, ctx->host.len); *p++ = CR; *p++ = LF; /* add "\r\n" at the header end */ *p++ = CR; *p++ = LF; b->last = p; ctx->request = b; OCSP_REQUEST_free(ocsp); return NGX_OK; failed: OCSP_REQUEST_free(ocsp); return NGX_ERROR; }
const char* bud_context_get_ocsp_req(bud_context_t* context, size_t* size, char** ocsp_request, size_t* ocsp_request_len) { STACK_OF(OPENSSL_STRING)* urls; OCSP_REQUEST* req; OCSP_CERTID* id; char* encoded; unsigned char* pencoded; size_t encoded_len; urls = NULL; id = NULL; encoded = NULL; /* Cached url */ if (context->ocsp_url != NULL) goto has_url; urls = X509_get1_ocsp(context->cert); if (urls == NULL) goto done; context->ocsp_url = sk_OPENSSL_STRING_pop(urls); context->ocsp_url_len = strlen(context->ocsp_url); has_url: if (context->ocsp_url == NULL) goto done; id = OCSP_CERTID_dup(context->ocsp_id); if (id == NULL) goto done; /* Create request */ req = OCSP_REQUEST_new(); if (req == NULL) goto done; if (!OCSP_request_add0_id(req, id)) goto done; id = NULL; encoded_len = i2d_OCSP_REQUEST(req, NULL); encoded = malloc(encoded_len); if (encoded == NULL) goto done; pencoded = (unsigned char*) encoded; i2d_OCSP_REQUEST(req, &pencoded); OCSP_REQUEST_free(req); *ocsp_request = encoded; *ocsp_request_len = encoded_len; encoded = NULL; done: if (id != NULL) OCSP_CERTID_free(id); if (urls != NULL) X509_email_free(urls); if (encoded != NULL) free(encoded); *size = context->ocsp_url_len; return context->ocsp_url; }
int myproxy_ocsp_verify(X509 *cert, X509 *issuer) { BIO *bio = 0; int rc, reason, ssl, status; char *host = 0, *path = 0, *port = 0, *certdir = 0; char *aiaocspurl = 0, *chosenurl = 0; SSL_CTX *ctx = 0; X509_LOOKUP *lookup = NULL; X509_STORE *store = 0; OCSP_CERTID *id; OCSP_REQUEST *req = 0; OCSP_RESPONSE *resp = 0; OCSP_BASICRESP *basic = 0; myproxy_ocspresult_t result; ASN1_GENERALIZEDTIME *producedAt, *thisUpdate, *nextUpdate; globus_result_t res; if (!policy && !responder_url) { result = MYPROXY_OCSPRESULT_ERROR_NOTCONFIGURED; goto end; } result = MYPROXY_OCSPRESULT_ERROR_UNKNOWN; if (policy && strstr(policy, "aia")) { aiaocspurl = myproxy_get_aia_ocsp_uri(cert); } if (!responder_url && !aiaocspurl) { result = MYPROXY_OCSPRESULT_ERROR_NOTCONFIGURED; goto end; } chosenurl = aiaocspurl ? aiaocspurl : responder_url; if (!OCSP_parse_url(chosenurl, &host, &port, &path, &ssl)) { result = MYPROXY_OCSPRESULT_ERROR_BADOCSPADDRESS; goto end; } myproxy_log("querying OCSP responder at %s", chosenurl); if (!(req = OCSP_REQUEST_new())) { result = MYPROXY_OCSPRESULT_ERROR_OUTOFMEMORY; goto end; } id = OCSP_cert_to_id(0, cert, issuer); if (!id || !OCSP_request_add0_id(req, id)) goto end; if (usenonce) OCSP_request_add1_nonce(req, 0, -1); /* sign the request */ if (sign_cert && sign_key && !OCSP_request_sign(req, sign_cert, sign_key, EVP_sha1(), 0, 0)) { result = MYPROXY_OCSPRESULT_ERROR_SIGNFAILURE; goto end; } /* setup GSI context */ store=X509_STORE_new(); lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); if (lookup == NULL) { result = MYPROXY_OCSPRESULT_ERROR_OUTOFMEMORY; goto end; } res = GLOBUS_GSI_SYSCONFIG_GET_CERT_DIR(&certdir); if (res != GLOBUS_SUCCESS) { verror_put_string("failed to find GSI CA cert directory"); globus_error_to_verror(res); goto end; } X509_LOOKUP_add_dir(lookup, certdir, X509_FILETYPE_PEM); ctx = SSL_CTX_new(SSLv23_client_method()); if (ctx == NULL) { result = MYPROXY_OCSPRESULT_ERROR_OUTOFMEMORY; goto end; } SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2); SSL_CTX_set_cert_store(ctx, store); SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL); /* establish a connection to the OCSP responder */ if (!(bio = my_connect(host, atoi(port), ssl, &ctx))) { result = MYPROXY_OCSPRESULT_ERROR_CONNECTFAILURE; goto end; } /* send the request and get a response */ resp = OCSP_sendreq_bio(bio, path, req); if ((rc = OCSP_response_status(resp)) != OCSP_RESPONSE_STATUS_SUCCESSFUL) { switch (rc) { case OCSP_RESPONSE_STATUS_MALFORMEDREQUEST: result = MYPROXY_OCSPRESULT_ERROR_MALFORMEDREQUEST; break; case OCSP_RESPONSE_STATUS_INTERNALERROR: result = MYPROXY_OCSPRESULT_ERROR_INTERNALERROR; break; case OCSP_RESPONSE_STATUS_TRYLATER: result = MYPROXY_OCSPRESULT_ERROR_TRYLATER; break; case OCSP_RESPONSE_STATUS_SIGREQUIRED: result = MYPROXY_OCSPRESULT_ERROR_SIGREQUIRED; break; case OCSP_RESPONSE_STATUS_UNAUTHORIZED: result = MYPROXY_OCSPRESULT_ERROR_UNAUTHORIZED; break; } goto end; } /* verify the response */ result = MYPROXY_OCSPRESULT_ERROR_INVALIDRESPONSE; if (!(basic = OCSP_response_get1_basic(resp))) goto end; if (usenonce && OCSP_check_nonce(req, basic) <= 0) goto end; if (!responder_cert || (rc = OCSP_basic_verify(basic, responder_cert, store, OCSP_TRUSTOTHER)) <= 0) if ((rc = OCSP_basic_verify(basic, NULL, store, 0)) <= 0) goto end; if (!OCSP_resp_find_status(basic, id, &status, &reason, &producedAt, &thisUpdate, &nextUpdate)) goto end; if (!OCSP_check_validity(thisUpdate, nextUpdate, skew, maxage)) goto end; /* All done. Set the return code based on the status from the response. */ if (status == V_OCSP_CERTSTATUS_REVOKED) { result = MYPROXY_OCSPRESULT_CERTIFICATE_REVOKED; myproxy_log("OCSP status revoked!"); } else { result = MYPROXY_OCSPRESULT_CERTIFICATE_VALID; myproxy_log("OCSP status valid"); } end: if (result < 0 && result != MYPROXY_OCSPRESULT_ERROR_NOTCONFIGURED) { ssl_error_to_verror(); myproxy_log("OCSP check failed"); myproxy_log_verror(); } if (bio) BIO_free_all(bio); if (host) OPENSSL_free(host); if (port) OPENSSL_free(port); if (path) OPENSSL_free(path); if (req) OCSP_REQUEST_free(req); if (resp) OCSP_RESPONSE_free(resp); if (basic) OCSP_BASICRESP_free(basic); if (ctx) SSL_CTX_free(ctx); /* this does X509_STORE_free(store) */ if (certdir) free(certdir); if (aiaocspurl) free(aiaocspurl); return result; }
static int ocsp_check(CLI *c, X509_STORE_CTX *callback_ctx) { int error, retval=0; SOCKADDR_UNION addr; X509 *cert; X509 *issuer=NULL; OCSP_CERTID *certID; BIO *bio=NULL; OCSP_REQUEST *request=NULL; OCSP_RESPONSE *response=NULL; OCSP_BASICRESP *basicResponse=NULL; ASN1_GENERALIZEDTIME *revoked_at=NULL, *this_update=NULL, *next_update=NULL; int status, reason; /* connect specified OCSP server (responder) */ c->fd=s_socket(c->opt->ocsp_addr.addr[0].sa.sa_family, SOCK_STREAM, 0, 0, "OCSP: socket (auth_user)"); if(c->fd<0) return 0; /* reject connection */ memcpy(&addr, &c->opt->ocsp_addr.addr[0], sizeof addr); if(connect_blocking(c, &addr, addr_len(addr))) goto cleanup; s_log(LOG_DEBUG, "OCSP: server connected"); /* get current certificate ID */ cert=X509_STORE_CTX_get_current_cert(callback_ctx); /* get current cert */ if(X509_STORE_CTX_get1_issuer(&issuer, callback_ctx, cert)!=1) { sslerror("OCSP: X509_STORE_CTX_get1_issuer"); goto cleanup; } certID=OCSP_cert_to_id(0, cert, issuer); if(!certID) { sslerror("OCSP: OCSP_cert_to_id"); goto cleanup; } /* build request */ request=OCSP_REQUEST_new(); if(!request) { sslerror("OCSP: OCSP_REQUEST_new"); goto cleanup; } if(!OCSP_request_add0_id(request, certID)) { sslerror("OCSP: OCSP_request_add0_id"); goto cleanup; } OCSP_request_add1_nonce(request, 0, -1); /* send the request and get a response */ /* FIXME: this code won't work with ucontext threading */ /* (blocking sockets are used) */ bio=BIO_new_fd(c->fd, BIO_NOCLOSE); response=OCSP_sendreq_bio(bio, c->opt->ocsp_path, request); if(!response) { sslerror("OCSP: OCSP_sendreq_bio"); goto cleanup; } error=OCSP_response_status(response); if(error!=OCSP_RESPONSE_STATUS_SUCCESSFUL) { s_log(LOG_WARNING, "OCSP: Responder error: %d: %s", error, OCSP_response_status_str(error)); goto cleanup; } s_log(LOG_DEBUG, "OCSP: Response received"); /* verify the response */ basicResponse=OCSP_response_get1_basic(response); if(!basicResponse) { sslerror("OCSP: OCSP_response_get1_basic"); goto cleanup; } if(OCSP_check_nonce(request, basicResponse)<=0) { sslerror("OCSP: OCSP_check_nonce"); goto cleanup; } if(OCSP_basic_verify(basicResponse, NULL, c->opt->revocation_store, c->opt->ocsp_flags)<=0) { sslerror("OCSP: OCSP_basic_verify"); goto cleanup; } if(!OCSP_resp_find_status(basicResponse, certID, &status, &reason, &revoked_at, &this_update, &next_update)) { sslerror("OCSP: OCSP_resp_find_status"); goto cleanup; } s_log(LOG_NOTICE, "OCSP: Status: %d: %s", status, OCSP_cert_status_str(status)); log_time(LOG_INFO, "OCSP: This update", this_update); log_time(LOG_INFO, "OCSP: Next update", next_update); /* check if the response is valid for at least one minute */ if(!OCSP_check_validity(this_update, next_update, 60, -1)) { sslerror("OCSP: OCSP_check_validity"); goto cleanup; } if(status==V_OCSP_CERTSTATUS_REVOKED) { if(reason==-1) s_log(LOG_WARNING, "OCSP: Certificate revoked"); else s_log(LOG_WARNING, "OCSP: Certificate revoked: %d: %s", reason, OCSP_crl_reason_str(reason)); log_time(LOG_NOTICE, "OCSP: Revoked at", revoked_at); goto cleanup; } retval=1; /* accept connection */ cleanup: if(bio) BIO_free_all(bio); if(issuer) X509_free(issuer); if(request) OCSP_REQUEST_free(request); if(response) OCSP_RESPONSE_free(response); if(basicResponse) OCSP_BASICRESP_free(basicResponse); closesocket(c->fd); c->fd=-1; /* avoid double close on cleanup */ return retval; }
static int openssl_ocsp_request_new(lua_State*L) { OCSP_REQUEST *req = NULL; if (lua_isstring(L, 1)) { BIO* bio = load_bio_object(L, 1); req = d2i_OCSP_REQUEST_bio(bio, NULL); /* if (!req) { BIO_reset(bio); req = PEM_read_bio_OCSP_REQUEST(bio, NULL, NULL); } */ BIO_free(bio); } else { X509 *issuer = CHECK_OBJECT(1, X509, "openssl.x509"); X509_NAME *iname = X509_get_subject_name(issuer); ASN1_BIT_STRING *ikey = X509_get0_pubkey_bitstr(issuer); OCSP_CERTID *id = NULL; OCSP_ONEREQ *one; char buf[1024]; int nonce = lua_gettop(L) > 2 ? auxiliar_checkboolean(L, 3) : 0; req = OCSP_REQUEST_new(); if (lua_istable(L, 2)) { int len = lua_rawlen(L, 2); int i; for (i = 1; i <= len; i++) { lua_rawgeti(L, 2, i); if (auxiliar_isclass(L, "openssl.x509", -1)) { X509 *cert = CHECK_OBJECT(2, X509, "openssl.x509"); id = OCSP_cert_to_id(NULL, cert, issuer); one = OCSP_request_add0_id(req, id); } else { size_t len; char *serial = (char *)luaL_checklstring(L, -1, &len); ASN1_INTEGER *sno = ASN1_INTEGER_new(); BIO* bio = BIO_new(BIO_s_mem()); BIO_write(bio, serial, len); if (a2i_ASN1_INTEGER(bio, sno, buf, 1024) == 1) { id = OCSP_cert_id_new(EVP_sha1(), iname, ikey, sno); one = OCSP_request_add0_id(req, id); }; ASN1_INTEGER_free(sno); BIO_free(bio); } lua_pop(L, 1); } } else if (auxiliar_isclass(L, "openssl.x509", 2)) { X509 *cert = CHECK_OBJECT(2, X509, "openssl.x509"); id = OCSP_cert_to_id(NULL, cert, issuer); one = OCSP_request_add0_id(req, id); } else { ASN1_INTEGER *sno = ASN1_INTEGER_new(); BIO* bio = load_bio_object(L, 2); if (a2i_ASN1_INTEGER(bio, sno, buf, 1024) == 1) { id = OCSP_cert_id_new(EVP_sha1(), iname, ikey, sno); one = OCSP_request_add0_id(req, id); }; ASN1_INTEGER_free(sno); BIO_free(bio); } if (nonce) OCSP_request_add1_nonce(req, NULL, -1); } if(req) { PUSH_OBJECT(req, "openssl.ocsp_request"); }else lua_pushnil(L); return 1; }
static int ocsp_check(CLI *c, X509_STORE_CTX *callback_ctx) { int error, retval=0; X509 *cert; X509 *issuer=NULL; OCSP_CERTID *certID; OCSP_REQUEST *request=NULL; OCSP_RESPONSE *response=NULL; OCSP_BASICRESP *basicResponse=NULL; ASN1_GENERALIZEDTIME *revoked_at=NULL, *this_update=NULL, *next_update=NULL; int status, reason; /* get current certificate ID */ cert=X509_STORE_CTX_get_current_cert(callback_ctx); /* get current cert */ if(X509_STORE_CTX_get1_issuer(&issuer, callback_ctx, cert)!=1) { sslerror("OCSP: X509_STORE_CTX_get1_issuer"); goto cleanup; } certID=OCSP_cert_to_id(0, cert, issuer); if(!certID) { sslerror("OCSP: OCSP_cert_to_id"); goto cleanup; } /* build request */ request=OCSP_REQUEST_new(); if(!request) { sslerror("OCSP: OCSP_REQUEST_new"); goto cleanup; } if(!OCSP_request_add0_id(request, certID)) { sslerror("OCSP: OCSP_request_add0_id"); goto cleanup; } OCSP_request_add1_nonce(request, 0, -1); /* send the request and get a response */ response=ocsp_get_response(c, request); if(!response) goto cleanup; error=OCSP_response_status(response); if(error!=OCSP_RESPONSE_STATUS_SUCCESSFUL) { s_log(LOG_WARNING, "OCSP: Responder error: %d: %s", error, OCSP_response_status_str(error)); goto cleanup; } s_log(LOG_DEBUG, "OCSP: Response received"); /* verify the response */ basicResponse=OCSP_response_get1_basic(response); if(!basicResponse) { sslerror("OCSP: OCSP_response_get1_basic"); goto cleanup; } if(OCSP_check_nonce(request, basicResponse)<=0) { sslerror("OCSP: OCSP_check_nonce"); goto cleanup; } if(OCSP_basic_verify(basicResponse, NULL, c->opt->revocation_store, c->opt->ocsp_flags)<=0) { sslerror("OCSP: OCSP_basic_verify"); goto cleanup; } if(!OCSP_resp_find_status(basicResponse, certID, &status, &reason, &revoked_at, &this_update, &next_update)) { sslerror("OCSP: OCSP_resp_find_status"); goto cleanup; } s_log(LOG_NOTICE, "OCSP: Status: %d: %s", status, OCSP_cert_status_str(status)); log_time(LOG_INFO, "OCSP: This update", this_update); log_time(LOG_INFO, "OCSP: Next update", next_update); /* check if the response is valid for at least one minute */ if(!OCSP_check_validity(this_update, next_update, 60, -1)) { sslerror("OCSP: OCSP_check_validity"); goto cleanup; } if(status==V_OCSP_CERTSTATUS_REVOKED) { if(reason==-1) s_log(LOG_WARNING, "OCSP: Certificate revoked"); else s_log(LOG_WARNING, "OCSP: Certificate revoked: %d: %s", reason, OCSP_crl_reason_str(reason)); log_time(LOG_NOTICE, "OCSP: Revoked at", revoked_at); goto cleanup; } retval=1; /* accept connection */ cleanup: if(issuer) X509_free(issuer); if(request) OCSP_REQUEST_free(request); if(response) OCSP_RESPONSE_free(response); if(basicResponse) OCSP_BASICRESP_free(basicResponse); return retval; }
/* returns one of: * V_OCSP_CERTSTATUS_GOOD * V_OCSP_CERTSTATUS_REVOKED * V_OCSP_CERTSTATUS_UNKNOWN */ NOEXPORT int ocsp_request(CLI *c, X509_STORE_CTX *callback_ctx, OCSP_CERTID *cert_id, char *url) { int status=V_OCSP_CERTSTATUS_UNKNOWN; int reason; int ctx_err=X509_V_ERR_APPLICATION_VERIFICATION; OCSP_REQUEST *request=NULL; OCSP_RESPONSE *response=NULL; OCSP_BASICRESP *basic_response=NULL; ASN1_GENERALIZEDTIME *revoked_at=NULL, *this_update=NULL, *next_update=NULL; /* build request */ request=OCSP_REQUEST_new(); if(!request) { sslerror("OCSP: OCSP_REQUEST_new"); goto cleanup; } if(!OCSP_request_add0_id(request, cert_id)) { sslerror("OCSP: OCSP_request_add0_id"); goto cleanup; } OCSP_request_add1_nonce(request, NULL, -1); /* send the request and get a response */ response=ocsp_get_response(c, request, url); if(!response) goto cleanup; status=OCSP_response_status(response); if(status!=OCSP_RESPONSE_STATUS_SUCCESSFUL) { s_log(LOG_WARNING, "OCSP: Responder error: %d: %s", status, OCSP_response_status_str(status)); goto cleanup; } s_log(LOG_DEBUG, "OCSP: Response received"); /* verify the response */ basic_response=OCSP_response_get1_basic(response); if(!basic_response) { sslerror("OCSP: OCSP_response_get1_basic"); goto cleanup; } if(OCSP_check_nonce(request, basic_response)<=0) { s_log(LOG_WARNING, "OCSP: Invalid nonce"); goto cleanup; } if(OCSP_basic_verify(basic_response, NULL, c->opt->revocation_store, c->opt->ocsp_flags)<=0) { sslerror("OCSP: OCSP_basic_verify"); goto cleanup; } if(!OCSP_resp_find_status(basic_response, cert_id, &status, &reason, &revoked_at, &this_update, &next_update)) { sslerror("OCSP: OCSP_resp_find_status"); goto cleanup; } s_log(LOG_NOTICE, "OCSP: Status: %s", OCSP_cert_status_str(status)); log_time(LOG_INFO, "OCSP: This update", this_update); log_time(LOG_INFO, "OCSP: Next update", next_update); /* check if the response is valid for at least one minute */ if(!OCSP_check_validity(this_update, next_update, 60, -1)) { sslerror("OCSP: OCSP_check_validity"); status=V_OCSP_CERTSTATUS_UNKNOWN; goto cleanup; } switch(status) { case V_OCSP_CERTSTATUS_GOOD: break; case V_OCSP_CERTSTATUS_REVOKED: if(reason==-1) s_log(LOG_WARNING, "OCSP: Certificate revoked"); else s_log(LOG_WARNING, "OCSP: Certificate revoked: %d: %s", reason, OCSP_crl_reason_str(reason)); log_time(LOG_NOTICE, "OCSP: Revoked at", revoked_at); ctx_err=X509_V_ERR_CERT_REVOKED; break; case V_OCSP_CERTSTATUS_UNKNOWN: s_log(LOG_WARNING, "OCSP: Unknown verification status"); } cleanup: if(request) OCSP_REQUEST_free(request); if(response) OCSP_RESPONSE_free(response); if(basic_response) OCSP_BASICRESP_free(basic_response); if(status!=V_OCSP_CERTSTATUS_GOOD) X509_STORE_CTX_set_error(callback_ctx, ctx_err); return status; }