From ee306a13321e11b3e4c40960ccacc3dbbe33b9c8 Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Thu, 12 Jul 2001 20:41:51 +0000 Subject: [PATCH] Initial OCSP server support, using index.txt format. This can process internal requests or behave like a mini responder. Todo: documentation, update usage info. --- CHANGES | 7 + apps/apps.h | 6 + apps/ca.c | 211 +++++++++++++++----------- apps/ocsp.c | 424 +++++++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 540 insertions(+), 108 deletions(-) diff --git a/CHANGES b/CHANGES index c5dffa6280..b1929cace8 100644 --- a/CHANGES +++ b/CHANGES @@ -12,6 +12,13 @@ *) applies to 0.9.6a/0.9.6b and 0.9.7 +) applies to 0.9.7 only + +) Add initial OCSP responder support to ocsp application. The + revocation information is handled using the text based index + use by the ca application. The responder can either handle + requests generated internally, supplied in files (for example + via a CGI script) or using an internal minimal server. + [Steve Henson] + +) Add configuration choices to get zlib compression for TLS. [Richard Levitte] diff --git a/apps/apps.h b/apps/apps.h index ae2f7f0833..de136f453b 100644 --- a/apps/apps.h +++ b/apps/apps.h @@ -68,6 +68,7 @@ #include #include #include +#include int app_RAND_load_file(const char *file, BIO *bio_e, int dont_warn); int app_RAND_write_file(const char *file, BIO *bio_e); @@ -187,6 +188,11 @@ STACK_OF(X509) *load_certs(BIO *err, const char *file, int format, X509_STORE *setup_verify(BIO *bp, char *CAfile, char *CApath); ENGINE *setup_engine(BIO *err, const char *engine, int debug); +/* Functions defined in ca.c and also used in ocsp.c */ +int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, + ASN1_GENERALIZEDTIME **pinvtm, char *str); +int make_serial_index(TXT_DB *db); + #define FORMAT_UNDEF 0 #define FORMAT_ASN1 1 #define FORMAT_TEXT 2 diff --git a/apps/ca.c b/apps/ca.c index e0a9ef9eae..7bee4b625b 100644 --- a/apps/ca.c +++ b/apps/ca.c @@ -658,15 +658,8 @@ bad: db=TXT_DB_read(in,DB_NUMBER); if (db == NULL) goto err; - if (!TXT_DB_create_index(db, DB_serial, NULL, - LHASH_HASH_FN(index_serial_hash), - LHASH_COMP_FN(index_serial_cmp))) - { - BIO_printf(bio_err, - "error creating serial number index:(%ld,%ld,%ld)\n", - db->error,db->arg1,db->arg2); + if (!make_serial_index(db)) goto err; - } if (get_certificate_status(ser_status,db) != 1) BIO_printf(bio_err,"Error verifying serial %s!\n", @@ -891,13 +884,8 @@ bad: BIO_printf(bio_err,"generating index\n"); } - if (!TXT_DB_create_index(db, DB_serial, NULL, - LHASH_HASH_FN(index_serial_hash), - LHASH_COMP_FN(index_serial_cmp))) - { - BIO_printf(bio_err,"error creating serial number index:(%ld,%ld,%ld)\n",db->error,db->arg1,db->arg2); + if (!make_serial_index(db)) goto err; - } if (!TXT_DB_create_index(db, DB_name, index_name_qual, LHASH_HASH_FN(index_name_hash), @@ -2889,92 +2877,21 @@ char *make_revocation_str(int rev_type, char *rev_arg) * 2 OK and some extensions added (i.e. V2 CRL) */ + int make_revoked(X509_REVOKED *rev, char *str) { char *tmp = NULL; - char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p; int reason_code = -1; int i, ret = 0; ASN1_OBJECT *hold = NULL; ASN1_GENERALIZEDTIME *comp_time = NULL; ASN1_ENUMERATED *rtmp = NULL; - tmp = BUF_strdup(str); - p = strchr(tmp, ','); - - rtime_str = tmp; - if (p) - { - *p = '\0'; - p++; - reason_str = p; - p = strchr(p, ','); - if (p) - { - *p = '\0'; - arg_str = p + 1; - } - } + i = unpack_revinfo(&rev->revocationDate, &reason_code, &hold, &comp_time, str); - if (rev && !ASN1_UTCTIME_set_string(rev->revocationDate, rtime_str)) - { - BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str); + if (i == 0) goto err; - } - if (reason_str) - { - for (i = 0; i < NUM_REASONS; i++) - { - if(!strcasecmp(reason_str, crl_reasons[i])) - { - reason_code = i; - break; - } - } - if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS) - { - BIO_printf(bio_err, "invalid reason code %s\n", reason_str); - goto err; - } - - if (reason_code == 7) - reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL; - else if (reason_code == 8) /* Hold instruction */ - { - if (!arg_str) - { - BIO_printf(bio_err, "missing hold instruction\n"); - goto err; - } - reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD; - hold = OBJ_txt2obj(arg_str, 0); - - if (!hold) - { - BIO_printf(bio_err, "invalid object identifier %s\n", arg_str); - goto err; - } - } - else if ((reason_code == 9) || (reason_code == 10)) - { - if (!arg_str) - { - BIO_printf(bio_err, "missing compromised time\n"); - goto err; - } - comp_time = ASN1_GENERALIZEDTIME_new(); - if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str)) - { - BIO_printf(bio_err, "invalid compromised time %s\n", arg_str); - goto err; - } - if (reason_code == 9) - reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE; - else - reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE; - } - } if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)) { @@ -3108,3 +3025,121 @@ int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str) BIO_printf(bp,"'\n"); return 1; } + +int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, ASN1_GENERALIZEDTIME **pinvtm, char *str) + { + char *tmp = NULL; + char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p; + int reason_code = -1; + int i, ret = 0; + ASN1_OBJECT *hold = NULL; + ASN1_GENERALIZEDTIME *comp_time = NULL; + tmp = BUF_strdup(str); + + p = strchr(tmp, ','); + + rtime_str = tmp; + + if (p) + { + *p = '\0'; + p++; + reason_str = p; + p = strchr(p, ','); + if (p) + { + *p = '\0'; + arg_str = p + 1; + } + } + + if (prevtm) + { + *prevtm = ASN1_UTCTIME_new(); + if (!ASN1_UTCTIME_set_string(*prevtm, rtime_str)) + { + BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str); + goto err; + } + } + if (reason_str) + { + for (i = 0; i < NUM_REASONS; i++) + { + if(!strcasecmp(reason_str, crl_reasons[i])) + { + reason_code = i; + break; + } + } + if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS) + { + BIO_printf(bio_err, "invalid reason code %s\n", reason_str); + goto err; + } + + if (reason_code == 7) + reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL; + else if (reason_code == 8) /* Hold instruction */ + { + if (!arg_str) + { + BIO_printf(bio_err, "missing hold instruction\n"); + goto err; + } + reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD; + hold = OBJ_txt2obj(arg_str, 0); + + if (!hold) + { + BIO_printf(bio_err, "invalid object identifier %s\n", arg_str); + goto err; + } + if (phold) *phold = hold; + } + else if ((reason_code == 9) || (reason_code == 10)) + { + if (!arg_str) + { + BIO_printf(bio_err, "missing compromised time\n"); + goto err; + } + comp_time = ASN1_GENERALIZEDTIME_new(); + if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str)) + { + BIO_printf(bio_err, "invalid compromised time %s\n", arg_str); + goto err; + } + if (reason_code == 9) + reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE; + else + reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE; + } + } + + if (preason) *preason = reason_code; + if (pinvtm) *pinvtm = comp_time; + else ASN1_GENERALIZEDTIME_free(comp_time); + + err: + + if (tmp) OPENSSL_free(tmp); + if (!phold) ASN1_OBJECT_free(hold); + if (!pinvtm) ASN1_GENERALIZEDTIME_free(comp_time); + + return ret; + } + +int make_serial_index(TXT_DB *db) + { + if (!TXT_DB_create_index(db, DB_serial, NULL, + LHASH_HASH_FN(index_serial_hash), + LHASH_COMP_FN(index_serial_cmp))) + { + BIO_printf(bio_err, + "error creating serial number index:(%ld,%ld,%ld)\n", + db->error,db->arg1,db->arg2); + return 0; + } + return 1; + } diff --git a/apps/ocsp.c b/apps/ocsp.c index 16207a6283..e11e7b1f9a 100644 --- a/apps/ocsp.c +++ b/apps/ocsp.c @@ -67,6 +67,19 @@ /* Maximum leeway in validity period: default 5 minutes */ #define MAX_VALIDITY_PERIOD (5 * 60) +/* CA index.txt definitions */ +#define DB_type 0 +#define DB_exp_date 1 +#define DB_rev_date 2 +#define DB_serial 3 /* index - unique */ +#define DB_file 4 +#define DB_name 5 /* index - unique for active */ +#define DB_NUMBER 6 + +#define DB_TYPE_REV 'R' +#define DB_TYPE_EXP 'E' +#define DB_TYPE_VAL 'V' + static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *issuer, STACK_OF(OCSP_CERTID) *ids); static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, X509 *issuer, @@ -75,6 +88,15 @@ static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req, STACK *names, STACK_OF(OCSP_CERTID) *ids, long nsec, long maxage); +static int make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req, TXT_DB *db, + X509 *ca, X509 *rcert, EVP_PKEY *rkey, + STACK_OF(X509) *rother, unsigned long flags, + int nmin, int ndays); + +static char **lookup_serial(TXT_DB *db, ASN1_INTEGER *ser); +static OCSP_REQUEST *do_responder(BIO **cbio, char *port); +static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp); + #undef PROG #define PROG ocsp_main @@ -88,14 +110,15 @@ int MAIN(int argc, char **argv) char *reqin = NULL, *respin = NULL; char *reqout = NULL, *respout = NULL; char *signfile = NULL, *keyfile = NULL; + char *rsignfile = NULL, *rkeyfile = NULL; char *outfile = NULL; int add_nonce = 1, noverify = 0, use_ssl = -1; OCSP_REQUEST *req = NULL; OCSP_RESPONSE *resp = NULL; OCSP_BASICRESP *bs = NULL; X509 *issuer = NULL, *cert = NULL; - X509 *signer = NULL; - EVP_PKEY *key = NULL; + X509 *signer = NULL, *rsigner = NULL; + EVP_PKEY *key = NULL, *rkey = NULL; BIO *cbio = NULL, *derbio = NULL; BIO *out = NULL; int req_text = 0, resp_text = 0; @@ -103,14 +126,21 @@ int MAIN(int argc, char **argv) char *CAfile = NULL, *CApath = NULL; X509_STORE *store = NULL; SSL_CTX *ctx = NULL; - STACK_OF(X509) *sign_other = NULL, *verify_other = NULL; - char *sign_certfile = NULL, *verify_certfile = NULL; - unsigned long sign_flags = 0, verify_flags = 0; + STACK_OF(X509) *sign_other = NULL, *verify_other = NULL, *rother = NULL; + char *sign_certfile = NULL, *verify_certfile = NULL, *rcertfile = NULL; + unsigned long sign_flags = 0, verify_flags = 0, rflags = 0; int ret = 1; int badarg = 0; int i; STACK *reqnames = NULL; STACK_OF(OCSP_CERTID) *ids = NULL; + + X509 *rca_cert = NULL; + char *ridx_filename = NULL; + char *rca_filename = NULL; + TXT_DB *rdb = NULL; + int nmin = 0, ndays = -1; + if (bio_err == NULL) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); SSL_load_error_strings(); args = argv + 1; @@ -149,12 +179,27 @@ int MAIN(int argc, char **argv) } else badarg = 1; } + else if (!strcmp(*args, "-port")) + { + if (args[1]) + { + args++; + port = *args; + } + else badarg = 1; + } else if (!strcmp(*args, "-noverify")) noverify = 1; else if (!strcmp(*args, "-nonce")) add_nonce = 2; else if (!strcmp(*args, "-no_nonce")) add_nonce = 0; + else if (!strcmp(*args, "-responder_no_certs")) + rflags |= OCSP_NOCERTS; + else if (!strcmp(*args, "-responder_no_time")) + rflags |= OCSP_NOTIME; + else if (!strcmp(*args, "-responder_key_id")) + rflags |= OCSP_RESPID_KEY; else if (!strcmp(*args, "-no_certs")) sign_flags |= OCSP_NOCERTS; else if (!strcmp(*args, "-no_signature_verify")) @@ -361,12 +406,91 @@ int MAIN(int argc, char **argv) } else badarg = 1; } + else if (!strcmp(*args, "-index")) + { + if (args[1]) + { + args++; + ridx_filename = *args; + } + else badarg = 1; + } + else if (!strcmp(*args, "-CA")) + { + if (args[1]) + { + args++; + rca_filename = *args; + } + else badarg = 1; + } + else if (!strcmp (*args, "-nmin")) + { + if (args[1]) + { + args++; + nmin = atol(*args); + if (nmin < 0) + { + BIO_printf(bio_err, + "Illegal update period %s\n", + *args); + badarg = 1; + } + } + if (ndays == -1) + ndays = 0; + else badarg = 1; + } + else if (!strcmp (*args, "-ndays")) + { + if (args[1]) + { + args++; + ndays = atol(*args); + if (ndays < 0) + { + BIO_printf(bio_err, + "Illegal update period %s\n", + *args); + badarg = 1; + } + } + else badarg = 1; + } + else if (!strcmp(*args, "-rsigner")) + { + if (args[1]) + { + args++; + rsignfile = *args; + } + else badarg = 1; + } + else if (!strcmp(*args, "-rkey")) + { + if (args[1]) + { + args++; + rkeyfile = *args; + } + else badarg = 1; + } + else if (!strcmp(*args, "-rother")) + { + if (args[1]) + { + args++; + rcertfile = *args; + } + else badarg = 1; + } else badarg = 1; args++; } /* Have we anything to do? */ - if (!req && !reqin && !respin) badarg = 1; + if (!req && !reqin && !respin && !(port && ridx_filename)) badarg = 1; if (badarg) { @@ -437,7 +561,20 @@ int MAIN(int argc, char **argv) } } - if (!req && (signfile || reqout || host || add_nonce)) + if (!req && port) + { + req = do_responder(&cbio, port); + if (!req && !cbio) + goto end; + if (!req && cbio) + { + 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; @@ -464,12 +601,7 @@ int MAIN(int argc, char **argv) key = load_key(bio_err, keyfile, FORMAT_PEM, NULL, NULL, "signer private key"); if (!key) - { -#if 0 /* An appropriate message has already been printed */ - BIO_printf(bio_err, "Error loading signer private key\n"); -#endif goto end; - } if (!OCSP_request_sign(req, signer, key, EVP_sha1(), sign_other, sign_flags)) { BIO_printf(bio_err, "Error signing OCSP request\n"); @@ -477,21 +609,61 @@ int MAIN(int argc, char **argv) } } - if (reqout) + if (req_text && req) OCSP_REQUEST_print(out, req, 0); + + if (rsignfile) { - derbio = BIO_new_file(reqout, "wb"); - if (!derbio) + if (!rkeyfile) rkeyfile = rsignfile; + rsigner = load_cert(bio_err, rsignfile, FORMAT_PEM, + NULL, e, "responder certificate"); + if (!rsigner) { - BIO_printf(bio_err, "Error opening file %s\n", reqout); + BIO_printf(bio_err, "Error loading responder certificate\n"); goto end; } - i2d_OCSP_REQUEST_bio(derbio, req); - BIO_free(derbio); + rca_cert = load_cert(bio_err, rca_filename, FORMAT_PEM, + NULL, e, "CA certificate"); + if (rcertfile) + { + rother = load_certs(bio_err, sign_certfile, FORMAT_PEM, + NULL, e, "responder other certificates"); + if (!sign_other) goto end; + } + rkey = load_key(bio_err, rkeyfile, FORMAT_PEM, NULL, NULL, + "responder private key"); + if (!rkey) + goto end; } - if (req_text && req) OCSP_REQUEST_print(out, req, 0); + 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 (host) + if (ridx_filename) + { + BIO *db_bio = NULL; + db_bio = BIO_new_file(ridx_filename, "r"); + if (!db_bio) + { + BIO_printf(bio_err, "Error opening index file %s\n", ridx_filename); + goto end; + } + rdb = TXT_DB_read(db_bio, DB_NUMBER); + BIO_free(db_bio); + if (!rdb) + { + BIO_printf(bio_err, "Error reading index file %s\n", ridx_filename); + goto end; + } + if (!make_serial_index(rdb)) + goto end; + 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) { cbio = BIO_new_connect(host); if (!cbio) @@ -545,6 +717,8 @@ int MAIN(int argc, char **argv) goto end; } + done_resp: + if (respout) { derbio = BIO_new_file(respout, "wb"); @@ -569,6 +743,10 @@ int MAIN(int argc, char **argv) if (resp_text) OCSP_RESPONSE_print(out, resp, 0); + /* If running as responder don't verify our own response */ + if (cbio) + goto end; + store = setup_verify(bio_err, CAfile, CApath); if(!store) goto end; if (verify_certfile) @@ -622,8 +800,12 @@ end: 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); + TXT_DB_free(rdb); BIO_free_all(cbio); BIO_free(out); OCSP_REQUEST_free(req); @@ -763,3 +945,205 @@ static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req, return 1; } + +static int make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req, TXT_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(TXT_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); + itmp = BN_bn2hex(bn); + row[DB_serial] = itmp; + BN_free(bn); + rrow=TXT_DB_get_by_index(db,DB_serial,row); + OPENSSL_free(itmp); + return rrow; + } + +/* Quick and dirty OCSP server: read in and parse input request */ + +static OCSP_REQUEST *do_responder(BIO **pcbio, char *port) + { + int have_post = 0, len; + OCSP_REQUEST *req = NULL; + char inbuf[1024]; + BIO *acbio = NULL, *bufbio = NULL, *cbio = NULL; + bufbio = BIO_new(BIO_f_buffer()); + if (!bufbio) + goto err; + acbio = BIO_new_accept(port); + 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; + } + + BIO_printf(bio_err, "Waiting for OCSP client connection...\n"); + + if (BIO_do_accept(acbio) <= 0) + { + BIO_printf(bio_err, "Error accepting connection\n"); + ERR_print_errors(bio_err); + goto err; + } + + BIO_printf(bio_err, "Connection Established\n"); + + + cbio = BIO_pop(acbio); + BIO_free_all(acbio); + acbio = NULL; + + for(;;) + { + len = BIO_gets(cbio, inbuf, 1024); + if (len <= 0) goto err; + /* Look for "POST" signalling start of query */ + if (!have_post) + { + if(strncmp(inbuf, "POST", 4)) + { + BIO_printf(bio_err, "Invalid request\n"); + goto err; + } + 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); + + *pcbio = cbio; + + if (!req) + { + BIO_printf(bio_err, "Error parsing OCSP request\n"); + ERR_print_errors(bio_err); + } + + return req; + + err: + BIO_free_all(acbio); + BIO_free_all(cbio); + BIO_free(bufbio); + OCSP_REQUEST_free(req); + return NULL; + } + +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; + } + -- 2.34.1