#include <stdio.h>
#include <string.h>
+#include "apps.h"
#include <openssl/pem.h>
#include <openssl/ocsp.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
-#include "apps.h"
/* Maximum leeway in validity period: default 5 minutes */
#define MAX_VALIDITY_PERIOD (5 * 60)
int nmin, int ndays);
static char **lookup_serial(TXT_DB *db, ASN1_INTEGER *ser);
-static OCSP_REQUEST *do_responder(BIO **cbio, char *port);
+static BIO *init_responder(char *port);
+static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, char *port);
static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp);
#undef PROG
X509 *issuer = NULL, *cert = NULL;
X509 *signer = NULL, *rsigner = NULL;
EVP_PKEY *key = NULL, *rkey = NULL;
- BIO *cbio = NULL, *derbio = NULL;
+ BIO *acbio = NULL, *cbio = NULL;
+ BIO *derbio = NULL;
BIO *out = NULL;
int req_text = 0, resp_text = 0;
long nsec = MAX_VALIDITY_PERIOD, maxage = -1;
char *sign_certfile = NULL, *verify_certfile = NULL, *rcertfile = NULL;
unsigned long sign_flags = 0, verify_flags = 0, rflags = 0;
int ret = 1;
+ int accept_count = -1;
int badarg = 0;
int i;
STACK *reqnames = NULL;
int nmin = 0, ndays = -1;
if (bio_err == NULL) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
+
+ if (!load_config(bio_err, NULL))
+ goto end;
SSL_load_error_strings();
args = argv + 1;
reqnames = sk_new_null();
add_nonce = 2;
else if (!strcmp(*args, "-no_nonce"))
add_nonce = 0;
- else if (!strcmp(*args, "-responder_no_certs"))
+ else if (!strcmp(*args, "-resp_no_certs"))
rflags |= OCSP_NOCERTS;
- else if (!strcmp(*args, "-responder_no_time"))
- rflags |= OCSP_NOTIME;
- else if (!strcmp(*args, "-responder_key_id"))
+ else if (!strcmp(*args, "-resp_key_id"))
rflags |= OCSP_RESPID_KEY;
else if (!strcmp(*args, "-no_certs"))
sign_flags |= OCSP_NOCERTS;
ndays = 0;
else badarg = 1;
}
+ else if (!strcmp (*args, "-nrequest"))
+ {
+ if (args[1])
+ {
+ args++;
+ accept_count = atol(*args);
+ if (accept_count < 0)
+ {
+ BIO_printf(bio_err,
+ "Illegal accept count %s\n",
+ *args);
+ badarg = 1;
+ }
+ }
+ else badarg = 1;
+ }
else if (!strcmp (*args, "-ndays"))
{
if (args[1])
BIO_printf (bio_err, "-no_cert_verify don't check signing certificate\n");
BIO_printf (bio_err, "-no_chain don't chain verify response\n");
BIO_printf (bio_err, "-no_cert_checks don't do additional checks on signing certificate\n");
+ BIO_printf (bio_err, "-port num port to run responder on\n");
+ BIO_printf (bio_err, "-index file certificate status index file\n");
+ BIO_printf (bio_err, "-CA file CA certificate\n");
+ BIO_printf (bio_err, "-rsigner file responder certificate to sign responses with\n");
+ BIO_printf (bio_err, "-rkey file responder key to sign responses with\n");
+ BIO_printf (bio_err, "-rother file other certificates to include in response\n");
+ BIO_printf (bio_err, "-resp_no_certs don't include any certificates in response\n");
+ BIO_printf (bio_err, "-nmin n number of minutes before next update\n");
+ BIO_printf (bio_err, "-ndays n number of days before next update\n");
+ BIO_printf (bio_err, "-resp_key_id identify reponse by signing certificate key ID\n");
+ BIO_printf (bio_err, "-nrequest n number of requests to accept (default unlimited)\n");
goto end;
}
if (!req && port)
{
- req = do_responder(&cbio, port);
- if (!req && !cbio)
+ acbio = init_responder(port);
+ if (!acbio)
goto end;
- if (!req && cbio)
+ }
+
+ if (rsignfile && !rdb)
+ {
+ if (!rkeyfile) rkeyfile = rsignfile;
+ rsigner = load_cert(bio_err, rsignfile, FORMAT_PEM,
+ NULL, e, "responder certificate");
+ if (!rsigner)
+ {
+ BIO_printf(bio_err, "Error loading responder certificate\n");
+ goto end;
+ }
+ rca_cert = load_cert(bio_err, rca_filename, FORMAT_PEM,
+ NULL, e, "CA certificate");
+ if (rcertfile)
+ {
+ rother = load_certs(bio_err, rcertfile, FORMAT_PEM,
+ NULL, e, "responder other certificates");
+ if (!rother) goto end;
+ }
+ rkey = load_key(bio_err, rkeyfile, FORMAT_PEM, 0, NULL, NULL,
+ "responder private key");
+ if (!rkey)
+ goto end;
+ }
+ 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);
NULL, e, "signer certificates");
if (!sign_other) goto end;
}
- key = load_key(bio_err, keyfile, FORMAT_PEM, NULL, NULL,
+ key = load_key(bio_err, keyfile, FORMAT_PEM, 0, NULL, NULL,
"signer private key");
if (!key)
goto end;
if (req_text && req) OCSP_REQUEST_print(out, req, 0);
- if (rsignfile)
+ if (reqout)
{
- if (!rkeyfile) rkeyfile = rsignfile;
- rsigner = load_cert(bio_err, rsignfile, FORMAT_PEM,
- NULL, e, "responder certificate");
- if (!rsigner)
+ derbio = BIO_new_file(reqout, "wb");
+ if(!derbio)
{
- BIO_printf(bio_err, "Error loading responder certificate\n");
+ BIO_printf(bio_err, "Error opening file %s\n", reqout);
goto end;
}
- 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;
+ i2d_OCSP_REQUEST_bio(derbio, req);
+ BIO_free(derbio);
}
if (ridx_filename && (!rkey || !rsigner || !rca_cert))
goto end;
}
- if (ridx_filename)
+ if (ridx_filename && !rdb)
{
BIO *db_bio = NULL;
db_bio = BIO_new_file(ridx_filename, "r");
}
if (!make_serial_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);
/* 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;
+ }
- store = setup_verify(bio_err, CAfile, CApath);
- if(!store) 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,
X509_free(rca_cert);
TXT_DB_free(rdb);
BIO_free_all(cbio);
+ BIO_free_all(acbio);
BIO_free(out);
OCSP_REQUEST_free(req);
OCSP_RESPONSE_free(resp);
SSL_CTX_free(ctx);
}
- EXIT(ret);
+ OPENSSL_EXIT(ret);
}
static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *issuer,
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);
+ 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_serial,row);
/* Quick and dirty OCSP server: read in and parse input request */
-static OCSP_REQUEST *do_responder(BIO **pcbio, char *port)
+static BIO *init_responder(char *port)
{
- int have_post = 0, len;
- OCSP_REQUEST *req = NULL;
- char inbuf[1024];
- BIO *acbio = NULL, *bufbio = NULL, *cbio = NULL;
+ BIO *acbio = NULL, *bufbio = NULL;
bufbio = BIO_new(BIO_f_buffer());
if (!bufbio)
goto err;
goto err;
}
- BIO_printf(bio_err, "Waiting for OCSP client connection...\n");
+ 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);
- goto err;
+ return 0;
}
- BIO_printf(bio_err, "Connection Established\n");
-
-
cbio = BIO_pop(acbio);
- BIO_free_all(acbio);
- acbio = NULL;
+ *pcbio = cbio;
for(;;)
{
- len = BIO_gets(cbio, inbuf, 1024);
- if (len <= 0) goto err;
+ 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");
- goto err;
+ return 1;
}
have_post = 1;
}
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;
+ *preq = req;
+
+ return 1;
- 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)