New function OCSP_parse_url() and -url option for ocsp utility.
[openssl.git] / apps / ocsp.c
1 /* ocsp.c */
2 /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
3  * project 2000.
4  */
5 /* ====================================================================
6  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer. 
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58
59 #include <stdio.h>
60 #include <string.h>
61 #include <openssl/pem.h>
62 #include <openssl/ocsp.h>
63 #include <openssl/err.h>
64 #include "apps.h"
65
66 static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *issuer,
67                                 STACK_OF(OCSP_CERTID) *ids);
68 static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, X509 *issuer,
69                                 STACK_OF(OCSP_CERTID) *ids);
70 static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
71                                 STACK *names, STACK_OF(OCSP_CERTID) *ids);
72
73 #undef PROG
74 #define PROG ocsp_main
75
76 int MAIN(int, char **);
77
78 int MAIN(int argc, char **argv)
79         {
80         char **args;
81         char *host = NULL, *port = NULL, *path = "/";
82         char *reqin = NULL, *respin = NULL;
83         char *reqout = NULL, *respout = NULL;
84         char *signfile = NULL, *keyfile = NULL;
85         char *outfile = NULL;
86         int add_nonce = 1, noverify = 0, use_ssl = -1;
87         OCSP_REQUEST *req = NULL;
88         OCSP_RESPONSE *resp = NULL;
89         OCSP_BASICRESP *bs = NULL;
90         X509 *issuer = NULL, *cert = NULL;
91         X509 *signer = NULL;
92         EVP_PKEY *key = NULL;
93         BIO *cbio = NULL, *derbio = NULL;
94         BIO *out = NULL;
95         int req_text = 0, resp_text = 0;
96         char *CAfile = NULL, *CApath = NULL;
97         X509_STORE *store = NULL;
98         STACK_OF(X509) *sign_other = NULL, *verify_other = NULL;
99         char *sign_certfile = NULL, *verify_certfile = NULL;
100         unsigned long sign_flags = 0, verify_flags = 0;
101         int ret = 1;
102         int badarg = 0;
103         int i;
104         STACK *reqnames = NULL;
105         STACK_OF(OCSP_CERTID) *ids = NULL;
106         if (bio_err == NULL) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
107         ERR_load_crypto_strings();
108         args = argv + 1;
109         reqnames = sk_new_null();
110         ids = sk_OCSP_CERTID_new_null();
111         while (!badarg && *args && *args[0] == '-')
112                 {
113                 if (!strcmp(*args, "-out"))
114                         {
115                         if (args[1])
116                                 {
117                                 args++;
118                                 outfile = *args;
119                                 }
120                         else badarg = 1;
121                         }
122                 else if (!strcmp(*args, "-url"))
123                         {
124                         if (args[1])
125                                 {
126                                 args++;
127                                 if (!OCSP_parse_url(*args, &host, &port, &path, &use_ssl))
128                                         {
129                                         BIO_printf(bio_err, "Error parsing URL\n");
130                                         badarg = 1;
131                                         }
132                                 }
133                         else badarg = 1;
134                         }
135                 else if (!strcmp(*args, "-host"))
136                         {
137                         if (args[1])
138                                 {
139                                 args++;
140                                 host = *args;
141                                 }
142                         else badarg = 1;
143                         }
144                 else if (!strcmp(*args, "-noverify"))
145                         noverify = 1;
146                 else if (!strcmp(*args, "-nonce"))
147                         add_nonce = 2;
148                 else if (!strcmp(*args, "-no_nonce"))
149                         add_nonce = 0;
150                 else if (!strcmp(*args, "-no_certs"))
151                         sign_flags |= OCSP_NOCERTS;
152                 else if (!strcmp(*args, "-no_signature_verify"))
153                         verify_flags |= OCSP_NOSIGS;
154                 else if (!strcmp(*args, "-no_cert_verify"))
155                         verify_flags |= OCSP_NOVERIFY;
156                 else if (!strcmp(*args, "-no_chain"))
157                         verify_flags |= OCSP_NOCHAIN;
158                 else if (!strcmp(*args, "-no_cert_checks"))
159                         verify_flags |= OCSP_NOCHECKS;
160                 else if (!strcmp(*args, "-no_explicit"))
161                         verify_flags |= OCSP_NOEXPLICIT;
162                 else if (!strcmp(*args, "-trust_other"))
163                         verify_flags |= OCSP_TRUSTOTHER;
164                 else if (!strcmp(*args, "-no_intern"))
165                         verify_flags |= OCSP_NOINTERN;
166                 else if (!strcmp(*args, "-text"))
167                         {
168                         req_text = 1;
169                         resp_text = 1;
170                         }
171                 else if (!strcmp(*args, "-req_text"))
172                         req_text = 1;
173                 else if (!strcmp(*args, "-resp_text"))
174                         resp_text = 1;
175                 else if (!strcmp(*args, "-reqin"))
176                         {
177                         if (args[1])
178                                 {
179                                 args++;
180                                 reqin = *args;
181                                 }
182                         else badarg = 1;
183                         }
184                 else if (!strcmp(*args, "-respin"))
185                         {
186                         if (args[1])
187                                 {
188                                 args++;
189                                 respin = *args;
190                                 }
191                         else badarg = 1;
192                         }
193                 else if (!strcmp(*args, "-signer"))
194                         {
195                         if (args[1])
196                                 {
197                                 args++;
198                                 signfile = *args;
199                                 }
200                         else badarg = 1;
201                         }
202                 else if (!strcmp (*args, "-VAfile"))
203                         {
204                         if (args[1])
205                                 {
206                                 args++;
207                                 verify_certfile = *args;
208                                 verify_flags |= OCSP_TRUSTOTHER;
209                                 }
210                         else badarg = 1;
211                         }
212                 else if (!strcmp(*args, "-sign_other"))
213                         {
214                         if (args[1])
215                                 {
216                                 args++;
217                                 sign_certfile = *args;
218                                 }
219                         else badarg = 1;
220                         }
221                 else if (!strcmp(*args, "-verify_other"))
222                         {
223                         if (args[1])
224                                 {
225                                 args++;
226                                 verify_certfile = *args;
227                                 }
228                         else badarg = 1;
229                         }
230                 else if (!strcmp (*args, "-CAfile"))
231                         {
232                         if (args[1])
233                                 {
234                                 args++;
235                                 CAfile = *args;
236                                 }
237                         else badarg = 1;
238                         }
239                 else if (!strcmp (*args, "-CApath"))
240                         {
241                         if (args[1])
242                                 {
243                                 args++;
244                                 CApath = *args;
245                                 }
246                         else badarg = 1;
247                         }
248                  else if (!strcmp(*args, "-signkey"))
249                         {
250                         if (args[1])
251                                 {
252                                 args++;
253                                 keyfile = *args;
254                                 }
255                         else badarg = 1;
256                         }
257                 else if (!strcmp(*args, "-reqout"))
258                         {
259                         if (args[1])
260                                 {
261                                 args++;
262                                 reqout = *args;
263                                 }
264                         else badarg = 1;
265                         }
266                 else if (!strcmp(*args, "-respout"))
267                         {
268                         if (args[1])
269                                 {
270                                 args++;
271                                 respout = *args;
272                                 }
273                         else badarg = 1;
274                         }
275                  else if (!strcmp(*args, "-path"))
276                         {
277                         if (args[1])
278                                 {
279                                 args++;
280                                 path = *args;
281                                 }
282                         else badarg = 1;
283                         }
284                 else if (!strcmp(*args, "-issuer"))
285                         {
286                         if (args[1])
287                                 {
288                                 args++;
289                                 X509_free(issuer);
290                                 issuer = load_cert(bio_err, *args, FORMAT_PEM);
291                                 if(!issuer) goto end;
292                                 }
293                         else badarg = 1;
294                         }
295                 else if (!strcmp (*args, "-cert"))
296                         {
297                         if (args[1])
298                                 {
299                                 args++;
300                                 X509_free(cert);
301                                 cert = load_cert(bio_err, *args, FORMAT_PEM);
302                                 if(!cert) goto end;
303                                 if(!add_ocsp_cert(&req, cert, issuer, ids))
304                                         goto end;
305                                 if(!sk_push(reqnames, *args))
306                                         goto end;
307                                 }
308                         else badarg = 1;
309                         }
310                 else if (!strcmp(*args, "-serial"))
311                         {
312                         if (args[1])
313                                 {
314                                 args++;
315                                 if(!add_ocsp_serial(&req, *args, issuer, ids))
316                                         goto end;
317                                 if(!sk_push(reqnames, *args))
318                                         goto end;
319                                 }
320                         else badarg = 1;
321                         }
322                 else badarg = 1;
323                 args++;
324                 }
325
326         /* Have we anything to do? */
327         if (!req && !reqin && !respin) badarg = 1;
328
329         if (badarg)
330                 {
331                 BIO_printf (bio_err, "OCSP utility\n");
332                 BIO_printf (bio_err, "Usage ocsp [options]\n");
333                 BIO_printf (bio_err, "where options are\n");
334                 BIO_printf (bio_err, "-out file          output filename\n");
335                 BIO_printf (bio_err, "-issuer file       issuer certificate\n");
336                 BIO_printf (bio_err, "-cert file         certificate to check\n");
337                 BIO_printf (bio_err, "-serial n          serial number to check\n");
338                 BIO_printf (bio_err, "-signer file       certificate to sign OCSP request with\n");
339                 BIO_printf (bio_err, "-signkey file      private key to sign OCSP request with\n");
340                 BIO_printf (bio_err, "-sign_certs file   additional certificates to include in signed request\n");
341                 BIO_printf (bio_err, "-no_certs          don't include any certificates in signed request\n");
342                 BIO_printf (bio_err, "-req_text          print text form of request\n");
343                 BIO_printf (bio_err, "-resp_text         print text form of response\n");
344                 BIO_printf (bio_err, "-text              print text form of request and response\n");
345                 BIO_printf (bio_err, "-reqout file       write DER encoded OCSP request to \"file\"\n");
346                 BIO_printf (bio_err, "-respout file      write DER encoded OCSP reponse to \"file\"\n");
347                 BIO_printf (bio_err, "-reqin file        read DER encoded OCSP request from \"file\"\n");
348                 BIO_printf (bio_err, "-respin file       read DER encoded OCSP reponse from \"file\"\n");
349                 BIO_printf (bio_err, "-nonce             add OCSP nonce to request\n");
350                 BIO_printf (bio_err, "-no_nonce          don't add OCSP nonce to request\n");
351                 BIO_printf (bio_err, "-url URL           OCSP responder URL\n");
352                 BIO_printf (bio_err, "-host host:n       send OCSP request to host on port n\n");
353                 BIO_printf (bio_err, "-path              path to use in OCSP request\n");
354                 BIO_printf (bio_err, "-CApath dir        trusted certificates directory\n");
355                 BIO_printf (bio_err, "-CAfile file       trusted certificates file\n");
356                 BIO_printf (bio_err, "-VAfile file       validator certificates file\n");
357                 BIO_printf (bio_err, "-noverify          don't verify response at all\n");
358                 BIO_printf (bio_err, "-verify_certs file additional certificates to search for signer\n");
359                 BIO_printf (bio_err, "-trust_other       don't verify additional certificates\n");
360                 BIO_printf (bio_err, "-no_intern         don't search certificates contained in response for signer\n");
361                 BIO_printf (bio_err, "-no_sig_verify     don't check signature on response\n");
362                 BIO_printf (bio_err, "-no_cert_verify    don't check signing certificate\n");
363                 BIO_printf (bio_err, "-no_chain          don't chain verify response\n");
364                 BIO_printf (bio_err, "-no_cert_checks    don't do additional checks on signing certificate\n");
365                 goto end;
366                 }
367
368         if(outfile) out = BIO_new_file(outfile, "w");
369         else out = BIO_new_fp(stdout, BIO_NOCLOSE);
370
371         if(!out)
372                 {
373                 BIO_printf(bio_err, "Error opening output file\n");
374                 goto end;
375                 }
376
377         if (!req && (add_nonce != 2)) add_nonce = 0;
378
379         if (!req && reqin)
380                 {
381                 derbio = BIO_new_file(reqin, "rb");
382                 if (!derbio)
383                         {
384                         BIO_printf(bio_err, "Error Opening OCSP request file\n");
385                         goto end;
386                         }
387                 req = d2i_OCSP_REQUEST_bio(derbio, NULL);
388                 BIO_free(derbio);
389                 if(!req)
390                         {
391                         BIO_printf(bio_err, "Error reading OCSP request\n");
392                         goto end;
393                         }
394                 }
395
396         if (!req && (signfile || reqout || host || add_nonce))
397                 {
398                 BIO_printf(bio_err, "Need an OCSP request for this operation!\n");
399                 goto end;
400                 }
401
402         if (req && add_nonce) OCSP_request_add1_nonce(req, NULL, -1);
403
404         if (signfile)
405                 {
406                 if (!keyfile) keyfile = signfile;
407                 signer = load_cert(bio_err, signfile, FORMAT_PEM);
408                 if (!signer)
409                         {
410                         BIO_printf(bio_err, "Error loading signer certificate\n");
411                         goto end;
412                         }
413                 if (sign_certfile)
414                         {
415                         sign_other = load_certs(bio_err, sign_certfile, FORMAT_PEM);
416                         if (!sign_other) goto end;
417                         }
418                 key = load_key(bio_err, keyfile, FORMAT_PEM, NULL, NULL);
419                 if (!key)
420                         {
421                         BIO_printf(bio_err, "Error loading signer private key\n");
422                         goto end;
423                         }
424                 if (!OCSP_request_sign(req, signer, key, EVP_sha1(), sign_other, sign_flags))
425                         {
426                         BIO_printf(bio_err, "Error signing OCSP request\n");
427                         goto end;
428                         }
429                 }
430
431         if (reqout)
432                 {
433                 derbio = BIO_new_file(reqout, "wb");
434                 if (!derbio)
435                         {
436                         BIO_printf(bio_err, "Error opening file %s\n", reqout);
437                         goto end;
438                         }
439                 i2d_OCSP_REQUEST_bio(derbio, req);
440                 BIO_free(derbio);
441                 }
442
443         if (req_text && req) OCSP_REQUEST_print(out, req, 0);
444
445         if (host)
446                 {
447                 cbio = BIO_new_connect(host);
448                 if (!cbio)
449                         {
450                         BIO_printf(bio_err, "Error creating connect BIO\n");
451                         goto end;
452                         }
453                 if (port) BIO_set_conn_port(cbio, port);
454                 if (BIO_do_connect(cbio) <= 0)
455                         {
456                         BIO_printf(bio_err, "Error connecting BIO\n");
457                         goto end;
458                         }
459                 resp = OCSP_sendreq_bio(cbio, path, req);
460                 BIO_free(cbio);
461                 cbio = NULL;
462                 if (!resp)
463                         {
464                         BIO_printf(bio_err, "Error querying OCSP responsder\n");
465                         goto end;
466                         }
467                 }
468         else if (respin)
469                 {
470                 derbio = BIO_new_file(respin, "rb");
471                 if (!derbio)
472                         {
473                         BIO_printf(bio_err, "Error Opening OCSP response file\n");
474                         goto end;
475                         }
476                 resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
477                 BIO_free(derbio);
478                 if(!resp)
479                         {
480                         BIO_printf(bio_err, "Error reading OCSP response\n");
481                         goto end;
482                         }
483         
484                 }
485         else
486                 {
487                 ret = 0;
488                 goto end;
489                 }
490
491         if (respout)
492                 {
493                 derbio = BIO_new_file(respout, "wb");
494                 if(!derbio)
495                         {
496                         BIO_printf(bio_err, "Error opening file %s\n", respout);
497                         goto end;
498                         }
499                 i2d_OCSP_RESPONSE_bio(derbio, resp);
500                 BIO_free(derbio);
501                 }
502
503         i = OCSP_response_status(resp);
504
505         if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL)
506                 {
507                 BIO_printf(out, "Responder Error: %s (%ld)\n",
508                                 OCSP_response_status_str(i), i);
509                 ret = 0;
510                 goto end;
511                 }
512
513         if (resp_text) OCSP_RESPONSE_print(out, resp, 0);
514
515         store = setup_verify(bio_err, CAfile, CApath);
516         if(!store) goto end;
517         if (verify_certfile)
518                 {
519                 verify_other = load_certs(bio_err, verify_certfile, FORMAT_PEM);
520                 if (!verify_other) goto end;
521                 }
522
523         bs = OCSP_response_get1_basic(resp);
524
525         if (!bs)
526                 {
527                 BIO_printf(bio_err, "Error parsing response\n");
528                 goto end;
529                 }
530
531         if (!noverify)
532                 {
533                 if (req && ((i = OCSP_check_nonce(req, bs)) <= 0))
534                         {
535                         if (i == -1)
536                                 BIO_printf(bio_err, "WARNING: no nonce in response\n");
537                         else
538                                 {
539                                 BIO_printf(bio_err, "Nonce Verify error\n");
540                                 goto end;
541                                 }
542                         }
543
544                 i = OCSP_basic_verify(bs, verify_other, store, verify_flags);
545                 if (i < 0) i = OCSP_basic_verify(bs, NULL, store, 0);
546
547                 if(i <= 0)
548                         {
549                         BIO_printf(bio_err, "Response Verify Failure\n", i);
550                         ERR_print_errors(bio_err);
551                         }
552                 else
553                         BIO_printf(bio_err, "Response verify OK\n");
554
555                 }
556
557         if (!print_ocsp_summary(out, bs, req, reqnames, ids))
558                 goto end;
559
560         ret = 0;
561
562 end:
563         ERR_print_errors(bio_err);
564         X509_free(signer);
565         X509_STORE_free(store);
566         EVP_PKEY_free(key);
567         X509_free(issuer);
568         X509_free(cert);
569         BIO_free(cbio);
570         BIO_free(out);
571         OCSP_REQUEST_free(req);
572         OCSP_RESPONSE_free(resp);
573         OCSP_BASICRESP_free(bs);
574         sk_free(reqnames);
575         sk_OCSP_CERTID_free(ids);
576         sk_X509_pop_free(sign_other, X509_free);
577         sk_X509_pop_free(verify_other, X509_free);
578
579         if (use_ssl != -1)
580                 {
581                 OPENSSL_free(host);
582                 OPENSSL_free(port);
583                 OPENSSL_free(path);
584                 }
585
586         EXIT(ret);
587 }
588
589 static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *issuer,
590                                 STACK_OF(OCSP_CERTID) *ids)
591         {
592         OCSP_CERTID *id;
593         if(!issuer)
594                 {
595                 BIO_printf(bio_err, "No issuer certificate specified\n");
596                 return 0;
597                 }
598         if(!*req) *req = OCSP_REQUEST_new();
599         if(!*req) goto err;
600         id = OCSP_cert_to_id(NULL, cert, issuer);
601         if(!id || !sk_OCSP_CERTID_push(ids, id)) goto err;
602         if(!OCSP_request_add0_id(*req, id)) goto err;
603         return 1;
604
605         err:
606         BIO_printf(bio_err, "Error Creating OCSP request\n");
607         return 0;
608         }
609
610 static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, X509 *issuer,
611                                 STACK_OF(OCSP_CERTID) *ids)
612         {
613         OCSP_CERTID *id;
614         X509_NAME *iname;
615         ASN1_BIT_STRING *ikey;
616         ASN1_INTEGER *sno;
617         if(!issuer)
618                 {
619                 BIO_printf(bio_err, "No issuer certificate specified\n");
620                 return 0;
621                 }
622         if(!*req) *req = OCSP_REQUEST_new();
623         if(!*req) goto err;
624         iname = X509_get_subject_name(issuer);
625         ikey = X509_get0_pubkey_bitstr(issuer);
626         sno = s2i_ASN1_INTEGER(NULL, serial);
627         if(!sno)
628                 {
629                 BIO_printf(bio_err, "Error converting serial number %s\n", serial);
630                 return 0;
631                 }
632         id = OCSP_cert_id_new(EVP_sha1(), iname, ikey, sno);
633         ASN1_INTEGER_free(sno);
634         if(!id || !sk_OCSP_CERTID_push(ids, id)) goto err;
635         if(!OCSP_request_add0_id(*req, id)) goto err;
636         return 1;
637
638         err:
639         BIO_printf(bio_err, "Error Creating OCSP request\n");
640         return 0;
641         }
642
643 static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
644                                         STACK *names, STACK_OF(OCSP_CERTID) *ids)
645         {
646         OCSP_CERTID *id;
647         char *name;
648         int i;
649
650         int status, reason;
651
652         ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
653
654         if (!bs || !req || !sk_num(names) || !sk_OCSP_CERTID_num(ids))
655                 return 1;
656
657         for (i = 0; i < sk_OCSP_CERTID_num(ids); i++)
658                 {
659                 id = sk_OCSP_CERTID_value(ids, i);
660                 name = sk_value(names, i);
661                 BIO_printf(out, "%s: ", name);
662
663                 if(!OCSP_resp_find_status(bs, id, &status, &reason,
664                                         &rev, &thisupd, &nextupd))
665                         {
666                         BIO_puts(out, "ERROR: No Status found.\n");
667                         continue;
668                         }
669                 BIO_printf(out, "%s\n", OCSP_cert_status_str(status));
670
671                 BIO_puts(out, "\tThis Update: ");
672                 ASN1_GENERALIZEDTIME_print(out, thisupd);
673                 BIO_puts(out, "\n");
674
675                 if(nextupd)
676                         {
677                         BIO_puts(out, "\tNext Update: ");
678                         ASN1_GENERALIZEDTIME_print(out, thisupd);
679                         BIO_puts(out, "\n");
680                         }
681
682                 if (status != V_OCSP_CERTSTATUS_REVOKED)
683                         continue;
684
685                 if (reason != -1)
686                         BIO_printf(out, "\tReason: %s\n",
687                                 OCSP_crl_reason_str(reason));
688
689                 BIO_puts(out, "\tRevocation Time: ");
690                 ASN1_GENERALIZEDTIME_print(out, rev);
691                 BIO_puts(out, "\n");
692                 }
693
694         return 1;
695         }
696