Commit 73758d43 authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

Additional functionality in ocsp utility: print summary

of status info. Check nonce values. Option to disable
verify. Update usage message.

Rename status to string functions and make them global.
parent 90f63e8f
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -3,6 +3,14 @@

 Changes between 0.9.6 and 0.9.7  [xx XXX 2000]

  *) Add summary printout to ocsp utility. The various functions which
     convert status values to strings have been renamed to:
     OCSP_response_status_str(), OCSP_cert_status_str() and
     OCSP_crl_reason_str() and are no longer static. New options
     to verify nonce values and to disable verification. OCSP response
     printout format cleaned up.
     [Steve Henson]

  *) Add additional OCSP certificate checks. These are those specified
     in RFC2560. This consists of two separate checks: the CA of the
     certificate being checked must either be the OCSP signer certificate
+121 −16
Original line number Diff line number Diff line
@@ -63,8 +63,12 @@
#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
@@ -79,7 +83,7 @@ int MAIN(int argc, char **argv)
	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;
@@ -94,9 +98,13 @@ int MAIN(int argc, char **argv)
	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"))
@@ -117,6 +125,8 @@ int MAIN(int argc, char **argv)
				}
			else badarg = 1;
			}
		else if (!strcmp(*args, "-noverify"))
			noverify = 1;
		else if (!strcmp(*args, "-nonce"))
			add_nonce = 2;
		else if (!strcmp(*args, "-no_nonce"))
@@ -230,7 +240,9 @@ int MAIN(int argc, char **argv)
				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;
@@ -240,7 +252,9 @@ int MAIN(int argc, char **argv)
			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;
@@ -274,6 +288,9 @@ int MAIN(int argc, char **argv)
		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;
		}

@@ -311,7 +328,7 @@ int MAIN(int argc, char **argv)
		goto end;
		}

	if (req) OCSP_request_add1_nonce(req, NULL, -1);
	if (req && add_nonce) OCSP_request_add1_nonce(req, NULL, -1);

	if (signfile)
		{
@@ -406,6 +423,16 @@ int MAIN(int argc, char **argv)
		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);
@@ -413,16 +440,35 @@ int MAIN(int argc, char **argv)

	bs = OCSP_response_get1_basic(resp);

	if (!bs)
		{
		BIO_printf(bio_err, "Error parsing response\n");
		goto end;
		}

	if (!noverify)
		{
		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 error (%d)\n", i);
			BIO_printf(bio_err, "Response Verify Failure\n", i);
			ERR_print_errors(bio_err);
			}
		else
			BIO_printf(bio_err, "Response verify OK\n");

		}

	if (!print_ocsp_summary(out, bs, req, reqnames, ids))
		goto end;

	ret = 0;

end:
@@ -437,11 +483,14 @@ end:
	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)
@@ -452,7 +501,7 @@ static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *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;

@@ -461,7 +510,8 @@ static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *issuer)
	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;
@@ -484,7 +534,7 @@ static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, X509 *issuer)
		}
	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;

@@ -492,3 +542,58 @@ static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, X509 *issuer)
	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;
	}
+6 −0
Original line number Diff line number Diff line
@@ -100,6 +100,8 @@ typedef struct ocsp_cert_id_st
	ASN1_INTEGER *serialNumber;
	} OCSP_CERTID;

DECLARE_STACK_OF(OCSP_CERTID)

/*   Request ::=     SEQUENCE {
 *       reqCert                    CertID,
 *       singleRequestExtensions    [0] EXPLICIT Extensions OPTIONAL }
@@ -538,6 +540,10 @@ DECLARE_ASN1_FUNCTIONS(OCSP_REQINFO)
DECLARE_ASN1_FUNCTIONS(OCSP_CRLID)
DECLARE_ASN1_FUNCTIONS(OCSP_SERVICELOC)

char *OCSP_response_status_str(long s);
char *OCSP_cert_status_str(long s);
char *OCSP_crl_reason_str(long s);

int OCSP_REQUEST_print(BIO *bp, OCSP_REQUEST* a, unsigned long flags);
int OCSP_RESPONSE_print(BIO *bp, OCSP_RESPONSE* o, unsigned long flags);

+8 −7
Original line number Diff line number Diff line
@@ -97,7 +97,7 @@ static char *table2string(long s, OCSP_TBLSTR *ts, int len)
	return "(UNKNOWN)";
}

static char* ocspResponseStatus2string(long s)
char *OCSP_response_status_str(long s)
        {
	static OCSP_TBLSTR rstat_tbl[] = {
	        { OCSP_RESPONSE_STATUS_SUCCESSFUL, "successful" },
@@ -109,7 +109,7 @@ static char* ocspResponseStatus2string(long s)
	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" },
@@ -118,7 +118,7 @@ static char* ocspCertStatus2string(long s)
	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" },
@@ -195,7 +195,7 @@ int OCSP_RESPONSE_print(BIO *bp, OCSP_RESPONSE* o, unsigned long flags)
	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;
@@ -237,8 +237,8 @@ int OCSP_RESPONSE_print(BIO *bp, OCSP_RESPONSE* o, unsigned long flags)
		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)
		        {
@@ -253,7 +253,7 @@ int OCSP_RESPONSE_print(BIO *bp, OCSP_RESPONSE* o, unsigned long flags)
				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;
				}
			}
@@ -271,6 +271,7 @@ int OCSP_RESPONSE_print(BIO *bp, OCSP_RESPONSE* o, unsigned long flags)
					"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))
+1 −1
Original line number Diff line number Diff line
@@ -144,7 +144,7 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,

	end:
	if(chain) sk_X509_pop_free(chain, X509_free);
	return 1;
	return ret;
	}


Loading