293b46cdb382f9ad5aa6464e87097232988d3f23
[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 <openssl/ssl.h>
65 #include "apps.h"
66
67 static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *issuer,
68                                 STACK_OF(OCSP_CERTID) *ids);
69 static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, X509 *issuer,
70                                 STACK_OF(OCSP_CERTID) *ids);
71 static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
72                                 STACK *names, STACK_OF(OCSP_CERTID) *ids);
73
74 #undef PROG
75 #define PROG ocsp_main
76
77 int MAIN(int, char **);
78
79 int MAIN(int argc, char **argv)
80         {
81         char **args;
82         char *host = NULL, *port = NULL, *path = "/";
83         char *reqin = NULL, *respin = NULL;
84         char *reqout = NULL, *respout = NULL;
85         char *signfile = NULL, *keyfile = NULL;
86         char *outfile = NULL;
87         int add_nonce = 1, noverify = 0, use_ssl = -1;
88         OCSP_REQUEST *req = NULL;
89         OCSP_RESPONSE *resp = NULL;
90         OCSP_BASICRESP *bs = NULL;
91         X509 *issuer = NULL, *cert = NULL;
92         X509 *signer = NULL;
93         EVP_PKEY *key = NULL;
94         BIO *cbio = NULL, *derbio = NULL;
95         BIO *out = NULL;
96         int req_text = 0, resp_text = 0;
97         char *CAfile = NULL, *CApath = NULL;
98         X509_STORE *store = NULL;
99         SSL_CTX *ctx = NULL;
100         STACK_OF(X509) *sign_other = NULL, *verify_other = NULL;
101         char *sign_certfile = NULL, *verify_certfile = NULL;
102         unsigned long sign_flags = 0, verify_flags = 0;
103         int ret = 1;
104         int badarg = 0;
105         int i;
106         STACK *reqnames = NULL;
107         STACK_OF(OCSP_CERTID) *ids = NULL;
108         if (bio_err == NULL) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
109         SSL_load_error_strings();
110         args = argv + 1;
111         reqnames = sk_new_null();
112         ids = sk_OCSP_CERTID_new_null();
113         while (!badarg && *args && *args[0] == '-')
114                 {
115                 if (!strcmp(*args, "-out"))
116                         {
117                         if (args[1])
118                                 {
119                                 args++;
120                                 outfile = *args;
121                                 }
122                         else badarg = 1;
123                         }
124                 else if (!strcmp(*args, "-url"))
125                         {
126                         if (args[1])
127                                 {
128                                 args++;
129                                 if (!OCSP_parse_url(*args, &host, &port, &path, &use_ssl))
130                                         {
131                                         BIO_printf(bio_err, "Error parsing URL\n");
132                                         badarg = 1;
133                                         }
134                                 }
135                         else badarg = 1;
136                         }
137                 else if (!strcmp(*args, "-host"))
138                         {
139                         if (args[1])
140                                 {
141                                 args++;
142                                 host = *args;
143                                 }
144                         else badarg = 1;
145                         }
146                 else if (!strcmp(*args, "-noverify"))
147                         noverify = 1;
148                 else if (!strcmp(*args, "-nonce"))
149                         add_nonce = 2;
150                 else if (!strcmp(*args, "-no_nonce"))
151                         add_nonce = 0;
152                 else if (!strcmp(*args, "-no_certs"))
153                         sign_flags |= OCSP_NOCERTS;
154                 else if (!strcmp(*args, "-no_signature_verify"))
155                         verify_flags |= OCSP_NOSIGS;
156                 else if (!strcmp(*args, "-no_cert_verify"))
157                         verify_flags |= OCSP_NOVERIFY;
158                 else if (!strcmp(*args, "-no_chain"))
159                         verify_flags |= OCSP_NOCHAIN;
160                 else if (!strcmp(*args, "-no_cert_checks"))
161                         verify_flags |= OCSP_NOCHECKS;
162                 else if (!strcmp(*args, "-no_explicit"))
163                         verify_flags |= OCSP_NOEXPLICIT;
164                 else if (!strcmp(*args, "-trust_other"))
165                         verify_flags |= OCSP_TRUSTOTHER;
166                 else if (!strcmp(*args, "-no_intern"))
167                         verify_flags |= OCSP_NOINTERN;
168                 else if (!strcmp(*args, "-text"))
169                         {
170                         req_text = 1;
171                         resp_text = 1;
172                         }
173                 else if (!strcmp(*args, "-req_text"))
174                         req_text = 1;
175                 else if (!strcmp(*args, "-resp_text"))
176                         resp_text = 1;
177                 else if (!strcmp(*args, "-reqin"))
178                         {
179                         if (args[1])
180                                 {
181                                 args++;
182                                 reqin = *args;
183                                 }
184                         else badarg = 1;
185                         }
186                 else if (!strcmp(*args, "-respin"))
187                         {
188                         if (args[1])
189                                 {
190                                 args++;
191                                 respin = *args;
192                                 }
193                         else badarg = 1;
194                         }
195                 else if (!strcmp(*args, "-signer"))
196                         {
197                         if (args[1])
198                                 {
199                                 args++;
200                                 signfile = *args;
201                                 }
202                         else badarg = 1;
203                         }
204                 else if (!strcmp (*args, "-VAfile"))
205                         {
206                         if (args[1])
207                                 {
208                                 args++;
209                                 verify_certfile = *args;
210                                 verify_flags |= OCSP_TRUSTOTHER;
211                                 }
212                         else badarg = 1;
213                         }
214                 else if (!strcmp(*args, "-sign_other"))
215                         {
216                         if (args[1])
217                                 {
218                                 args++;
219                                 sign_certfile = *args;
220                                 }
221                         else badarg = 1;
222                         }
223                 else if (!strcmp(*args, "-verify_other"))
224                         {
225                         if (args[1])
226                                 {
227                                 args++;
228                                 verify_certfile = *args;
229                                 }
230                         else badarg = 1;
231                         }
232                 else if (!strcmp (*args, "-CAfile"))
233                         {
234                         if (args[1])
235                                 {
236                                 args++;
237                                 CAfile = *args;
238                                 }
239                         else badarg = 1;
240                         }
241                 else if (!strcmp (*args, "-CApath"))
242                         {
243                         if (args[1])
244                                 {
245                                 args++;
246                                 CApath = *args;
247                                 }
248                         else badarg = 1;
249                         }
250                  else if (!strcmp(*args, "-signkey"))
251                         {
252                         if (args[1])
253                                 {
254                                 args++;
255                                 keyfile = *args;
256                                 }
257                         else badarg = 1;
258                         }
259                 else if (!strcmp(*args, "-reqout"))
260                         {
261                         if (args[1])
262                                 {
263                                 args++;
264                                 reqout = *args;
265                                 }
266                         else badarg = 1;
267                         }
268                 else if (!strcmp(*args, "-respout"))
269                         {
270                         if (args[1])
271                                 {
272                                 args++;
273                                 respout = *args;
274                                 }
275                         else badarg = 1;
276                         }
277                  else if (!strcmp(*args, "-path"))
278                         {
279                         if (args[1])
280                                 {
281                                 args++;
282                                 path = *args;
283                                 }
284                         else badarg = 1;
285                         }
286                 else if (!strcmp(*args, "-issuer"))
287                         {
288                         if (args[1])
289                                 {
290                                 args++;
291                                 X509_free(issuer);
292                                 issuer = load_cert(bio_err, *args, FORMAT_PEM);
293                                 if(!issuer) goto end;
294                                 }
295                         else badarg = 1;
296                         }
297                 else if (!strcmp (*args, "-cert"))
298                         {
299                         if (args[1])
300                                 {
301                                 args++;
302                                 X509_free(cert);
303                                 cert = load_cert(bio_err, *args, FORMAT_PEM);
304                                 if(!cert) goto end;
305                                 if(!add_ocsp_cert(&req, cert, issuer, ids))
306                                         goto end;
307                                 if(!sk_push(reqnames, *args))
308                                         goto end;
309                                 }
310                         else badarg = 1;
311                         }
312                 else if (!strcmp(*args, "-serial"))
313                         {
314                         if (args[1])
315                                 {
316                                 args++;
317                                 if(!add_ocsp_serial(&req, *args, issuer, ids))
318                                         goto end;
319                                 if(!sk_push(reqnames, *args))
320                                         goto end;
321                                 }
322                         else badarg = 1;
323                         }
324                 else badarg = 1;
325                 args++;
326                 }
327
328         /* Have we anything to do? */
329         if (!req && !reqin && !respin) badarg = 1;
330
331         if (badarg)
332                 {
333                 BIO_printf (bio_err, "OCSP utility\n");
334                 BIO_printf (bio_err, "Usage ocsp [options]\n");
335                 BIO_printf (bio_err, "where options are\n");
336                 BIO_printf (bio_err, "-out file          output filename\n");
337                 BIO_printf (bio_err, "-issuer file       issuer certificate\n");
338                 BIO_printf (bio_err, "-cert file         certificate to check\n");
339                 BIO_printf (bio_err, "-serial n          serial number to check\n");
340                 BIO_printf (bio_err, "-signer file       certificate to sign OCSP request with\n");
341                 BIO_printf (bio_err, "-signkey file      private key to sign OCSP request with\n");
342                 BIO_printf (bio_err, "-sign_certs file   additional certificates to include in signed request\n");
343                 BIO_printf (bio_err, "-no_certs          don't include any certificates in signed request\n");
344                 BIO_printf (bio_err, "-req_text          print text form of request\n");
345                 BIO_printf (bio_err, "-resp_text         print text form of response\n");
346                 BIO_printf (bio_err, "-text              print text form of request and response\n");
347                 BIO_printf (bio_err, "-reqout file       write DER encoded OCSP request to \"file\"\n");
348                 BIO_printf (bio_err, "-respout file      write DER encoded OCSP reponse to \"file\"\n");
349                 BIO_printf (bio_err, "-reqin file        read DER encoded OCSP request from \"file\"\n");
350                 BIO_printf (bio_err, "-respin file       read DER encoded OCSP reponse from \"file\"\n");
351                 BIO_printf (bio_err, "-nonce             add OCSP nonce to request\n");
352                 BIO_printf (bio_err, "-no_nonce          don't add OCSP nonce to request\n");
353                 BIO_printf (bio_err, "-url URL           OCSP responder URL\n");
354                 BIO_printf (bio_err, "-host host:n       send OCSP request to host on port n\n");
355                 BIO_printf (bio_err, "-path              path to use in OCSP request\n");
356                 BIO_printf (bio_err, "-CApath dir        trusted certificates directory\n");
357                 BIO_printf (bio_err, "-CAfile file       trusted certificates file\n");
358                 BIO_printf (bio_err, "-VAfile file       validator certificates file\n");
359                 BIO_printf (bio_err, "-noverify          don't verify response at all\n");
360                 BIO_printf (bio_err, "-verify_certs file additional certificates to search for signer\n");
361                 BIO_printf (bio_err, "-trust_other       don't verify additional certificates\n");
362                 BIO_printf (bio_err, "-no_intern         don't search certificates contained in response for signer\n");
363                 BIO_printf (bio_err, "-no_sig_verify     don't check signature on response\n");
364                 BIO_printf (bio_err, "-no_cert_verify    don't check signing certificate\n");
365                 BIO_printf (bio_err, "-no_chain          don't chain verify response\n");
366                 BIO_printf (bio_err, "-no_cert_checks    don't do additional checks on signing certificate\n");
367                 goto end;
368                 }
369
370         if(outfile) out = BIO_new_file(outfile, "w");
371         else out = BIO_new_fp(stdout, BIO_NOCLOSE);
372
373         if(!out)
374                 {
375                 BIO_printf(bio_err, "Error opening output file\n");
376                 goto end;
377                 }
378
379         if (!req && (add_nonce != 2)) add_nonce = 0;
380
381         if (!req && reqin)
382                 {
383                 derbio = BIO_new_file(reqin, "rb");
384                 if (!derbio)
385                         {
386                         BIO_printf(bio_err, "Error Opening OCSP request file\n");
387                         goto end;
388                         }
389                 req = d2i_OCSP_REQUEST_bio(derbio, NULL);
390                 BIO_free(derbio);
391                 if(!req)
392                         {
393                         BIO_printf(bio_err, "Error reading OCSP request\n");
394                         goto end;
395                         }
396                 }
397
398         if (!req && (signfile || reqout || host || add_nonce))
399                 {
400                 BIO_printf(bio_err, "Need an OCSP request for this operation!\n");
401                 goto end;
402                 }
403
404         if (req && add_nonce) OCSP_request_add1_nonce(req, NULL, -1);
405
406         if (signfile)
407                 {
408                 if (!keyfile) keyfile = signfile;
409                 signer = load_cert(bio_err, signfile, FORMAT_PEM);
410                 if (!signer)
411                         {
412                         BIO_printf(bio_err, "Error loading signer certificate\n");
413                         goto end;
414                         }
415                 if (sign_certfile)
416                         {
417                         sign_other = load_certs(bio_err, sign_certfile, FORMAT_PEM);
418                         if (!sign_other) goto end;
419                         }
420                 key = load_key(bio_err, keyfile, FORMAT_PEM, NULL, NULL);
421                 if (!key)
422                         {
423                         BIO_printf(bio_err, "Error loading signer private key\n");
424                         goto end;
425                         }
426                 if (!OCSP_request_sign(req, signer, key, EVP_sha1(), sign_other, sign_flags))
427                         {
428                         BIO_printf(bio_err, "Error signing OCSP request\n");
429                         goto end;
430                         }
431                 }
432
433         if (reqout)
434                 {
435                 derbio = BIO_new_file(reqout, "wb");
436                 if (!derbio)
437                         {
438                         BIO_printf(bio_err, "Error opening file %s\n", reqout);
439                         goto end;
440                         }
441                 i2d_OCSP_REQUEST_bio(derbio, req);
442                 BIO_free(derbio);
443                 }
444
445         if (req_text && req) OCSP_REQUEST_print(out, req, 0);
446
447         if (host)
448                 {
449                 cbio = BIO_new_connect(host);
450                 if (!cbio)
451                         {
452                         BIO_printf(bio_err, "Error creating connect BIO\n");
453                         goto end;
454                         }
455                 if (port) BIO_set_conn_port(cbio, port);
456                 if (use_ssl == 1)
457                         {
458                         BIO *sbio;
459                         ctx = SSL_CTX_new(SSLv23_client_method());
460                         SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
461                         sbio = BIO_new_ssl(ctx, 1);
462                         cbio = BIO_push(sbio, cbio);
463                         }
464                 if (BIO_do_connect(cbio) <= 0)
465                         {
466                         BIO_printf(bio_err, "Error connecting BIO\n");
467                         goto end;
468                         }
469                 resp = OCSP_sendreq_bio(cbio, path, req);
470                 BIO_free_all(cbio);
471                 cbio = NULL;
472                 if (!resp)
473                         {
474                         BIO_printf(bio_err, "Error querying OCSP responsder\n");
475                         goto end;
476                         }
477                 }
478         else if (respin)
479                 {
480                 derbio = BIO_new_file(respin, "rb");
481                 if (!derbio)
482                         {
483                         BIO_printf(bio_err, "Error Opening OCSP response file\n");
484                         goto end;
485                         }
486                 resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
487                 BIO_free(derbio);
488                 if(!resp)
489                         {
490                         BIO_printf(bio_err, "Error reading OCSP response\n");
491                         goto end;
492                         }
493         
494                 }
495         else
496                 {
497                 ret = 0;
498                 goto end;
499                 }
500
501         if (respout)
502                 {
503                 derbio = BIO_new_file(respout, "wb");
504                 if(!derbio)
505                         {
506                         BIO_printf(bio_err, "Error opening file %s\n", respout);
507                         goto end;
508                         }
509                 i2d_OCSP_RESPONSE_bio(derbio, resp);
510                 BIO_free(derbio);
511                 }
512
513         i = OCSP_response_status(resp);
514
515         if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL)
516                 {
517                 BIO_printf(out, "Responder Error: %s (%ld)\n",
518                                 OCSP_response_status_str(i), i);
519                 ret = 0;
520                 goto end;
521                 }
522
523         if (resp_text) OCSP_RESPONSE_print(out, resp, 0);
524
525         store = setup_verify(bio_err, CAfile, CApath);
526         if(!store) goto end;
527         if (verify_certfile)
528                 {
529                 verify_other = load_certs(bio_err, verify_certfile, FORMAT_PEM);
530                 if (!verify_other) goto end;
531                 }
532
533         bs = OCSP_response_get1_basic(resp);
534
535         if (!bs)
536                 {
537                 BIO_printf(bio_err, "Error parsing response\n");
538                 goto end;
539                 }
540
541         if (!noverify)
542                 {
543                 if (req && ((i = OCSP_check_nonce(req, bs)) <= 0))
544                         {
545                         if (i == -1)
546                                 BIO_printf(bio_err, "WARNING: no nonce in response\n");
547                         else
548                                 {
549                                 BIO_printf(bio_err, "Nonce Verify error\n");
550                                 goto end;
551                                 }
552                         }
553
554                 i = OCSP_basic_verify(bs, verify_other, store, verify_flags);
555                 if (i < 0) i = OCSP_basic_verify(bs, NULL, store, 0);
556
557                 if(i <= 0)
558                         {
559                         BIO_printf(bio_err, "Response Verify Failure\n", i);
560                         ERR_print_errors(bio_err);
561                         }
562                 else
563                         BIO_printf(bio_err, "Response verify OK\n");
564
565                 }
566
567         if (!print_ocsp_summary(out, bs, req, reqnames, ids))
568                 goto end;
569
570         ret = 0;
571
572 end:
573         ERR_print_errors(bio_err);
574         X509_free(signer);
575         X509_STORE_free(store);
576         EVP_PKEY_free(key);
577         X509_free(issuer);
578         X509_free(cert);
579         BIO_free_all(cbio);
580         BIO_free(out);
581         OCSP_REQUEST_free(req);
582         OCSP_RESPONSE_free(resp);
583         OCSP_BASICRESP_free(bs);
584         sk_free(reqnames);
585         sk_OCSP_CERTID_free(ids);
586         sk_X509_pop_free(sign_other, X509_free);
587         sk_X509_pop_free(verify_other, X509_free);
588
589         if (use_ssl != -1)
590                 {
591                 OPENSSL_free(host);
592                 OPENSSL_free(port);
593                 OPENSSL_free(path);
594                 SSL_CTX_free(ctx);
595                 }
596
597         EXIT(ret);
598 }
599
600 static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *issuer,
601                                 STACK_OF(OCSP_CERTID) *ids)
602         {
603         OCSP_CERTID *id;
604         if(!issuer)
605                 {
606                 BIO_printf(bio_err, "No issuer certificate specified\n");
607                 return 0;
608                 }
609         if(!*req) *req = OCSP_REQUEST_new();
610         if(!*req) goto err;
611         id = OCSP_cert_to_id(NULL, cert, issuer);
612         if(!id || !sk_OCSP_CERTID_push(ids, id)) goto err;
613         if(!OCSP_request_add0_id(*req, id)) goto err;
614         return 1;
615
616         err:
617         BIO_printf(bio_err, "Error Creating OCSP request\n");
618         return 0;
619         }
620
621 static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, X509 *issuer,
622                                 STACK_OF(OCSP_CERTID) *ids)
623         {
624         OCSP_CERTID *id;
625         X509_NAME *iname;
626         ASN1_BIT_STRING *ikey;
627         ASN1_INTEGER *sno;
628         if(!issuer)
629                 {
630                 BIO_printf(bio_err, "No issuer certificate specified\n");
631                 return 0;
632                 }
633         if(!*req) *req = OCSP_REQUEST_new();
634         if(!*req) goto err;
635         iname = X509_get_subject_name(issuer);
636         ikey = X509_get0_pubkey_bitstr(issuer);
637         sno = s2i_ASN1_INTEGER(NULL, serial);
638         if(!sno)
639                 {
640                 BIO_printf(bio_err, "Error converting serial number %s\n", serial);
641                 return 0;
642                 }
643         id = OCSP_cert_id_new(EVP_sha1(), iname, ikey, sno);
644         ASN1_INTEGER_free(sno);
645         if(!id || !sk_OCSP_CERTID_push(ids, id)) goto err;
646         if(!OCSP_request_add0_id(*req, id)) goto err;
647         return 1;
648
649         err:
650         BIO_printf(bio_err, "Error Creating OCSP request\n");
651         return 0;
652         }
653
654 static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
655                                         STACK *names, STACK_OF(OCSP_CERTID) *ids)
656         {
657         OCSP_CERTID *id;
658         char *name;
659         int i;
660
661         int status, reason;
662
663         ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
664
665         if (!bs || !req || !sk_num(names) || !sk_OCSP_CERTID_num(ids))
666                 return 1;
667
668         for (i = 0; i < sk_OCSP_CERTID_num(ids); i++)
669                 {
670                 id = sk_OCSP_CERTID_value(ids, i);
671                 name = sk_value(names, i);
672                 BIO_printf(out, "%s: ", name);
673
674                 if(!OCSP_resp_find_status(bs, id, &status, &reason,
675                                         &rev, &thisupd, &nextupd))
676                         {
677                         BIO_puts(out, "ERROR: No Status found.\n");
678                         continue;
679                         }
680                 BIO_printf(out, "%s\n", OCSP_cert_status_str(status));
681
682                 BIO_puts(out, "\tThis Update: ");
683                 ASN1_GENERALIZEDTIME_print(out, thisupd);
684                 BIO_puts(out, "\n");
685
686                 if(nextupd)
687                         {
688                         BIO_puts(out, "\tNext Update: ");
689                         ASN1_GENERALIZEDTIME_print(out, thisupd);
690                         BIO_puts(out, "\n");
691                         }
692
693                 if (status != V_OCSP_CERTSTATUS_REVOKED)
694                         continue;
695
696                 if (reason != -1)
697                         BIO_printf(out, "\tReason: %s\n",
698                                 OCSP_crl_reason_str(reason));
699
700                 BIO_puts(out, "\tRevocation Time: ");
701                 ASN1_GENERALIZEDTIME_print(out, rev);
702                 BIO_puts(out, "\n");
703                 }
704
705         return 1;
706         }
707