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