Additional functionality in ocsp utility: print summary
authorDr. Stephen Henson <steve@openssl.org>
Fri, 19 Jan 2001 01:32:23 +0000 (01:32 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Fri, 19 Jan 2001 01:32:23 +0000 (01:32 +0000)
of status info. Check nonce values. Option to disable
verify. Update usage message.

Rename status to string functions and make them global.

CHANGES
apps/ocsp.c
crypto/ocsp/ocsp.h
crypto/ocsp/ocsp_prn.c
crypto/ocsp/ocsp_vfy.c
crypto/stack/safestack.h

diff --git a/CHANGES b/CHANGES
index dedd7c328724c86c859816dd4e627ce837a5d633..59dc558f903d12fe693fd668a071b422801b6d7a 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -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
index bea16ebb711763f7fbe162abeebfb4663e575d2f..f23aa4c52a856b397f794d79964cc83dd61c000c 100644 (file)
 #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,15 +440,34 @@ int MAIN(int argc, char **argv)
 
        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;
 
@@ -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;
+       }
+
index ef36ba991080b67b86de40f7af33bdcf408f38fa..0c643e1a8821823e35bdd9465779577a6448ee7e 100644 (file)
@@ -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);
 
index fc6318351798a06d7416f2556075027dadf522f3..4b7bc287695899bf00880aa7c98590dc24a087b3 100644 (file)
@@ -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))
index b656609ee8d53b473a182e5696fa3e69f94be2eb..8868c980cbaadf9d3ed7b117bc7d2e262e92ab64 100644 (file)
@@ -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;
        }
 
 
index 67bce3f5ea52ec542ffee5ad67f645fdb8a84c2b..fe77eeaa187897ecbc1173c55898f54f07449649 100644 (file)
@@ -504,6 +504,26 @@ STACK_OF(type) \
 #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))