static VALUE ossl_ocspcid_initialize(int argc, VALUE *argv, VALUE self) { OCSP_CERTID *id, *newid; X509 *x509s, *x509i; VALUE subject, issuer, digest; const EVP_MD *md; if (rb_scan_args(argc, argv, "21", &subject, &issuer, &digest) == 0) { return self; } x509s = GetX509CertPtr(subject); /* NO NEED TO DUP */ x509i = GetX509CertPtr(issuer); /* NO NEED TO DUP */ if (!NIL_P(digest)) { md = GetDigestPtr(digest); newid = OCSP_cert_to_id(md, x509s, x509i); } else { newid = OCSP_cert_to_id(NULL, x509s, x509i); } if(!newid) ossl_raise(eOCSPError, NULL); GetOCSPCertId(self, id); OCSP_CERTID_free(id); RDATA(self)->data = newid; return self; }
int SslOcspStapling::getCertId(X509 *pCert) { int i, n; X509 *pXissuer; X509_STORE *pXstore; STACK_OF(X509) *pXchain; X509_STORE_CTX *pXstore_ctx; pXchain = m_pCtx->extra_certs; n = sk_X509_num(pXchain); for (i = 0; i < n; i++) { pXissuer = sk_X509_value(pXchain, i); if (X509_check_issued(pXissuer, pCert) == X509_V_OK) { CRYPTO_add(&pXissuer->references, 1, CRYPTO_LOCK_X509); m_pCertId = OCSP_cert_to_id(NULL, pCert, pXissuer); X509_free(pXissuer); return 0; } } pXstore = SSL_CTX_get_cert_store(m_pCtx); if (pXstore == NULL) { setLastErrMsg("SSL_CTX_get_cert_store failed!\n"); return LS_FAIL; } pXstore_ctx = X509_STORE_CTX_new(); if (pXstore_ctx == NULL) { setLastErrMsg("X509_STORE_CTX_new failed!\n"); return LS_FAIL; } if (X509_STORE_CTX_init(pXstore_ctx, pXstore, NULL, NULL) == 0) { setLastErrMsg("X509_STORE_CTX_init failed!\n"); return LS_FAIL; } n = X509_STORE_CTX_get1_issuer(&pXissuer, pXstore_ctx, pCert); X509_STORE_CTX_free(pXstore_ctx); if ((n == -1) || (n == 0)) { setLastErrMsg("X509_STORE_CTX_get1_issuer failed!\n"); return LS_FAIL; } m_pCertId = OCSP_cert_to_id(NULL, pCert, pXissuer); X509_free(pXissuer); return 0; }
/* 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); }
static VALUE ossl_ocspcid_initialize(VALUE self, VALUE subject, VALUE issuer) { OCSP_CERTID *id, *newid; X509 *x509s, *x509i; x509s = GetX509CertPtr(subject); /* NO NEED TO DUP */ x509i = GetX509CertPtr(issuer); /* NO NEED TO DUP */ if(!(newid = OCSP_cert_to_id(NULL, x509s, x509i))) ossl_raise(eOCSPError, NULL); GetOCSPCertId(self, id); OCSP_CERTID_free(id); RDATA(self)->data = newid; return self; }
/* 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; }
/* * 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 void ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx) { #if OPENSSL_VERSION_NUMBER >= 0x0090707fL const #endif u_char *p; int n; size_t len; time_t now, valid; ngx_str_t response; X509_STORE *store; STACK_OF(X509) *chain; OCSP_CERTID *id; OCSP_RESPONSE *ocsp; OCSP_BASICRESP *basic; ngx_ssl_stapling_t *staple; ASN1_GENERALIZEDTIME *thisupdate, *nextupdate; staple = ctx->data; now = ngx_time(); ocsp = NULL; basic = NULL; id = NULL; if (ctx->code != 200) { goto error; } /* check the response */ len = ctx->response->last - ctx->response->pos; p = ctx->response->pos; ocsp = d2i_OCSP_RESPONSE(NULL, &p, len); if (ocsp == NULL) { ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0, "d2i_OCSP_RESPONSE() failed"); goto error; } n = OCSP_response_status(ocsp); if (n != OCSP_RESPONSE_STATUS_SUCCESSFUL) { ngx_log_error(NGX_LOG_ERR, ctx->log, 0, "OCSP response not successful (%d: %s)", n, OCSP_response_status_str(n)); goto error; } basic = OCSP_response_get1_basic(ocsp); if (basic == NULL) { ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0, "OCSP_response_get1_basic() failed"); goto error; } store = SSL_CTX_get_cert_store(staple->ssl_ctx); if (store == NULL) { ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0, "SSL_CTX_get_cert_store() failed"); goto error; } #if OPENSSL_VERSION_NUMBER >= 0x10001000L SSL_CTX_get_extra_chain_certs(staple->ssl_ctx, &chain); #else chain = staple->ssl_ctx->extra_certs; #endif if (OCSP_basic_verify(basic, chain, store, staple->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY) != 1) { ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0, "OCSP_basic_verify() failed"); goto 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 error; } if (OCSP_resp_find_status(basic, id, &n, NULL, NULL, &thisupdate, &nextupdate) != 1) { ngx_log_error(NGX_LOG_ERR, ctx->log, 0, "certificate status not found in the OCSP response"); goto error; } if (n != V_OCSP_CERTSTATUS_GOOD) { ngx_log_error(NGX_LOG_ERR, ctx->log, 0, "certificate status \"%s\" in the OCSP response", OCSP_cert_status_str(n)); goto error; } if (OCSP_check_validity(thisupdate, nextupdate, 300, -1) != 1) { ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0, "OCSP_check_validity() failed"); goto error; } if (nextupdate) { valid = ngx_ssl_stapling_time(nextupdate); if (valid == (time_t) NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, ctx->log, 0, "invalid nextUpdate time in certificate status"); goto error; } } else { valid = NGX_MAX_TIME_T_VALUE; } OCSP_CERTID_free(id); OCSP_BASICRESP_free(basic); OCSP_RESPONSE_free(ocsp); id = NULL; basic = NULL; ocsp = NULL; /* copy the response to memory not in ctx->pool */ response.len = len; response.data = ngx_alloc(response.len, ctx->log); if (response.data == NULL) { goto error; } ngx_memcpy(response.data, ctx->response->pos, response.len); ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0, "ssl ocsp response, %s, %uz", OCSP_cert_status_str(n), response.len); if (staple->staple.data) { ngx_free(staple->staple.data); } staple->staple = response; staple->valid = valid; /* * refresh before the response expires, * but not earlier than in 5 minutes, and at least in an hour */ staple->loading = 0; staple->refresh = ngx_max(ngx_min(valid - 300, now + 3600), now + 300); ngx_ssl_ocsp_done(ctx); return; error: staple->loading = 0; staple->refresh = now + 300; if (id) { OCSP_CERTID_free(id); } if (basic) { OCSP_BASICRESP_free(basic); } if (ocsp) { OCSP_RESPONSE_free(ocsp); } ngx_ssl_ocsp_done(ctx); }
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; }
/** * NOTE: From node.js * * Read a file that contains our certificate in "PEM" format, * possibly followed by a sequence of CA certificates that should be * sent to the peer in the Certificate message. * * Taken from OpenSSL - editted for style. */ int bud_context_use_certificate_chain(bud_context_t* ctx, BIO *in) { int ret; X509* x; X509* ca; X509_STORE* store; X509_STORE_CTX store_ctx; int r; unsigned long err; ERR_clear_error(); ret = 0; x = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL); if (x == NULL) { SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB); goto end; } ret = SSL_CTX_use_certificate(ctx->ctx, x); ctx->cert = x; ctx->issuer = NULL; if (ERR_peek_error() != 0) { /* Key/certificate mismatch doesn't imply ret==0 ... */ ret = 0; } if (ret) { /** * If we could set up our certificate, now proceed to * the CA certificates. */ if (ctx->ctx->extra_certs != NULL) { sk_X509_pop_free(ctx->ctx->extra_certs, X509_free); ctx->ctx->extra_certs = NULL; } while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) { r = SSL_CTX_add_extra_chain_cert(ctx->ctx, ca); if (!r) { X509_free(ca); ret = 0; goto end; } /** * Note that we must not free r if it was successfully * added to the chain (while we must free the main * certificate, since its reference count is increased * by SSL_CTX_use_certificate). */ /* Find issuer */ if (ctx->issuer != NULL || X509_check_issued(ca, x) != X509_V_OK) continue; ctx->issuer = ca; } /* When the while loop ends, it's usually just EOF. */ err = ERR_peek_last_error(); if (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE) { ERR_clear_error(); } else { /* some real error */ ret = 0; } } end: if (ret) { /* Try getting issuer from cert store */ if (ctx->issuer == NULL) { store = SSL_CTX_get_cert_store(ctx->ctx); ret = X509_STORE_CTX_init(&store_ctx, store, NULL, NULL); if (!ret) goto fatal; ret = X509_STORE_CTX_get1_issuer(&ctx->issuer, &store_ctx, ctx->cert); X509_STORE_CTX_cleanup(&store_ctx); ret = ret < 0 ? 0 : 1; /* NOTE: get_cert_store doesn't increment reference count */ } else { /* Increment issuer reference count */ CRYPTO_add(&ctx->issuer->references, 1, CRYPTO_LOCK_X509); } if (ctx->issuer != NULL) { /* Get ocsp_id */ ctx->ocsp_id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer); if (ctx->ocsp_id == NULL) { ctx->issuer = NULL; goto fatal; } } } else { if (ctx->issuer != NULL) X509_free(ctx->issuer); } fatal: if (ctx->cert != x && x != NULL) X509_free(x); return ret; }
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; }
/** * NOTE: From node.js * * Read a file that contains our certificate in "PEM" format, * possibly followed by a sequence of CA certificates that should be * sent to the peer in the Certificate message. * * Taken from OpenSSL - editted for style. */ int bud_context_use_certificate_chain(bud_context_t* ctx, BIO *in) { int ret; X509* x; X509* ca; int r; unsigned long err; bud_context_pkey_type_t type; bud_context_pem_t* pem; ERR_clear_error(); ret = 0; x = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL); pem = NULL; if (x == NULL) { SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB); goto end; } ret = SSL_CTX_use_certificate(ctx->ctx, x); SSL_CTX_select_current_cert(ctx->ctx, x); type = bud_config_pkey_type(x->cert_info->key->pkey); pem = &ctx->pem[type]; pem->cert = x; pem->issuer = NULL; if (ERR_peek_error() != 0) { /* Key/certificate mismatch doesn't imply ret==0 ... */ ret = 0; } if (ret) { while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) { /* * Extra cert - add it to store to make OpenSSL pick and send proper * certs automatically */ r = SSL_CTX_add1_chain_cert(ctx->ctx, ca); if (!r) { X509_free(ca); ret = 0; goto end; } /** * Note that we must not free r if it was successfully * added to the chain (while we must free the main * certificate, since its reference count is increased * by SSL_CTX_use_certificate). */ /* Find issuer */ if (pem->issuer != NULL || X509_check_issued(ca, x) != X509_V_OK) continue; pem->issuer = ca; } /* When the while loop ends, it's usually just EOF. */ err = ERR_peek_last_error(); if (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE) { ERR_clear_error(); } else { /* some real error */ ret = 0; } } end: if (ret) { /* Try getting issuer from cert store */ if (pem->issuer == NULL) { X509_STORE* store; X509_STORE_CTX store_ctx; store = SSL_CTX_get_cert_store(ctx->ctx); ret = X509_STORE_CTX_init(&store_ctx, store, NULL, NULL); if (!ret) goto fatal; ret = X509_STORE_CTX_get1_issuer(&pem->issuer, &store_ctx, pem->cert); X509_STORE_CTX_cleanup(&store_ctx); ret = ret < 0 ? 0 : 1; /* NOTE: get_cert_store doesn't increment reference count */ } else { /* Increment issuer reference count */ CRYPTO_add(&pem->issuer->references, 1, CRYPTO_LOCK_X509); } if (pem->issuer != NULL) { /* Get ocsp_id */ pem->ocsp_id = OCSP_cert_to_id(NULL, pem->cert, pem->issuer); if (pem->ocsp_id == NULL) goto fatal; } } fatal: if (!ret && pem != NULL && pem->issuer != NULL) { X509_free(pem->issuer); pem->issuer = NULL; } if (!(pem != NULL && pem->cert == x) && x != NULL) X509_free(x); return ret; }
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_response(lua_State *L) { OCSP_RESPONSE *res = NULL; if (lua_isstring(L, 1)) { BIO* bio = load_bio_object(L, 1); res = d2i_OCSP_RESPONSE_bio(bio, NULL); /* BIO_reset(bio); if (!res) { res = PEM_read_bio_OCSP_RESPONSE(bio, NULL, NULL); } */ BIO_free(bio); } else { ASN1_TIME* thispnd, *nextpnd; OCSP_CERTID *ca_id, *cid; OCSP_BASICRESP *bs; OCSP_REQUEST *req = CHECK_OBJECT(1, OCSP_REQUEST, "openssl.ocsp_request"); X509* ca = CHECK_OBJECT(2, X509, "openssl.x509"); X509* rcert = CHECK_OBJECT(3, X509, "openssl.x509"); EVP_PKEY *rkey = CHECK_OBJECT(4, EVP_PKEY, "openssl.evp_pkey"); unsigned long flag = luaL_optint(L, 6, 0); int nmin = luaL_optint(L, 7, 0); int nday = luaL_optint(L, 8, 1); STACK_OF(X509) *rother = lua_isnoneornil(L, 9) ? NULL : CHECK_OBJECT(9, STACK_OF(X509), "openssl.stack_of_x509"); int i, id_count, type; BIO* bio = NULL; type = lua_type(L, 5); if (type != LUA_TFUNCTION && type != LUA_TTABLE) { luaL_error(L, "#5 must be a table or function that to get status of certificate"); } bio = BIO_new(BIO_s_mem()); ca_id = OCSP_cert_to_id(EVP_sha1(), NULL, ca); bs = OCSP_BASICRESP_new(); thispnd = X509_gmtime_adj(NULL, 0); nextpnd = X509_gmtime_adj(NULL, nmin * 60 + nday * 3600 * 24); id_count = OCSP_request_onereq_count(req); for (i = 0; i < id_count; i++) { OCSP_ONEREQ *one; ASN1_INTEGER *serial; ASN1_OBJECT* inst = NULL; ASN1_TIME* revtm = NULL; ASN1_GENERALIZEDTIME *invtm = NULL; OCSP_SINGLERESP *single = NULL; int reason = OCSP_REVOKED_STATUS_UNSPECIFIED, status = V_OCSP_CERTSTATUS_UNKNOWN; one = OCSP_request_onereq_get0(req, i); cid = OCSP_onereq_get0_id(one); if (OCSP_id_issuer_cmp(ca_id, cid)) { OCSP_basic_add1_status(bs, cid, V_OCSP_CERTSTATUS_UNKNOWN, 0, NULL, thispnd, nextpnd); continue; } OCSP_id_get0_info(NULL, NULL, NULL, &serial, cid); if (lua_istable(L, 5)) { BUF_MEM *buf; BIO_reset(bio); i2a_ASN1_INTEGER(bio, serial); BIO_get_mem_ptr(bio, &buf); lua_pushlstring(L, buf->data, buf->length); lua_gettable(L, 5); if (lua_isnil(L, -1)) status = V_OCSP_CERTSTATUS_UNKNOWN; else { luaL_checktype(L, -1, LUA_TTABLE); lua_getfield(L, -1, "revoked"); if (lua_toboolean(L, -1)) { lua_pop(L, 1); status = V_OCSP_CERTSTATUS_REVOKED; lua_getfield(L, -1, "revoked_time"); if (!lua_isnil(L, -1)) { revtm = ASN1_TIME_new(); ASN1_TIME_set(revtm, luaL_checkint(L, -1)); } lua_pop(L, 1); lua_getfield(L, -1, "reason"); if (lua_isstring(L, -1)) reason = openssl_get_revoke_reason(lua_tostring(L, -1)); else reason = luaL_checkint(L, -1); lua_pop(L, 1); } else { lua_pop(L, 1); status = V_OCSP_CERTSTATUS_GOOD; } } } else { } if (reason == 7) reason = OCSP_REVOKED_STATUS_REMOVEFROMCRL; else if (reason == 8) { reason = OCSP_REVOKED_STATUS_CERTIFICATEHOLD; //inst = OBJ_txt2obj(str, 0); } else if (reason == 9 || reason == 10) { if ( reason == 9 ) reason = OCSP_REVOKED_STATUS_KEYCOMPROMISE; else if (reason == 10) reason = OCSP_REVOKED_STATUS_CACOMPROMISE; /* invtm = ASN1_GENERALIZEDTIME_new(); if (!ASN1_GENERALIZEDTIME_set_string(invtm, arg_str)) */ } single = OCSP_basic_add1_status(bs, cid, status, reason, revtm, thispnd, nextpnd); if (invtm) { OCSP_SINGLERESP_add1_ext_i2d(single, NID_invalidity_date, invtm, 0, 0); ASN1_TIME_free(revtm); } if (inst) { OCSP_SINGLERESP_add1_ext_i2d(single, NID_hold_instruction_code, inst, 0, 0); ASN1_OBJECT_free(inst); } if (invtm) ASN1_GENERALIZEDTIME_free(invtm); } OCSP_copy_nonce(bs, req); OCSP_basic_sign(bs, rcert, rkey, EVP_sha1(), rother, flag); res = OCSP_response_create(OCSP_RESPONSE_STATUS_SUCCESSFUL, bs); BIO_free(bio); } if(res) { PUSH_OBJECT(res, "openssl.ocsp_response"); }else lua_pushnil(L); return 1; }
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; }
NOEXPORT int ocsp_check(X509_STORE_CTX *callback_ctx) { SSL *ssl; CLI *c; X509 *cert; OCSP_CERTID *cert_id; STACK_OF(OPENSSL_STRING) *aia; int i, status=V_OCSP_CERTSTATUS_UNKNOWN; /* get the current certificate ID */ cert=X509_STORE_CTX_get_current_cert(callback_ctx); if(!cert) { s_log(LOG_ERR, "OCSP: Failed to get the current certificate"); X509_STORE_CTX_set_error(callback_ctx, X509_V_ERR_APPLICATION_VERIFICATION); return 0; /* reject */ } if(!X509_NAME_cmp(X509_get_subject_name(cert), X509_get_issuer_name(cert))) { s_log(LOG_DEBUG, "OCSP: Ignoring root certificate"); return 1; /* accept */ } cert_id=OCSP_cert_to_id(NULL, cert, get_current_issuer(callback_ctx)); if(!cert_id) { sslerror("OCSP: OCSP_cert_to_id"); X509_STORE_CTX_set_error(callback_ctx, X509_V_ERR_APPLICATION_VERIFICATION); return 0; /* reject */ } ssl=X509_STORE_CTX_get_ex_data(callback_ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); c=SSL_get_ex_data(ssl, cli_index); /* use the responder specified in the configuration file */ if(c->opt->ocsp_url) { s_log(LOG_DEBUG, "OCSP: Connecting configured responder \"%s\"", c->opt->ocsp_url); if(ocsp_request(c, callback_ctx, cert_id, c->opt->ocsp_url)!= V_OCSP_CERTSTATUS_GOOD) return 0; /* reject */ } /* use the responder from AIA (Authority Information Access) */ if(!c->opt->option.aia) return 1; /* accept */ aia=X509_get1_ocsp(cert); if(!aia) return 1; /* accept */ for(i=0; i<sk_OPENSSL_STRING_num(aia); i++) { s_log(LOG_DEBUG, "OCSP: Connecting AIA responder \"%s\"", sk_OPENSSL_STRING_value(aia, i)); status=ocsp_request(c, callback_ctx, cert_id, sk_OPENSSL_STRING_value(aia, i)); if(status!=V_OCSP_CERTSTATUS_UNKNOWN) break; /* we received a definitive response */ } X509_email_free(aia); if(status==V_OCSP_CERTSTATUS_GOOD) return 1; /* accept */ return 0; /* reject */ }