#include <openssl/err.h>
#include "apps.h"
-static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *issuer);
-static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, X509 *issuer);
+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_OF(OCSP_CERTID) *ids);
+static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
+ STACK *names, STACK_OF(OCSP_CERTID) *ids);
#undef PROG
#define PROG ocsp_main
char *reqout = NULL, *respout = NULL;
char *signfile = NULL, *keyfile = NULL;
char *outfile = NULL;
- int add_nonce = 1;
+ int add_nonce = 1, noverify = 0;
OCSP_REQUEST *req = NULL;
OCSP_RESPONSE *resp = NULL;
OCSP_BASICRESP *bs = NULL;
int ret = 1;
int badarg = 0;
int i;
+ STACK *reqnames = NULL;
+ STACK_OF(OCSP_CERTID) *ids = NULL;
if (bio_err == NULL) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
ERR_load_crypto_strings();
args = argv + 1;
+ reqnames = sk_new_null();
+ ids = sk_OCSP_CERTID_new_null();
while (!badarg && *args && *args[0] == '-')
{
if (!strcmp(*args, "-out"))
}
else badarg = 1;
}
+ else if (!strcmp(*args, "-noverify"))
+ noverify = 1;
else if (!strcmp(*args, "-nonce"))
add_nonce = 2;
else if (!strcmp(*args, "-no_nonce"))
X509_free(cert);
cert = load_cert(bio_err, *args, FORMAT_PEM);
if(!cert) goto end;
- if(!add_ocsp_cert(&req, cert, issuer))
+ if(!add_ocsp_cert(&req, cert, issuer, ids))
+ goto end;
+ if(!sk_push(reqnames, *args))
goto end;
}
else badarg = 1;
if (args[1])
{
args++;
- if(!add_ocsp_serial(&req, *args, issuer))
+ if(!add_ocsp_serial(&req, *args, issuer, ids))
+ goto end;
+ if(!sk_push(reqnames, *args))
goto end;
}
else badarg = 1;
BIO_printf (bio_err, "-no_nonce don't add OCSP nonce to request\n");
BIO_printf (bio_err, "-host host:n send OCSP request to host on port n\n");
BIO_printf (bio_err, "-path path to use in OCSP request\n");
+ BIO_printf (bio_err, "-CApath dir trusted certificates directory\n");
+ BIO_printf (bio_err, "-CAfile file trusted certificates file\n");
+ BIO_printf (bio_err, "-noverify don't verify response\n");
goto end;
}
goto end;
}
- if (req) OCSP_request_add1_nonce(req, NULL, -1);
+ if (req && add_nonce) OCSP_request_add1_nonce(req, NULL, -1);
if (signfile)
{
BIO_free(derbio);
}
+ i = OCSP_response_status(resp);
+
+ if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL)
+ {
+ BIO_printf(out, "Responder Error: %s (%ld)\n",
+ OCSP_response_status_str(i), i);
+ ret = 0;
+ goto end;
+ }
+
if (resp_text) OCSP_RESPONSE_print(out, resp, 0);
store = setup_verify(bio_err, CAfile, CApath);
bs = OCSP_response_get1_basic(resp);
- i = OCSP_basic_verify(bs, NULL, store, 0);
+ if (!bs)
+ {
+ BIO_printf(bio_err, "Error parsing response\n");
+ goto end;
+ }
- if(i <= 0)
+ if (!noverify)
{
- BIO_printf(bio_err, "Response verify error (%d)\n", i);
- ERR_print_errors(bio_err);
+ if (req && (OCSP_check_nonce(req, bs) <= 0))
+ {
+ BIO_printf(bio_err, "Nonce Verify error\n");
+ goto end;
+ }
+
+ i = OCSP_basic_verify(bs, NULL, store, 0);
+
+ if(i <= 0)
+ {
+ BIO_printf(bio_err, "Response Verify Failure\n", i);
+ ERR_print_errors(bio_err);
+ }
+ else
+ BIO_printf(bio_err, "Response verify OK\n");
+
}
- else
- BIO_printf(bio_err, "Response verify OK\n");
+
+ if (!print_ocsp_summary(out, bs, req, reqnames, ids))
+ goto end;
ret = 0;
OCSP_REQUEST_free(req);
OCSP_RESPONSE_free(resp);
OCSP_BASICRESP_free(bs);
+ sk_free(reqnames);
+ sk_OCSP_CERTID_free(ids);
EXIT(ret);
}
-static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *issuer)
+static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *issuer,
+ STACK_OF(OCSP_CERTID) *ids)
{
OCSP_CERTID *id;
if(!issuer)
if(!*req) *req = OCSP_REQUEST_new();
if(!*req) goto err;
id = OCSP_cert_to_id(NULL, cert, issuer);
- if(!id) goto err;
+ if(!id || !sk_OCSP_CERTID_push(ids, id)) goto err;
if(!OCSP_request_add0_id(*req, id)) goto err;
return 1;
return 0;
}
-static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, X509 *issuer)
+static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, X509 *issuer,
+ STACK_OF(OCSP_CERTID) *ids)
{
OCSP_CERTID *id;
X509_NAME *iname;
}
id = OCSP_cert_id_new(EVP_sha1(), iname, ikey, sno);
ASN1_INTEGER_free(sno);
- if(!id) goto err;
+ if(!id || !sk_OCSP_CERTID_push(ids, id)) goto err;
if(!OCSP_request_add0_id(*req, id)) goto err;
return 1;
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)
+ {
+ 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;
+ }
+ 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, thisupd);
+ BIO_puts(out, "\n");
+ }
+
+ if (status != V_OCSP_CERTSTATUS_REVOKED)
+ continue;
+
+ if (reason > 0)
+ 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;
+ }
+
return "(UNKNOWN)";
}
-static char* ocspResponseStatus2string(long s)
+char *OCSP_response_status_str(long s)
{
static OCSP_TBLSTR rstat_tbl[] = {
{ OCSP_RESPONSE_STATUS_SUCCESSFUL, "successful" },
return table2string(s, rstat_tbl, 6);
}
-static char* ocspCertStatus2string(long s)
+char *OCSP_cert_status_str(long s)
{
static OCSP_TBLSTR cstat_tbl[] = {
{ V_OCSP_CERTSTATUS_GOOD, "good" },
return table2string(s, cstat_tbl, 3);
}
-static char * cRLReason2string(long s)
+char *OCSP_crl_reason_str(long s)
{
OCSP_TBLSTR reason_tbl[] = {
{ OCSP_REVOKED_STATUS_UNSPECIFIED, "unspecified" },
if (BIO_puts(bp,"OCSP Response Data:\n") <= 0) goto err;
l=ASN1_ENUMERATED_get(o->responseStatus);
if (BIO_printf(bp," OCSP Response Status: %s (0x%x)\n",
- ocspResponseStatus2string(l), l) <= 0) goto err;
+ OCSP_response_status_str(l), l) <= 0) goto err;
if (rb == NULL) return 1;
if (BIO_puts(bp," Response Type: ") <= 0)
goto err;
cid = single->certId;
if(ocsp_certid_print(bp, cid, 4) <= 0) goto err;
cst = single->certStatus;
- if (BIO_printf(bp,"\n Cert Status: %s",
- ocspCertStatus2string(cst->type)) <= 0)
+ if (BIO_printf(bp," Cert Status: %s",
+ OCSP_cert_status_str(cst->type)) <= 0)
goto err;
if (cst->type == V_OCSP_CERTSTATUS_REVOKED)
{
l=ASN1_ENUMERATED_get(rev->revocationReason);
if (BIO_printf(bp,
"\n Revocation Reason: %s (0x%x)",
- cRLReason2string(l), l) <= 0)
+ OCSP_crl_reason_str(l), l) <= 0)
goto err;
}
}
"Response Single Extensions",
single->singleExtensions, flags, 8))
goto err;
+ if (!BIO_write(bp,"\n",1)) goto err;
}
if (!X509V3_extensions_print(bp, "Response Extensions",
rd->responseExtensions, flags, 4))
#define sk_NAME_FUNCS_pop(st) SKM_sk_pop(NAME_FUNCS, (st))
#define sk_NAME_FUNCS_sort(st) SKM_sk_sort(NAME_FUNCS, (st))
+#define sk_OCSP_CERTID_new(st) SKM_sk_new(OCSP_CERTID, (st))
+#define sk_OCSP_CERTID_new_null() SKM_sk_new_null(OCSP_CERTID)
+#define sk_OCSP_CERTID_free(st) SKM_sk_free(OCSP_CERTID, (st))
+#define sk_OCSP_CERTID_num(st) SKM_sk_num(OCSP_CERTID, (st))
+#define sk_OCSP_CERTID_value(st, i) SKM_sk_value(OCSP_CERTID, (st), (i))
+#define sk_OCSP_CERTID_set(st, i, val) SKM_sk_set(OCSP_CERTID, (st), (i), (val))
+#define sk_OCSP_CERTID_zero(st) SKM_sk_zero(OCSP_CERTID, (st))
+#define sk_OCSP_CERTID_push(st, val) SKM_sk_push(OCSP_CERTID, (st), (val))
+#define sk_OCSP_CERTID_unshift(st, val) SKM_sk_unshift(OCSP_CERTID, (st), (val))
+#define sk_OCSP_CERTID_find(st, val) SKM_sk_find(OCSP_CERTID, (st), (val))
+#define sk_OCSP_CERTID_delete(st, i) SKM_sk_delete(OCSP_CERTID, (st), (i))
+#define sk_OCSP_CERTID_delete_ptr(st, ptr) SKM_sk_delete_ptr(OCSP_CERTID, (st), (ptr))
+#define sk_OCSP_CERTID_insert(st, val, i) SKM_sk_insert(OCSP_CERTID, (st), (val), (i))
+#define sk_OCSP_CERTID_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(OCSP_CERTID, (st), (cmp))
+#define sk_OCSP_CERTID_dup(st) SKM_sk_dup(OCSP_CERTID, st)
+#define sk_OCSP_CERTID_pop_free(st, free_func) SKM_sk_pop_free(OCSP_CERTID, (st), (free_func))
+#define sk_OCSP_CERTID_shift(st) SKM_sk_shift(OCSP_CERTID, (st))
+#define sk_OCSP_CERTID_pop(st) SKM_sk_pop(OCSP_CERTID, (st))
+#define sk_OCSP_CERTID_sort(st) SKM_sk_sort(OCSP_CERTID, (st))
+
#define sk_OCSP_ONEREQ_new(st) SKM_sk_new(OCSP_ONEREQ, (st))
#define sk_OCSP_ONEREQ_new_null() SKM_sk_new_null(OCSP_ONEREQ)
#define sk_OCSP_ONEREQ_free(st) SKM_sk_free(OCSP_ONEREQ, (st))