*
*/
#ifndef OPENSSL_NO_OCSP
-
+#define USE_SOCKETS
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
-#include "apps.h"
-#include <openssl/pem.h>
-#include <openssl/ocsp.h>
-#include <openssl/err.h>
+#include "apps.h" /* needs to be included before the openssl headers! */
+#include <openssl/e_os2.h>
#include <openssl/ssl.h>
+#include <openssl/err.h>
/* 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,
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,
+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);
-static char **lookup_serial(TXT_DB *db, ASN1_INTEGER *ser);
+static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser);
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);
+static OCSP_RESPONSE *query_responder(BIO *err, BIO *cbio, char *path,
+ OCSP_REQUEST *req, int req_timeout);
#undef PROG
#define PROG ocsp_main
BIO *acbio = NULL, *cbio = NULL;
BIO *derbio = NULL;
BIO *out = NULL;
+ int req_timeout = -1;
int req_text = 0, resp_text = 0;
long nsec = MAX_VALIDITY_PERIOD, maxage = -1;
char *CAfile = NULL, *CApath = NULL;
X509_STORE *store = NULL;
- SSL_CTX *ctx = NULL;
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 accept_count = -1;
int badarg = 0;
int i;
+ int ignore_err = 0;
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;
+ CA_DB *rdb = 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();
+ OpenSSL_add_ssl_algorithms();
args = argv + 1;
reqnames = sk_new_null();
ids = sk_OCSP_CERTID_new_null();
}
else badarg = 1;
}
+ else if (!strcmp(*args, "-timeout"))
+ {
+ if (args[1])
+ {
+ args++;
+ req_timeout = atol(*args);
+ if (req_timeout < 0)
+ {
+ BIO_printf(bio_err,
+ "Illegal timeout value %s\n",
+ *args);
+ badarg = 1;
+ }
+ }
+ else badarg = 1;
+ }
else if (!strcmp(*args, "-url"))
{
if (args[1])
}
else badarg = 1;
}
+ else if (!strcmp(*args, "-ignore_err"))
+ ignore_err = 1;
else if (!strcmp(*args, "-noverify"))
noverify = 1;
else if (!strcmp(*args, "-nonce"))
BIO_printf (bio_err, "-serial n serial number to check\n");
BIO_printf (bio_err, "-signer file certificate to sign OCSP request with\n");
BIO_printf (bio_err, "-signkey file private key to sign OCSP request with\n");
- BIO_printf (bio_err, "-sign_certs file additional certificates to include in signed request\n");
+ BIO_printf (bio_err, "-sign_other file additional certificates to include in signed request\n");
BIO_printf (bio_err, "-no_certs don't include any certificates in signed request\n");
BIO_printf (bio_err, "-req_text print text form of request\n");
BIO_printf (bio_err, "-resp_text print text form of response\n");
BIO_printf (bio_err, "-validity_period n maximum validity discrepancy in seconds\n");
BIO_printf (bio_err, "-status_age n maximum status age in seconds\n");
BIO_printf (bio_err, "-noverify don't verify response at all\n");
- BIO_printf (bio_err, "-verify_certs file additional certificates to search for signer\n");
+ BIO_printf (bio_err, "-verify_other file additional certificates to search for signer\n");
BIO_printf (bio_err, "-trust_other don't verify additional certificates\n");
BIO_printf (bio_err, "-no_intern don't search certificates contained in response for signer\n");
- BIO_printf (bio_err, "-no_sig_verify don't check signature on response\n");
+ BIO_printf (bio_err, "-no_signature_verify don't check signature on response\n");
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");
if (ridx_filename && !rdb)
{
- 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;
+ rdb = load_index(ridx_filename, NULL);
+ if (!rdb) goto end;
+ if (!index_index(rdb)) goto end;
}
if (rdb)
else if (host)
{
#ifndef OPENSSL_NO_SOCK
- cbio = BIO_new_connect(host);
+ resp = process_responder(bio_err, req, host, path,
+ port, use_ssl, req_timeout);
+ if (!resp)
+ goto end;
#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;
- ctx = SSL_CTX_new(SSLv23_client_method());
- 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)
{
if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL)
{
- BIO_printf(out, "Responder Error: %s (%ld)\n",
+ 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(i <= 0)
{
- BIO_printf(bio_err, "Response Verify Failure\n", i);
+ BIO_printf(bio_err, "Response Verify Failure\n");
ERR_print_errors(bio_err);
}
else
X509_free(cert);
X509_free(rsigner);
X509_free(rca_cert);
- TXT_DB_free(rdb);
+ free_index(rdb);
BIO_free_all(cbio);
BIO_free_all(acbio);
BIO_free(out);
OPENSSL_free(host);
OPENSSL_free(port);
OPENSSL_free(path);
- SSL_CTX_free(ctx);
}
OPENSSL_EXIT(ret);
}
-static int make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req, TXT_DB *db,
+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)
}
-static char **lookup_serial(TXT_DB *db, ASN1_INTEGER *ser)
+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);
+ OPENSSL_assert(bn); /* FIXME: should report an error at this point and abort */
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);
+ rrow=TXT_DB_get_by_index(db->db,DB_serial,row);
OPENSSL_free(itmp);
return rrow;
}
return 0;
BIO_printf(cbio, http_resp, i2d_OCSP_RESPONSE(resp, NULL));
i2d_OCSP_RESPONSE_bio(cbio, resp);
- BIO_flush(cbio);
+ (void)BIO_flush(cbio);
return 1;
}
+static OCSP_RESPONSE *query_responder(BIO *err, BIO *cbio, char *path,
+ OCSP_REQUEST *req, int req_timeout)
+ {
+ int fd;
+ int rv;
+ OCSP_REQ_CTX *ctx = NULL;
+ OCSP_RESPONSE *rsp = NULL;
+ fd_set confds;
+ struct timeval tv;
+
+ if (req_timeout != -1)
+ BIO_set_nbio(cbio, 1);
+
+ rv = BIO_do_connect(cbio);
+
+ if ((rv <= 0) && ((req_timeout == -1) || !BIO_should_retry(cbio)))
+ {
+ BIO_puts(err, "Error connecting BIO\n");
+ return NULL;
+ }
+
+ if (req_timeout == -1)
+ return OCSP_sendreq_bio(cbio, path, req);
+
+ if (BIO_get_fd(cbio, &fd) <= 0)
+ {
+ BIO_puts(err, "Can't get connection fd\n");
+ goto err;
+ }
+
+ if (rv <= 0)
+ {
+ FD_ZERO(&confds);
+ openssl_fdset(fd, &confds);
+ tv.tv_usec = 0;
+ tv.tv_sec = req_timeout;
+ rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv);
+ if (rv == 0)
+ {
+ BIO_puts(err, "Timeout on connect\n");
+ return NULL;
+ }
+ }
+
+
+ ctx = OCSP_sendreq_new(cbio, path, req, -1);
+ if (!ctx)
+ return NULL;
+
+ for (;;)
+ {
+ rv = OCSP_sendreq_nbio(&rsp, ctx);
+ if (rv != -1)
+ break;
+ FD_ZERO(&confds);
+ openssl_fdset(fd, &confds);
+ tv.tv_usec = 0;
+ tv.tv_sec = req_timeout;
+ if (BIO_should_read(cbio))
+ rv = select(fd + 1, (void *)&confds, NULL, NULL, &tv);
+ else if (BIO_should_write(cbio))
+ rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv);
+ else
+ {
+ BIO_puts(err, "Unexpected retry condition\n");
+ goto err;
+ }
+ if (rv == 0)
+ {
+ BIO_puts(err, "Timeout on request\n");
+ break;
+ }
+ if (rv == -1)
+ {
+ BIO_puts(err, "Select error\n");
+ break;
+ }
+
+ }
+ err:
+ if (ctx)
+ OCSP_REQ_CTX_free(ctx);
+
+ return rsp;
+ }
+
+OCSP_RESPONSE *process_responder(BIO *err, OCSP_REQUEST *req,
+ char *host, char *path, char *port, int use_ssl,
+ int req_timeout)
+ {
+ BIO *cbio = NULL;
+ SSL_CTX *ctx = NULL;
+ OCSP_RESPONSE *resp = NULL;
+ cbio = BIO_new_connect(host);
+ if (!cbio)
+ {
+ BIO_printf(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(err, "SSL is disabled\n");
+ goto end;
+#endif
+ if (ctx == NULL)
+ {
+ BIO_printf(err, "Error creating SSL context.\n");
+ goto end;
+ }
+ SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
+ sbio = BIO_new_ssl(ctx, 1);
+ cbio = BIO_push(sbio, cbio);
+ }
+ resp = query_responder(err, cbio, path, req, req_timeout);
+ if (!resp)
+ BIO_printf(bio_err, "Error querying OCSP responsder\n");
+ end:
+ if (ctx)
+ SSL_CTX_free(ctx);
+ if (cbio)
+ BIO_free_all(cbio);
+ return resp;
+ }
+
#endif