📄 ocsp.c
字号:
} if(acbio) BIO_printf(bio_err, "Waiting for OCSP client connections...\n"); redo_accept: if (acbio) { if (!do_responder(&req, &cbio, acbio, port)) goto end; if (!req) { resp = OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, NULL); send_ocsp_response(cbio, resp); goto done_resp; } } if (!req && (signfile || reqout || host || add_nonce || ridx_filename)) { BIO_printf(bio_err, "Need an OCSP request for this operation!\n"); goto end; } if (req && add_nonce) OCSP_request_add1_nonce(req, NULL, -1); if (signfile) { if (!keyfile) keyfile = signfile; signer = load_cert(bio_err, signfile, FORMAT_PEM, NULL, e, "signer certificate"); if (!signer) { BIO_printf(bio_err, "Error loading signer certificate\n"); goto end; } if (sign_certfile) { sign_other = load_certs(bio_err, sign_certfile, FORMAT_PEM, NULL, e, "signer certificates"); if (!sign_other) goto end; } key = load_key(bio_err, keyfile, FORMAT_PEM, 0, NULL, NULL, "signer private key"); if (!key) goto end; if (!OCSP_request_sign(req, signer, key, EVP_sha1(), sign_other, sign_flags)) { BIO_printf(bio_err, "Error signing OCSP request\n"); goto end; } } if (req_text && req) OCSP_REQUEST_print(out, req, 0); if (reqout) { derbio = BIO_new_file(reqout, "wb"); if(!derbio) { BIO_printf(bio_err, "Error opening file %s\n", reqout); goto end; } i2d_OCSP_REQUEST_bio(derbio, req); BIO_free(derbio); } if (ridx_filename && (!rkey || !rsigner || !rca_cert)) { BIO_printf(bio_err, "Need a responder certificate, key and CA for this operation!\n"); goto end; } if (ridx_filename && !rdb) { rdb = load_index(ridx_filename, NULL); if (!rdb) goto end; if (!index_index(rdb)) goto end; } if (rdb) { i = make_ocsp_response(&resp, req, rdb, rca_cert, rsigner, rkey, rother, rflags, nmin, ndays); if (cbio) send_ocsp_response(cbio, resp); } else if (host) {#ifndef OPENSSL_NO_SOCK cbio = BIO_new_connect(host);#else BIO_printf(bio_err, "Error creating connect BIO - sockets not supported.\n"); goto end;#endif if (!cbio) { BIO_printf(bio_err, "Error creating connect BIO\n"); goto end; } if (port) BIO_set_conn_port(cbio, port); if (use_ssl == 1) { BIO *sbio;#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3) ctx = SSL_CTX_new(SSLv23_client_method());#elif !defined(OPENSSL_NO_SSL3) ctx = SSL_CTX_new(SSLv3_client_method());#elif !defined(OPENSSL_NO_SSL2) ctx = SSL_CTX_new(SSLv2_client_method());#else BIO_printf(bio_err, "SSL is disabled\n"); goto end;#endif SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); sbio = BIO_new_ssl(ctx, 1); cbio = BIO_push(sbio, cbio); } if (BIO_do_connect(cbio) <= 0) { BIO_printf(bio_err, "Error connecting BIO\n"); goto end; } resp = OCSP_sendreq_bio(cbio, path, req); BIO_free_all(cbio); cbio = NULL; if (!resp) { BIO_printf(bio_err, "Error querying OCSP responsder\n"); goto end; } } else if (respin) { derbio = BIO_new_file(respin, "rb"); if (!derbio) { BIO_printf(bio_err, "Error Opening OCSP response file\n"); goto end; } resp = d2i_OCSP_RESPONSE_bio(derbio, NULL); BIO_free(derbio); if(!resp) { BIO_printf(bio_err, "Error reading OCSP response\n"); goto end; } } else { ret = 0; goto end; } done_resp: if (respout) { derbio = BIO_new_file(respout, "wb"); if(!derbio) { BIO_printf(bio_err, "Error opening file %s\n", respout); goto end; } i2d_OCSP_RESPONSE_bio(derbio, resp); BIO_free(derbio); } i = OCSP_response_status(resp); if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL) { BIO_printf(out, "Responder Error: %s (%d)\n", OCSP_response_status_str(i), i); if (ignore_err) goto redo_accept; ret = 0; goto end; } if (resp_text) OCSP_RESPONSE_print(out, resp, 0); /* If running as responder don't verify our own response */ if (cbio) { if (accept_count > 0) accept_count--; /* Redo if more connections needed */ if (accept_count) { BIO_free_all(cbio); cbio = NULL; OCSP_REQUEST_free(req); req = NULL; OCSP_RESPONSE_free(resp); resp = NULL; goto redo_accept; } goto end; } if (!store) store = setup_verify(bio_err, CAfile, CApath); if (!store) goto end; if (verify_certfile) { verify_other = load_certs(bio_err, verify_certfile, FORMAT_PEM, NULL, e, "validator certificate"); if (!verify_other) goto end; } bs = OCSP_response_get1_basic(resp); if (!bs) { BIO_printf(bio_err, "Error parsing response\n"); goto end; } if (!noverify) { if (req && ((i = OCSP_check_nonce(req, bs)) <= 0)) { if (i == -1) BIO_printf(bio_err, "WARNING: no nonce in response\n"); else { BIO_printf(bio_err, "Nonce Verify error\n"); goto end; } } i = OCSP_basic_verify(bs, verify_other, store, verify_flags); if (i < 0) i = OCSP_basic_verify(bs, NULL, store, 0); if(i <= 0) { BIO_printf(bio_err, "Response Verify Failure\n"); ERR_print_errors(bio_err); } else BIO_printf(bio_err, "Response verify OK\n"); } if (!print_ocsp_summary(out, bs, req, reqnames, ids, nsec, maxage)) goto end; ret = 0;end: ERR_print_errors(bio_err); X509_free(signer); X509_STORE_free(store); EVP_PKEY_free(key); EVP_PKEY_free(rkey); X509_free(issuer); X509_free(cert); X509_free(rsigner); X509_free(rca_cert); free_index(rdb); BIO_free_all(cbio); BIO_free_all(acbio); BIO_free(out); OCSP_REQUEST_free(req); OCSP_RESPONSE_free(resp); OCSP_BASICRESP_free(bs); sk_free(reqnames); sk_OCSP_CERTID_free(ids); sk_X509_pop_free(sign_other, X509_free); sk_X509_pop_free(verify_other, X509_free); if (use_ssl != -1) { OPENSSL_free(host); OPENSSL_free(port); OPENSSL_free(path); SSL_CTX_free(ctx); } OPENSSL_EXIT(ret);}static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *issuer, STACK_OF(OCSP_CERTID) *ids) { OCSP_CERTID *id; if(!issuer) { BIO_printf(bio_err, "No issuer certificate specified\n"); return 0; } if(!*req) *req = OCSP_REQUEST_new(); if(!*req) goto err; id = OCSP_cert_to_id(NULL, cert, issuer); if(!id || !sk_OCSP_CERTID_push(ids, id)) goto err; if(!OCSP_request_add0_id(*req, id)) goto err; return 1; err: BIO_printf(bio_err, "Error Creating OCSP request\n"); return 0; }static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, X509 *issuer, STACK_OF(OCSP_CERTID) *ids) { OCSP_CERTID *id; X509_NAME *iname; ASN1_BIT_STRING *ikey; ASN1_INTEGER *sno; if(!issuer) { BIO_printf(bio_err, "No issuer certificate specified\n"); return 0; } if(!*req) *req = OCSP_REQUEST_new(); if(!*req) goto err; iname = X509_get_subject_name(issuer); ikey = X509_get0_pubkey_bitstr(issuer); sno = s2i_ASN1_INTEGER(NULL, serial); if(!sno) { BIO_printf(bio_err, "Error converting serial number %s\n", serial); return 0; } id = OCSP_cert_id_new(EVP_sha1(), iname, ikey, sno); ASN1_INTEGER_free(sno); if(!id || !sk_OCSP_CERTID_push(ids, id)) goto err; if(!OCSP_request_add0_id(*req, id)) goto err; return 1; err: BIO_printf(bio_err, "Error Creating OCSP request\n"); return 0; }static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req, STACK *names, STACK_OF(OCSP_CERTID) *ids, long nsec, long maxage) { OCSP_CERTID *id; char *name; int i; int status, reason; ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; if (!bs || !req || !sk_num(names) || !sk_OCSP_CERTID_num(ids)) return 1; for (i = 0; i < sk_OCSP_CERTID_num(ids); i++) { id = sk_OCSP_CERTID_value(ids, i); name = sk_value(names, i); BIO_printf(out, "%s: ", name); if(!OCSP_resp_find_status(bs, id, &status, &reason, &rev, &thisupd, &nextupd)) { BIO_puts(out, "ERROR: No Status found.\n"); continue; } /* Check validity: if invalid write to output BIO so we * know which response this refers to. */ if (!OCSP_check_validity(thisupd, nextupd, nsec, maxage)) { BIO_puts(out, "WARNING: Status times invalid.\n"); ERR_print_errors(out); } BIO_printf(out, "%s\n", OCSP_cert_status_str(status)); BIO_puts(out, "\tThis Update: "); ASN1_GENERALIZEDTIME_print(out, thisupd); BIO_puts(out, "\n"); if(nextupd) { BIO_puts(out, "\tNext Update: "); ASN1_GENERALIZEDTIME_print(out, nextupd); BIO_puts(out, "\n"); } if (status != V_OCSP_CERTSTATUS_REVOKED) continue; if (reason != -1) BIO_printf(out, "\tReason: %s\n", OCSP_crl_reason_str(reason)); BIO_puts(out, "\tRevocation Time: "); ASN1_GENERALIZEDTIME_print(out, rev); BIO_puts(out, "\n"); } return 1; }static int make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req, CA_DB *db, X509 *ca, X509 *rcert, EVP_PKEY *rkey, STACK_OF(X509) *rother, unsigned long flags, int nmin, int ndays) { ASN1_TIME *thisupd = NULL, *nextupd = NULL; OCSP_CERTID *cid, *ca_id = NULL; OCSP_BASICRESP *bs = NULL; int i, id_count, ret = 1; id_count = OCSP_request_onereq_count(req); if (id_count <= 0) { *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, NULL); goto end; } ca_id = OCSP_cert_to_id(EVP_sha1(), NULL, ca); bs = OCSP_BASICRESP_new(); thisupd = X509_gmtime_adj(NULL, 0); if (ndays != -1) nextupd = X509_gmtime_adj(NULL, nmin * 60 + ndays * 3600 * 24 ); /* Examine each certificate id in the request */ for (i = 0; i < id_count; i++) { OCSP_ONEREQ *one; ASN1_INTEGER *serial; char **inf; one = OCSP_request_onereq_get0(req, i); cid = OCSP_onereq_get0_id(one); /* Is this request about our CA? */ if (OCSP_id_issuer_cmp(ca_id, cid)) { OCSP_basic_add1_status(bs, cid, V_OCSP_CERTSTATUS_UNKNOWN, 0, NULL, thisupd, nextupd); continue; } OCSP_id_get0_info(NULL, NULL, NULL, &serial, cid); inf = lookup_serial(db, serial); if (!inf) OCSP_basic_add1_status(bs, cid, V_OCSP_CERTSTATUS_UNKNOWN, 0, NULL, thisupd, nextupd); else if (inf[DB_type][0] == DB_TYPE_VAL) OCSP_basic_add1_status(bs, cid, V_OCSP_CERTSTATUS_GOOD, 0, NULL, thisupd, nextupd); else if (inf[DB_type][0] == DB_TYPE_REV) { ASN1_OBJECT *inst = NULL; ASN1_TIME *revtm = NULL; ASN1_GENERALIZEDTIME *invtm = NULL; OCSP_SINGLERESP *single; int reason = -1; unpack_revinfo(&revtm, &reason, &inst, &invtm, inf[DB_rev_date]); single = OCSP_basic_add1_status(bs, cid, V_OCSP_CERTSTATUS_REVOKED, reason, revtm, thisupd, nextupd); if (invtm) OCSP_SINGLERESP_add1_ext_i2d(single, NID_invalidity_date, invtm, 0, 0); else if (inst) OCSP_SINGLERESP_add1_ext_i2d(single, NID_hold_instruction_code, inst, 0, 0); ASN1_OBJECT_free(inst); ASN1_TIME_free(revtm); ASN1_GENERALIZEDTIME_free(invtm); } } OCSP_copy_nonce(bs, req); OCSP_basic_sign(bs, rcert, rkey, EVP_sha1(), rother, flags); *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_SUCCESSFUL, bs); end: ASN1_TIME_free(thisupd); ASN1_TIME_free(nextupd); OCSP_CERTID_free(ca_id); OCSP_BASICRESP_free(bs); return ret; }static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser) { int i; BIGNUM *bn = NULL; char *itmp, *row[DB_NUMBER],**rrow; for (i = 0; i < DB_NUMBER; i++) row[i] = NULL; bn = ASN1_INTEGER_to_BN(ser,NULL); if (BN_is_zero(bn)) itmp = BUF_strdup("00"); else itmp = BN_bn2hex(bn); row[DB_serial] = itmp; BN_free(bn); rrow=TXT_DB_get_by_index(db->db,DB_serial,row); OPENSSL_free(itmp); return rrow; }/* Quick and dirty OCSP server: read in and parse input request */static BIO *init_responder(char *port) { BIO *acbio = NULL, *bufbio = NULL; bufbio = BIO_new(BIO_f_buffer()); if (!bufbio) goto err;#ifndef OPENSSL_NO_SOCK acbio = BIO_new_accept(port);#else BIO_printf(bio_err, "Error setting up accept BIO - sockets not supported.\n");#endif if (!acbio) goto err; BIO_set_accept_bios(acbio, bufbio); bufbio = NULL; if (BIO_do_accept(acbio) <= 0) { BIO_printf(bio_err, "Error setting up accept BIO\n"); ERR_print_errors(bio_err); goto err; } return acbio; err: BIO_free_all(acbio); BIO_free(bufbio); return NULL; }static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, char *port) { int have_post = 0, len; OCSP_REQUEST *req = NULL; char inbuf[1024]; BIO *cbio = NULL; if (BIO_do_accept(acbio) <= 0) { BIO_printf(bio_err, "Error accepting connection\n"); ERR_print_errors(bio_err); return 0; } cbio = BIO_pop(acbio); *pcbio = cbio; for(;;) { len = BIO_gets(cbio, inbuf, sizeof inbuf); if (len <= 0) return 1; /* Look for "POST" signalling start of query */ if (!have_post) { if(strncmp(inbuf, "POST", 4)) { BIO_printf(bio_err, "Invalid request\n"); return 1; } have_post = 1; } /* Look for end of headers */ if ((inbuf[0] == '\r') || (inbuf[0] == '\n')) break; } /* Try to read OCSP request */ req = d2i_OCSP_REQUEST_bio(cbio, NULL); if (!req) { BIO_printf(bio_err, "Error parsing OCSP request\n"); ERR_print_errors(bio_err); } *preq = req; return 1; }static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp) { char http_resp[] = "HTTP/1.0 200 OK\r\nContent-type: application/ocsp-response\r\n" "Content-Length: %d\r\n\r\n"; if (!cbio) return 0; BIO_printf(cbio, http_resp, i2d_OCSP_RESPONSE(resp, NULL)); i2d_OCSP_RESPONSE_bio(cbio, resp); BIO_flush(cbio); return 1; }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -