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