Bug Summary

File:src/usr.bin/openssl/ocsp.c
Warning:line 921, column 3
Value stored to 'i' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ocsp.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/openssl/obj -resource-dir /usr/local/llvm16/lib/clang/16 -D LIBRESSL_INTERNAL -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/openssl/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/usr.bin/openssl/ocsp.c
1/* $OpenBSD: ocsp.c,v 1.23 2023/03/06 14:32:06 tb Exp $ */
2/* Written by Dr Stephen N Henson (steve@openssl.org) 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#ifndef OPENSSL_NO_OCSP
59
60#include <sys/types.h>
61
62#include <stdio.h>
63#include <stdlib.h>
64#include <limits.h>
65#include <string.h>
66#include <poll.h>
67#include <time.h>
68
69/* Needs to be included before the openssl headers! */
70#include "apps.h"
71
72#include <openssl/bn.h>
73#include <openssl/crypto.h>
74#include <openssl/err.h>
75#include <openssl/evp.h>
76#include <openssl/ssl.h>
77#include <openssl/x509v3.h>
78
79/* Maximum leeway in validity period: default 5 minutes */
80#define MAX_VALIDITY_PERIOD(5 * 60) (5 * 60)
81
82static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert,
83 const EVP_MD *cert_id_md, X509 *issuer, STACK_OF(OCSP_CERTID)struct stack_st_OCSP_CERTID *ids);
84static int add_ocsp_serial(OCSP_REQUEST **req, char *serial,
85 const EVP_MD *cert_id_md, X509 *issuer, STACK_OF(OCSP_CERTID)struct stack_st_OCSP_CERTID *ids);
86static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
87 STACK_OF(OPENSSL_STRING)struct stack_st_OPENSSL_STRING *names, STACK_OF(OCSP_CERTID)struct stack_st_OCSP_CERTID *ids, long nsec,
88 long maxage);
89
90static int make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req,
91 CA_DB *db, X509 *ca, X509 *rcert, EVP_PKEY *rkey, STACK_OF(X509)struct stack_st_X509 *rother,
92 unsigned long flags, int nmin, int ndays);
93
94static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser);
95static BIO *init_responder(char *port);
96static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio,
97 char *port);
98static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp);
99static OCSP_RESPONSE *query_responder(BIO *err, BIO *cbio, char *path,
100 STACK_OF(CONF_VALUE)struct stack_st_CONF_VALUE *headers, const char *host, OCSP_REQUEST *req,
101 int req_timeout);
102
103static struct {
104 int accept_count;
105 int add_nonce;
106 char *CAfile;
107 char *CApath;
108 X509 *cert;
109 const EVP_MD *cert_id_md;
110 STACK_OF(CONF_VALUE)struct stack_st_CONF_VALUE *headers;
111 char *host;
112 STACK_OF(OCSP_CERTID)struct stack_st_OCSP_CERTID *ids;
113 int ignore_err;
114 X509 *issuer;
115 char *keyfile;
116 long maxage;
117 int ndays;
118 int nmin;
119 int no_usage;
120 int noverify;
121 long nsec;
122 char *outfile;
123 char *path;
124 char *port;
125 char *rca_filename;
126 char *rcertfile;
127 OCSP_REQUEST *req;
128 int req_text;
129 int req_timeout;
130 char *reqin;
131 STACK_OF(OPENSSL_STRING)struct stack_st_OPENSSL_STRING *reqnames;
132 char *reqout;
133 int resp_text;
134 char *respin;
135 char *respout;
136 unsigned long rflags;
137 char *ridx_filename;
138 char *rkeyfile;
139 char *rsignfile;
140 char *sign_certfile;
141 unsigned long sign_flags;
142 char *signfile;
143 int use_ssl;
144 char *verify_certfile;
145 unsigned long verify_flags;
146} cfg;
147
148static int
149ocsp_opt_cert(char *arg)
150{
151 X509_free(cfg.cert);
152 cfg.cert = load_cert(bio_err, arg, FORMAT_PEM3, NULL((void *)0),
153 "certificate");
154 if (cfg.cert == NULL((void *)0)) {
155 cfg.no_usage = 1;
156 return (1);
157 }
158 if (cfg.cert_id_md == NULL((void *)0))
159 cfg.cert_id_md = EVP_sha1();
160 if (!add_ocsp_cert(&cfg.req, cfg.cert,
161 cfg.cert_id_md, cfg.issuer, cfg.ids)) {
162 cfg.no_usage = 1;
163 return (1);
164 }
165 if (!sk_OPENSSL_STRING_push(cfg.reqnames, arg)sk_push(((_STACK*) (1 ? cfg.reqnames : (struct stack_st_OPENSSL_STRING
*)0)), ((void*) (1 ? arg : (char*)0)))
) {
166 cfg.no_usage = 1;
167 return (1);
168 }
169 return (0);
170}
171
172static int
173ocsp_opt_cert_id_md(int argc, char **argv, int *argsused)
174{
175 char *name = argv[0];
176
177 if (*name++ != '-')
178 return (1);
179
180 if ((cfg.cert_id_md = EVP_get_digestbyname(name)) == NULL((void *)0))
181 return (1);
182
183 *argsused = 1;
184 return (0);
185}
186
187static int
188ocsp_opt_header(int argc, char **argv, int *argsused)
189{
190 if (argc < 3 || argv[1] == NULL((void *)0) || argv[2] == NULL((void *)0))
191 return (1);
192
193 if (!X509V3_add_value(argv[1], argv[2], &cfg.headers)) {
194 cfg.no_usage = 1;
195 return (1);
196 }
197
198 *argsused = 3;
199 return (0);
200}
201
202static int
203ocsp_opt_host(char *arg)
204{
205 if (cfg.use_ssl != -1)
206 return (1);
207
208 cfg.host = arg;
209 return (0);
210}
211
212static int
213ocsp_opt_issuer(char *arg)
214{
215 X509_free(cfg.issuer);
216 cfg.issuer = load_cert(bio_err, arg, FORMAT_PEM3, NULL((void *)0),
217 "issuer certificate");
218 if (cfg.issuer == NULL((void *)0)) {
219 cfg.no_usage = 1;
220 return (1);
221 }
222 return (0);
223}
224
225static int
226ocsp_opt_ndays(char *arg)
227{
228 const char *errstr = NULL((void *)0);
229
230 cfg.ndays = strtonum(arg, 0, INT_MAX0x7fffffff, &errstr);
231 if (errstr != NULL((void *)0)) {
232 BIO_printf(bio_err, "Illegal update period %s: %s\n",
233 arg, errstr);
234 return (1);
235 }
236 return (0);
237}
238
239static int
240ocsp_opt_nmin(char *arg)
241{
242 const char *errstr = NULL((void *)0);
243
244 cfg.nmin = strtonum(arg, 0, INT_MAX0x7fffffff, &errstr);
245 if (errstr != NULL((void *)0)) {
246 BIO_printf(bio_err, "Illegal update period %s: %s\n",
247 arg, errstr);
248 return (1);
249 }
250
251 if (cfg.ndays != -1)
252 return (1);
253
254 cfg.ndays = 0;
255 return (0);
256}
257
258static int
259ocsp_opt_nrequest(char *arg)
260{
261 const char *errstr = NULL((void *)0);
262
263 cfg.accept_count = strtonum(arg, 0, INT_MAX0x7fffffff, &errstr);
264 if (errstr != NULL((void *)0)) {
265 BIO_printf(bio_err, "Illegal accept count %s: %s\n",
266 arg, errstr);
267 return (1);
268 }
269 return (0);
270}
271
272static int
273ocsp_opt_port(char *arg)
274{
275 if (cfg.use_ssl != -1)
276 return (1);
277
278 cfg.port = arg;
279 return (0);
280}
281
282static int
283ocsp_opt_serial(char *arg)
284{
285 if (cfg.cert_id_md == NULL((void *)0))
286 cfg.cert_id_md = EVP_sha1();
287 if (!add_ocsp_serial(&cfg.req, arg, cfg.cert_id_md,
288 cfg.issuer, cfg.ids)) {
289 cfg.no_usage = 1;
290 return (1);
291 }
292 if (!sk_OPENSSL_STRING_push(cfg.reqnames, arg)sk_push(((_STACK*) (1 ? cfg.reqnames : (struct stack_st_OPENSSL_STRING
*)0)), ((void*) (1 ? arg : (char*)0)))
) {
293 cfg.no_usage = 1;
294 return (1);
295 }
296 return (0);
297}
298
299static int
300ocsp_opt_status_age(char *arg)
301{
302 const char *errstr = NULL((void *)0);
303
304 cfg.maxage = strtonum(arg, 0, LONG_MAX0x7fffffffffffffffL, &errstr);
305 if (errstr != NULL((void *)0)) {
306 BIO_printf(bio_err, "Illegal validity age %s: %s\n",
307 arg, errstr);
308 return (1);
309 }
310 return (0);
311}
312
313static int
314ocsp_opt_text(void)
315{
316 cfg.req_text = 1;
317 cfg.resp_text = 1;
318 return (0);
319}
320
321static int
322ocsp_opt_timeout(char *arg)
323{
324 const char *errstr = NULL((void *)0);
325
326 cfg.req_timeout = strtonum(arg, 0, INT_MAX0x7fffffff, &errstr);
327 if (errstr != NULL((void *)0)) {
328 BIO_printf(bio_err, "Illegal timeout value %s: %s\n",
329 arg, errstr);
330 return (1);
331 }
332 return (0);
333}
334
335static int
336ocsp_opt_url(char *arg)
337{
338 if (cfg.host == NULL((void *)0) && cfg.port == NULL((void *)0) &&
339 cfg.path == NULL((void *)0)) {
340 if (!OCSP_parse_url(arg, &cfg.host, &cfg.port,
341 &cfg.path, &cfg.use_ssl)) {
342 BIO_printf(bio_err, "Error parsing URL\n");
343 return (1);
344 }
345 }
346 return (0);
347}
348
349static int
350ocsp_opt_vafile(char *arg)
351{
352 cfg.verify_certfile = arg;
353 cfg.verify_flags |= OCSP_TRUSTOTHER0x200;
354 return (0);
355}
356
357static int
358ocsp_opt_validity_period(char *arg)
359{
360 const char *errstr = NULL((void *)0);
361
362 cfg.nsec = strtonum(arg, 0, LONG_MAX0x7fffffffffffffffL, &errstr);
363 if (errstr != NULL((void *)0)) {
364 BIO_printf(bio_err, "Illegal validity period %s: %s\n",
365 arg, errstr);
366 return (1);
367 }
368 return (0);
369}
370
371static const struct option ocsp_options[] = {
372 {
373 .name = "CA",
374 .argname = "file",
375 .desc = "CA certificate corresponding to the revocation information",
376 .type = OPTION_ARG,
377 .opt.arg = &cfg.rca_filename,
378 },
379 {
380 .name = "CAfile",
381 .argname = "file",
382 .desc = "Trusted certificates file",
383 .type = OPTION_ARG,
384 .opt.arg = &cfg.CAfile,
385 },
386 {
387 .name = "CApath",
388 .argname = "directory",
389 .desc = "Trusted certificates directory",
390 .type = OPTION_ARG,
391 .opt.arg = &cfg.CApath,
392 },
393 {
394 .name = "cert",
395 .argname = "file",
396 .desc = "Certificate to check",
397 .type = OPTION_ARG_FUNC,
398 .opt.argfunc = ocsp_opt_cert,
399 },
400 {
401 .name = "header",
402 .argname = "name value",
403 .desc = "Add the header name with the value to the request",
404 .type = OPTION_ARGV_FUNC,
405 .opt.argvfunc = ocsp_opt_header,
406 },
407 {
408 .name = "host",
409 .argname = "hostname:port",
410 .desc = "Send OCSP request to host on port",
411 .type = OPTION_ARG_FUNC,
412 .opt.argfunc = ocsp_opt_host,
413 },
414 {
415 .name = "ignore_err",
416 .desc = "Ignore the invalid response",
417 .type = OPTION_FLAG,
418 .opt.flag = &cfg.ignore_err,
419 },
420 {
421 .name = "index",
422 .argname = "indexfile",
423 .desc = "Certificate status index file",
424 .type = OPTION_ARG,
425 .opt.arg = &cfg.ridx_filename,
426 },
427 {
428 .name = "issuer",
429 .argname = "file",
430 .desc = "Issuer certificate",
431 .type = OPTION_ARG_FUNC,
432 .opt.argfunc = ocsp_opt_issuer,
433 },
434 {
435 .name = "ndays",
436 .argname = "days",
437 .desc = "Number of days before next update",
438 .type = OPTION_ARG_FUNC,
439 .opt.argfunc = ocsp_opt_ndays,
440 },
441 {
442 .name = "nmin",
443 .argname = "minutes",
444 .desc = "Number of minutes before next update",
445 .type = OPTION_ARG_FUNC,
446 .opt.argfunc = ocsp_opt_nmin,
447 },
448 {
449 .name = "no_cert_checks",
450 .desc = "Don't do additional checks on signing certificate",
451 .type = OPTION_UL_VALUE_OR,
452 .opt.ulvalue = &cfg.verify_flags,
453 .ulvalue = OCSP_NOCHECKS0x100,
454 },
455 {
456 .name = "no_cert_verify",
457 .desc = "Don't check signing certificate",
458 .type = OPTION_UL_VALUE_OR,
459 .opt.ulvalue = &cfg.verify_flags,
460 .ulvalue = OCSP_NOVERIFY0x10,
461 },
462 {
463 .name = "no_certs",
464 .desc = "Don't include any certificates in signed request",
465 .type = OPTION_UL_VALUE_OR,
466 .opt.ulvalue = &cfg.sign_flags,
467 .ulvalue = OCSP_NOCERTS0x1,
468 },
469 {
470 .name = "no_chain",
471 .desc = "Don't use certificates in the response",
472 .type = OPTION_UL_VALUE_OR,
473 .opt.ulvalue = &cfg.verify_flags,
474 .ulvalue = OCSP_NOCHAIN0x8,
475 },
476 {
477 .name = "no_explicit",
478 .desc = "Don't check the explicit trust for OCSP signing",
479 .type = OPTION_UL_VALUE_OR,
480 .opt.ulvalue = &cfg.verify_flags,
481 .ulvalue = OCSP_NOEXPLICIT0x20,
482 },
483 {
484 .name = "no_intern",
485 .desc = "Don't search certificates contained in response for signer",
486 .type = OPTION_UL_VALUE_OR,
487 .opt.ulvalue = &cfg.verify_flags,
488 .ulvalue = OCSP_NOINTERN0x2,
489 },
490 {
491 .name = "no_nonce",
492 .desc = "Don't add OCSP nonce to request",
493 .type = OPTION_VALUE,
494 .opt.value = &cfg.add_nonce,
495 .value = 0,
496 },
497 {
498 .name = "no_signature_verify",
499 .desc = "Don't check signature on response",
500 .type = OPTION_UL_VALUE_OR,
501 .opt.ulvalue = &cfg.verify_flags,
502 .ulvalue = OCSP_NOSIGS0x4,
503 },
504 {
505 .name = "nonce",
506 .desc = "Add OCSP nonce to request",
507 .type = OPTION_VALUE,
508 .opt.value = &cfg.add_nonce,
509 .value = 2,
510 },
511 {
512 .name = "noverify",
513 .desc = "Don't verify response at all",
514 .type = OPTION_FLAG,
515 .opt.flag = &cfg.noverify,
516 },
517 {
518 .name = "nrequest",
519 .argname = "number",
520 .desc = "Number of requests to accept (default unlimited)",
521 .type = OPTION_ARG_FUNC,
522 .opt.argfunc = ocsp_opt_nrequest,
523 },
524 {
525 .name = "out",
526 .argname = "file",
527 .desc = "Output filename",
528 .type = OPTION_ARG,
529 .opt.arg = &cfg.outfile,
530 },
531 {
532 .name = "path",
533 .argname = "path",
534 .desc = "Path to use in OCSP request",
535 .type = OPTION_ARG,
536 .opt.arg = &cfg.path,
537 },
538 {
539 .name = "port",
540 .argname = "portnum",
541 .desc = "Port to run responder on",
542 .type = OPTION_ARG_FUNC,
543 .opt.argfunc = ocsp_opt_port,
544 },
545 {
546 .name = "req_text",
547 .desc = "Print text form of request",
548 .type = OPTION_FLAG,
549 .opt.flag = &cfg.req_text,
550 },
551 {
552 .name = "reqin",
553 .argname = "file",
554 .desc = "Read DER encoded OCSP request from \"file\"",
555 .type = OPTION_ARG,
556 .opt.arg = &cfg.reqin,
557 },
558 {
559 .name = "reqout",
560 .argname = "file",
561 .desc = "Write DER encoded OCSP request to \"file\"",
562 .type = OPTION_ARG,
563 .opt.arg = &cfg.reqout,
564 },
565 {
566 .name = "resp_key_id",
567 .desc = "Identify response by signing certificate key ID",
568 .type = OPTION_UL_VALUE_OR,
569 .opt.ulvalue = &cfg.rflags,
570 .ulvalue = OCSP_RESPID_KEY0x400,
571 },
572 {
573 .name = "resp_no_certs",
574 .desc = "Don't include any certificates in response",
575 .type = OPTION_UL_VALUE_OR,
576 .opt.ulvalue = &cfg.rflags,
577 .ulvalue = OCSP_NOCERTS0x1,
578 },
579 {
580 .name = "resp_text",
581 .desc = "Print text form of response",
582 .type = OPTION_FLAG,
583 .opt.flag = &cfg.resp_text,
584 },
585 {
586 .name = "respin",
587 .argname = "file",
588 .desc = "Read DER encoded OCSP response from \"file\"",
589 .type = OPTION_ARG,
590 .opt.arg = &cfg.respin,
591 },
592 {
593 .name = "respout",
594 .argname = "file",
595 .desc = "Write DER encoded OCSP response to \"file\"",
596 .type = OPTION_ARG,
597 .opt.arg = &cfg.respout,
598 },
599 {
600 .name = "rkey",
601 .argname = "file",
602 .desc = "Responder key to sign responses with",
603 .type = OPTION_ARG,
604 .opt.arg = &cfg.rkeyfile,
605 },
606 {
607 .name = "rother",
608 .argname = "file",
609 .desc = "Other certificates to include in response",
610 .type = OPTION_ARG,
611 .opt.arg = &cfg.rcertfile,
612 },
613 {
614 .name = "rsigner",
615 .argname = "file",
616 .desc = "Responder certificate to sign responses with",
617 .type = OPTION_ARG,
618 .opt.arg = &cfg.rsignfile,
619 },
620 {
621 .name = "serial",
622 .argname = "num",
623 .desc = "Serial number to check",
624 .type = OPTION_ARG_FUNC,
625 .opt.argfunc = ocsp_opt_serial,
626 },
627 {
628 .name = "sign_other",
629 .argname = "file",
630 .desc = "Additional certificates to include in signed request",
631 .type = OPTION_ARG,
632 .opt.arg = &cfg.sign_certfile,
633 },
634 {
635 .name = "signer",
636 .argname = "file",
637 .desc = "Certificate to sign OCSP request with",
638 .type = OPTION_ARG,
639 .opt.arg = &cfg.signfile,
640 },
641 {
642 .name = "signkey",
643 .argname = "file",
644 .desc = "Private key to sign OCSP request with",
645 .type = OPTION_ARG,
646 .opt.arg = &cfg.keyfile,
647 },
648 {
649 .name = "status_age",
650 .argname = "age",
651 .desc = "Maximum status age in seconds",
652 .type = OPTION_ARG_FUNC,
653 .opt.argfunc = ocsp_opt_status_age,
654 },
655 {
656 .name = "text",
657 .desc = "Print text form of request and response",
658 .type = OPTION_FUNC,
659 .opt.func = ocsp_opt_text,
660 },
661 {
662 .name = "timeout",
663 .argname = "seconds",
664 .desc = "Connection timeout to the OCSP responder in seconds",
665 .type = OPTION_ARG_FUNC,
666 .opt.argfunc = ocsp_opt_timeout,
667 },
668 {
669 .name = "trust_other",
670 .desc = "Don't verify additional certificates",
671 .type = OPTION_UL_VALUE_OR,
672 .opt.ulvalue = &cfg.verify_flags,
673 .ulvalue = OCSP_TRUSTOTHER0x200,
674 },
675 {
676 .name = "url",
677 .argname = "responder_url",
678 .desc = "OCSP responder URL",
679 .type = OPTION_ARG_FUNC,
680 .opt.argfunc = ocsp_opt_url,
681 },
682 {
683 .name = "VAfile",
684 .argname = "file",
685 .desc = "Explicitly trusted responder certificates",
686 .type = OPTION_ARG_FUNC,
687 .opt.argfunc = ocsp_opt_vafile,
688 },
689 {
690 .name = "validity_period",
691 .argname = "n",
692 .desc = "Maximum validity discrepancy in seconds",
693 .type = OPTION_ARG_FUNC,
694 .opt.argfunc = ocsp_opt_validity_period,
695 },
696 {
697 .name = "verify_other",
698 .argname = "file",
699 .desc = "Additional certificates to search for signer",
700 .type = OPTION_ARG,
701 .opt.arg = &cfg.verify_certfile,
702 },
703 {
704 .name = NULL((void *)0),
705 .desc = "",
706 .type = OPTION_ARGV_FUNC,
707 .opt.argvfunc = ocsp_opt_cert_id_md,
708 },
709 { NULL((void *)0) },
710};
711
712static void
713ocsp_usage(void)
714{
715 fprintf(stderr(&__sF[2]), "usage: ocsp "
716 "[-CA file] [-CAfile file] [-CApath directory] [-cert file]\n"
717 " [-dgst alg] [-header name value] [-host hostname:port]\n"
718 " [-ignore_err] [-index indexfile] [-issuer file]\n"
719 " [-ndays days] [-nmin minutes] [-no_cert_checks]\n"
720 " [-no_cert_verify] [-no_certs] [-no_chain] [-no_explicit]\n"
721 " [-no_intern] [-no_nonce] [-no_signature_verify] [-nonce]\n"
722 " [-noverify] [-nrequest number] [-out file] [-path path]\n"
723 " [-port portnum] [-req_text] [-reqin file] [-reqout file]\n"
724 " [-resp_key_id] [-resp_no_certs] [-resp_text] [-respin file]\n"
725 " [-respout file] [-rkey file] [-rother file] [-rsigner file]\n"
726 " [-serial num] [-sign_other file] [-signer file]\n"
727 " [-signkey file] [-status_age age] [-text]\n"
728 " [-timeout seconds] [-trust_other] [-url responder_url]\n"
729 " [-VAfile file] [-validity_period nsec] [-verify_other file]\n");
730 fprintf(stderr(&__sF[2]), "\n");
731 options_usage(ocsp_options);
732 fprintf(stderr(&__sF[2]), "\n");
733}
734
735int
736ocsp_main(int argc, char **argv)
737{
738 OCSP_RESPONSE *resp = NULL((void *)0);
739 OCSP_BASICRESP *bs = NULL((void *)0);
740 X509 *signer = NULL((void *)0), *rsigner = NULL((void *)0);
741 EVP_PKEY *key = NULL((void *)0), *rkey = NULL((void *)0);
742 BIO *acbio = NULL((void *)0), *cbio = NULL((void *)0);
743 BIO *derbio = NULL((void *)0);
744 BIO *out = NULL((void *)0);
745 X509_STORE *store = NULL((void *)0);
746 STACK_OF(X509)struct stack_st_X509 *sign_other = NULL((void *)0), *verify_other = NULL((void *)0), *rother = NULL((void *)0);
747 int ret = 1;
748 int badarg = 0;
749 int i;
750 X509 *rca_cert = NULL((void *)0);
751 CA_DB *rdb = NULL((void *)0);
752
753 if (pledge("stdio cpath wpath rpath inet dns tty", NULL((void *)0)) == -1) {
754 perror("pledge");
755 exit(1);
756 }
757
758 memset(&cfg, 0, sizeof(cfg));
759 cfg.accept_count = -1;
760 cfg.add_nonce = 1;
761 if ((cfg.ids = sk_OCSP_CERTID_new_null()((struct stack_st_OCSP_CERTID *)sk_new_null())) == NULL((void *)0))
762 goto end;
763 cfg.maxage = -1;
764 cfg.ndays = -1;
765 cfg.nsec = MAX_VALIDITY_PERIOD(5 * 60);
766 cfg.req_timeout = -1;
767 if ((cfg.reqnames = sk_OPENSSL_STRING_new_null()((struct stack_st_OPENSSL_STRING *)sk_new_null())) == NULL((void *)0))
768 goto end;
769 cfg.use_ssl = -1;
770
771 if (options_parse(argc, argv, ocsp_options, NULL((void *)0), NULL((void *)0)) != 0) {
772 if (cfg.no_usage)
773 goto end;
774 else
775 badarg = 1;
776 }
777
778 /* Have we anything to do? */
779 if (!cfg.req && !cfg.reqin && !cfg.respin &&
780 !(cfg.port && cfg.ridx_filename))
781 badarg = 1;
782
783 if (badarg) {
784 ocsp_usage();
785 goto end;
786 }
787 if (cfg.outfile)
788 out = BIO_new_file(cfg.outfile, "w");
789 else
790 out = BIO_new_fp(stdout(&__sF[1]), BIO_NOCLOSE0x00);
791
792 if (!out) {
793 BIO_printf(bio_err, "Error opening output file\n");
794 goto end;
795 }
796 if (!cfg.req && (cfg.add_nonce != 2))
797 cfg.add_nonce = 0;
798
799 if (!cfg.req && cfg.reqin) {
800 derbio = BIO_new_file(cfg.reqin, "rb");
801 if (!derbio) {
802 BIO_printf(bio_err,
803 "Error Opening OCSP request file\n");
804 goto end;
805 }
806 cfg.req = d2i_OCSP_REQUEST_bio(derbio, NULL((void *)0));
807 BIO_free(derbio);
808 if (!cfg.req) {
809 BIO_printf(bio_err, "Error reading OCSP request\n");
810 goto end;
811 }
812 }
813 if (!cfg.req && cfg.port) {
814 acbio = init_responder(cfg.port);
815 if (!acbio)
816 goto end;
817 }
818 if (cfg.rsignfile && !rdb) {
819 if (!cfg.rkeyfile)
820 cfg.rkeyfile = cfg.rsignfile;
821 rsigner = load_cert(bio_err, cfg.rsignfile, FORMAT_PEM3,
822 NULL((void *)0), "responder certificate");
823 if (!rsigner) {
824 BIO_printf(bio_err,
825 "Error loading responder certificate\n");
826 goto end;
827 }
828 rca_cert = load_cert(bio_err, cfg.rca_filename,
829 FORMAT_PEM3, NULL((void *)0), "CA certificate");
830 if (cfg.rcertfile) {
831 rother = load_certs(bio_err, cfg.rcertfile,
832 FORMAT_PEM3, NULL((void *)0), "responder other certificates");
833 if (!rother)
834 goto end;
835 }
836 rkey = load_key(bio_err, cfg.rkeyfile, FORMAT_PEM3, 0,
837 NULL((void *)0), "responder private key");
838 if (!rkey)
839 goto end;
840 }
841 if (acbio)
842 BIO_printf(bio_err, "Waiting for OCSP client connections...\n");
843
844 redo_accept:
845
846 if (acbio) {
847 if (!do_responder(&cfg.req, &cbio, acbio,
848 cfg.port))
849 goto end;
850 if (!cfg.req) {
851 resp = OCSP_response_create(
852 OCSP_RESPONSE_STATUS_MALFORMEDREQUEST1, NULL((void *)0));
853 send_ocsp_response(cbio, resp);
854 goto done_resp;
855 }
856 }
857 if (!cfg.req &&
858 (cfg.signfile || cfg.reqout || cfg.host ||
859 cfg.add_nonce || cfg.ridx_filename)) {
860 BIO_printf(bio_err,
861 "Need an OCSP request for this operation!\n");
862 goto end;
863 }
864 if (cfg.req && cfg.add_nonce)
865 OCSP_request_add1_nonce(cfg.req, NULL((void *)0), -1);
866
867 if (cfg.signfile) {
868 if (!cfg.keyfile)
869 cfg.keyfile = cfg.signfile;
870 signer = load_cert(bio_err, cfg.signfile, FORMAT_PEM3,
871 NULL((void *)0), "signer certificate");
872 if (!signer) {
873 BIO_printf(bio_err,
874 "Error loading signer certificate\n");
875 goto end;
876 }
877 if (cfg.sign_certfile) {
878 sign_other = load_certs(bio_err,
879 cfg.sign_certfile, FORMAT_PEM3, NULL((void *)0),
880 "signer certificates");
881 if (!sign_other)
882 goto end;
883 }
884 key = load_key(bio_err, cfg.keyfile, FORMAT_PEM3, 0,
885 NULL((void *)0), "signer private key");
886 if (!key)
887 goto end;
888
889 if (!OCSP_request_sign(cfg.req, signer, key, NULL((void *)0),
890 sign_other, cfg.sign_flags)) {
891 BIO_printf(bio_err, "Error signing OCSP request\n");
892 goto end;
893 }
894 }
895 if (cfg.req_text && cfg.req)
896 OCSP_REQUEST_print(out, cfg.req, 0);
897
898 if (cfg.reqout) {
899 derbio = BIO_new_file(cfg.reqout, "wb");
900 if (!derbio) {
901 BIO_printf(bio_err, "Error opening file %s\n",
902 cfg.reqout);
903 goto end;
904 }
905 i2d_OCSP_REQUEST_bio(derbio, cfg.req);
906 BIO_free(derbio);
907 }
908 if (cfg.ridx_filename && (!rkey || !rsigner || !rca_cert)) {
909 BIO_printf(bio_err,
910 "Need a responder certificate, key and CA for this operation!\n");
911 goto end;
912 }
913 if (cfg.ridx_filename && !rdb) {
914 rdb = load_index(cfg.ridx_filename, NULL((void *)0));
915 if (!rdb)
916 goto end;
917 if (!index_index(rdb))
918 goto end;
919 }
920 if (rdb) {
921 i = make_ocsp_response(&resp, cfg.req, rdb, rca_cert,
Value stored to 'i' is never read
922 rsigner, rkey, rother, cfg.rflags,
923 cfg.nmin, cfg.ndays);
924 if (cbio)
925 send_ocsp_response(cbio, resp);
926 } else if (cfg.host) {
927 resp = process_responder(bio_err, cfg.req,
928 cfg.host,
929 cfg.path ? cfg.path : "/",
930 cfg.port, cfg.use_ssl, cfg.headers,
931 cfg.req_timeout);
932 if (!resp)
933 goto end;
934 } else if (cfg.respin) {
935 derbio = BIO_new_file(cfg.respin, "rb");
936 if (!derbio) {
937 BIO_printf(bio_err,
938 "Error Opening OCSP response file\n");
939 goto end;
940 }
941 resp = d2i_OCSP_RESPONSE_bio(derbio, NULL((void *)0));
942 BIO_free(derbio);
943 if (!resp) {
944 BIO_printf(bio_err, "Error reading OCSP response\n");
945 goto end;
946 }
947 } else {
948 ret = 0;
949 goto end;
950 }
951
952 done_resp:
953
954 if (cfg.respout) {
955 derbio = BIO_new_file(cfg.respout, "wb");
956 if (!derbio) {
957 BIO_printf(bio_err, "Error opening file %s\n",
958 cfg.respout);
959 goto end;
960 }
961 i2d_OCSP_RESPONSE_bio(derbio, resp);
962 BIO_free(derbio);
963 }
964 i = OCSP_response_status(resp);
965
966 if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL0) {
967 BIO_printf(bio_err, "Responder Error: %s (%d)\n",
968 OCSP_response_status_str(i), i);
969 if (cfg.ignore_err)
970 goto redo_accept;
971 ret = 1;
972 goto end;
973 }
974 if (cfg.resp_text)
975 OCSP_RESPONSE_print(out, resp, 0);
976
977 /* If running as responder don't verify our own response */
978 if (cbio) {
979 if (cfg.accept_count > 0)
980 cfg.accept_count--;
981 /* Redo if more connections needed */
982 if (cfg.accept_count) {
983 BIO_free_all(cbio);
984 cbio = NULL((void *)0);
985 OCSP_REQUEST_free(cfg.req);
986 cfg.req = NULL((void *)0);
987 OCSP_RESPONSE_free(resp);
988 resp = NULL((void *)0);
989 goto redo_accept;
990 }
991 goto end;
992 }
993 if (!store)
994 store = setup_verify(bio_err, cfg.CAfile,
995 cfg.CApath);
996 if (!store)
997 goto end;
998 if (cfg.verify_certfile) {
999 verify_other = load_certs(bio_err, cfg.verify_certfile,
1000 FORMAT_PEM3, NULL((void *)0), "validator certificate");
1001 if (!verify_other)
1002 goto end;
1003 }
1004 bs = OCSP_response_get1_basic(resp);
1005
1006 if (!bs) {
1007 BIO_printf(bio_err, "Error parsing response\n");
1008 goto end;
1009 }
1010 if (!cfg.noverify) {
1011 if (cfg.req &&
1012 ((i = OCSP_check_nonce(cfg.req, bs)) <= 0)) {
1013 if (i == -1) {
1014 BIO_printf(bio_err,
1015 "WARNING: no nonce in response\n");
1016 } else {
1017 BIO_printf(bio_err, "Nonce Verify error\n");
1018 goto end;
1019 }
1020 }
1021 i = OCSP_basic_verify(bs, verify_other, store,
1022 cfg.verify_flags);
1023 if (i < 0)
1024 i = OCSP_basic_verify(bs, NULL((void *)0), store, 0);
1025
1026 if (i <= 0) {
1027 BIO_printf(bio_err, "Response Verify Failure\n");
1028 ERR_print_errors(bio_err);
1029 } else {
1030 BIO_printf(bio_err, "Response verify OK\n");
1031 }
1032 }
1033 if (!print_ocsp_summary(out, bs, cfg.req, cfg.reqnames,
1034 cfg.ids, cfg.nsec, cfg.maxage))
1035 goto end;
1036
1037 ret = 0;
1038
1039 end:
1040 ERR_print_errors(bio_err);
1041 X509_free(signer);
1042 X509_STORE_free(store);
1043 EVP_PKEY_free(key);
1044 EVP_PKEY_free(rkey);
1045 X509_free(cfg.issuer);
1046 X509_free(cfg.cert);
1047 X509_free(rsigner);
1048 X509_free(rca_cert);
1049 free_index(rdb);
1050 BIO_free_all(cbio);
1051 BIO_free_all(acbio);
1052 BIO_free(out);
1053 OCSP_REQUEST_free(cfg.req);
1054 OCSP_RESPONSE_free(resp);
1055 OCSP_BASICRESP_free(bs);
1056 sk_OPENSSL_STRING_free(cfg.reqnames)sk_free(((_STACK*) (1 ? cfg.reqnames : (struct stack_st_OPENSSL_STRING
*)0)))
;
1057 sk_OCSP_CERTID_free(cfg.ids)sk_free(((_STACK*) (1 ? (cfg.ids) : (struct stack_st_OCSP_CERTID
*)0)))
;
1058 sk_X509_pop_free(sign_other, X509_free)sk_pop_free(((_STACK*) (1 ? (sign_other) : (struct stack_st_X509
*)0)), ((void (*)(void *)) ((1 ? (X509_free) : (void (*)(X509
*))0))))
;
1059 sk_X509_pop_free(verify_other, X509_free)sk_pop_free(((_STACK*) (1 ? (verify_other) : (struct stack_st_X509
*)0)), ((void (*)(void *)) ((1 ? (X509_free) : (void (*)(X509
*))0))))
;
1060 sk_CONF_VALUE_pop_free(cfg.headers, X509V3_conf_free)sk_pop_free(((_STACK*) (1 ? (cfg.headers) : (struct stack_st_CONF_VALUE
*)0)), ((void (*)(void *)) ((1 ? (X509V3_conf_free) : (void (
*)(CONF_VALUE *))0))))
;
1061
1062 if (cfg.use_ssl != -1) {
1063 free(cfg.host);
1064 free(cfg.port);
1065 free(cfg.path);
1066 }
1067 return (ret);
1068}
1069
1070static int
1071add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, const EVP_MD *cert_id_md,
1072 X509 *issuer, STACK_OF(OCSP_CERTID)struct stack_st_OCSP_CERTID *ids)
1073{
1074 OCSP_CERTID *id;
1075
1076 if (!issuer) {
1077 BIO_printf(bio_err, "No issuer certificate specified\n");
1078 return 0;
1079 }
1080 if (!*req)
1081 *req = OCSP_REQUEST_new();
1082 if (!*req)
1083 goto err;
1084 id = OCSP_cert_to_id(cert_id_md, cert, issuer);
1085 if (!id || !sk_OCSP_CERTID_push(ids, id)sk_push(((_STACK*) (1 ? (ids) : (struct stack_st_OCSP_CERTID*
)0)), ((void*) (1 ? (id) : (OCSP_CERTID*)0)))
)
1086 goto err;
1087 if (!OCSP_request_add0_id(*req, id))
1088 goto err;
1089 return 1;
1090
1091 err:
1092 BIO_printf(bio_err, "Error Creating OCSP request\n");
1093 return 0;
1094}
1095
1096static int
1097add_ocsp_serial(OCSP_REQUEST **req, char *serial, const EVP_MD *cert_id_md,
1098 X509 *issuer, STACK_OF(OCSP_CERTID)struct stack_st_OCSP_CERTID *ids)
1099{
1100 OCSP_CERTID *id;
1101 X509_NAME *iname;
1102 ASN1_BIT_STRING *ikey;
1103 ASN1_INTEGER *sno;
1104
1105 if (!issuer) {
1106 BIO_printf(bio_err, "No issuer certificate specified\n");
1107 return 0;
1108 }
1109 if (!*req)
1110 *req = OCSP_REQUEST_new();
1111 if (!*req)
1112 goto err;
1113 iname = X509_get_subject_name(issuer);
1114 ikey = X509_get0_pubkey_bitstr(issuer);
1115 sno = s2i_ASN1_INTEGER(NULL((void *)0), serial);
1116 if (!sno) {
1117 BIO_printf(bio_err, "Error converting serial number %s\n",
1118 serial);
1119 return 0;
1120 }
1121 id = OCSP_cert_id_new(cert_id_md, iname, ikey, sno);
1122 ASN1_INTEGER_free(sno);
1123 if (!id || !sk_OCSP_CERTID_push(ids, id)sk_push(((_STACK*) (1 ? (ids) : (struct stack_st_OCSP_CERTID*
)0)), ((void*) (1 ? (id) : (OCSP_CERTID*)0)))
)
1124 goto err;
1125 if (!OCSP_request_add0_id(*req, id))
1126 goto err;
1127 return 1;
1128
1129 err:
1130 BIO_printf(bio_err, "Error Creating OCSP request\n");
1131 return 0;
1132}
1133
1134static int
1135print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
1136 STACK_OF(OPENSSL_STRING)struct stack_st_OPENSSL_STRING *names, STACK_OF(OCSP_CERTID)struct stack_st_OCSP_CERTID *ids, long nsec,
1137 long maxage)
1138{
1139 OCSP_CERTID *id;
1140 char *name;
1141 int i;
1142 int status, reason;
1143
1144 ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
1145
1146 if (!bs || !req || !sk_OPENSSL_STRING_num(names)sk_num(((_STACK*) (1 ? names : (struct stack_st_OPENSSL_STRING
*)0)))
||
1147 !sk_OCSP_CERTID_num(ids)sk_num(((_STACK*) (1 ? (ids) : (struct stack_st_OCSP_CERTID*)
0)))
)
1148 return 1;
1149
1150 for (i = 0; i < sk_OCSP_CERTID_num(ids)sk_num(((_STACK*) (1 ? (ids) : (struct stack_st_OCSP_CERTID*)
0)))
; i++) {
1151 id = sk_OCSP_CERTID_value(ids, i)((OCSP_CERTID *)sk_value(((_STACK*) (1 ? (ids) : (struct stack_st_OCSP_CERTID
*)0)), (i)))
;
1152 name = sk_OPENSSL_STRING_value(names, i)((OPENSSL_STRING)sk_value(((_STACK*) (1 ? names : (struct stack_st_OPENSSL_STRING
*)0)), i))
;
1153 BIO_printf(out, "%s: ", name);
1154
1155 if (!OCSP_resp_find_status(bs, id, &status, &reason,
1156 &rev, &thisupd, &nextupd)) {
1157 BIO_puts(out, "ERROR: No Status found.\n");
1158 continue;
1159 }
1160 /*
1161 * Check validity: if invalid write to output BIO so we know
1162 * which response this refers to.
1163 */
1164 if (!OCSP_check_validity(thisupd, nextupd, nsec, maxage)) {
1165 BIO_puts(out, "WARNING: Status times invalid.\n");
1166 ERR_print_errors(out);
1167 }
1168 BIO_printf(out, "%s\n", OCSP_cert_status_str(status));
1169
1170 BIO_puts(out, "\tThis Update: ");
1171 ASN1_GENERALIZEDTIME_print(out, thisupd);
1172 BIO_puts(out, "\n");
1173
1174 if (nextupd) {
1175 BIO_puts(out, "\tNext Update: ");
1176 ASN1_GENERALIZEDTIME_print(out, nextupd);
1177 BIO_puts(out, "\n");
1178 }
1179 if (status != V_OCSP_CERTSTATUS_REVOKED1)
1180 continue;
1181
1182 if (reason != -1)
1183 BIO_printf(out, "\tReason: %s\n",
1184 OCSP_crl_reason_str(reason));
1185
1186 BIO_puts(out, "\tRevocation Time: ");
1187 ASN1_GENERALIZEDTIME_print(out, rev);
1188 BIO_puts(out, "\n");
1189 }
1190
1191 return 1;
1192}
1193
1194
1195static int
1196make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req, CA_DB *db,
1197 X509 *ca, X509 *rcert, EVP_PKEY *rkey, STACK_OF(X509)struct stack_st_X509 *rother,
1198 unsigned long flags, int nmin, int ndays)
1199{
1200 ASN1_TIME *thisupd = NULL((void *)0), *nextupd = NULL((void *)0);
1201 OCSP_CERTID *cid, *ca_id = NULL((void *)0);
1202 OCSP_BASICRESP *bs = NULL((void *)0);
1203 int i, id_count, ret = 1;
1204
1205 id_count = OCSP_request_onereq_count(req);
1206
1207 if (id_count <= 0) {
1208 *resp = OCSP_response_create(
1209 OCSP_RESPONSE_STATUS_MALFORMEDREQUEST1, NULL((void *)0));
1210 goto end;
1211 }
1212 bs = OCSP_BASICRESP_new();
1213 thisupd = X509_gmtime_adj(NULL((void *)0), 0);
1214 if (ndays != -1)
1215 nextupd = X509_gmtime_adj(NULL((void *)0), nmin * 60 + ndays * 3600 * 24);
1216
1217 /* Examine each certificate id in the request */
1218 for (i = 0; i < id_count; i++) {
1219 OCSP_ONEREQ *one;
1220 ASN1_INTEGER *serial;
1221 char **inf;
1222 ASN1_OBJECT *cert_id_md_oid;
1223 const EVP_MD *cert_id_md;
1224 one = OCSP_request_onereq_get0(req, i);
1225 cid = OCSP_onereq_get0_id(one);
1226
1227 OCSP_id_get0_info(NULL((void *)0), &cert_id_md_oid, NULL((void *)0), NULL((void *)0), cid);
1228
1229 cert_id_md = EVP_get_digestbyobj(cert_id_md_oid)EVP_get_digestbyname(OBJ_nid2sn(OBJ_obj2nid(cert_id_md_oid)));
1230 if (!cert_id_md) {
1231 *resp = OCSP_response_create(
1232 OCSP_RESPONSE_STATUS_INTERNALERROR2, NULL((void *)0));
1233 goto end;
1234 }
1235 OCSP_CERTID_free(ca_id);
1236 ca_id = OCSP_cert_to_id(cert_id_md, NULL((void *)0), ca);
1237
1238 /* Is this request about our CA? */
1239 if (OCSP_id_issuer_cmp(ca_id, cid)) {
1240 OCSP_basic_add1_status(bs, cid,
1241 V_OCSP_CERTSTATUS_UNKNOWN2, 0, NULL((void *)0),
1242 thisupd, nextupd);
1243 continue;
1244 }
1245 OCSP_id_get0_info(NULL((void *)0), NULL((void *)0), NULL((void *)0), &serial, cid);
1246 inf = lookup_serial(db, serial);
1247 if (!inf) {
1248 OCSP_basic_add1_status(bs, cid,
1249 V_OCSP_CERTSTATUS_UNKNOWN2, 0, NULL((void *)0),
1250 thisupd, nextupd);
1251 } else if (inf[DB_type0][0] == DB_TYPE_VAL'V') {
1252 OCSP_basic_add1_status(bs, cid,
1253 V_OCSP_CERTSTATUS_GOOD0, 0, NULL((void *)0),
1254 thisupd, nextupd);
1255 } else if (inf[DB_type0][0] == DB_TYPE_REV'R') {
1256 ASN1_OBJECT *inst = NULL((void *)0);
1257 ASN1_TIME *revtm = NULL((void *)0);
1258 ASN1_GENERALIZEDTIME *invtm = NULL((void *)0);
1259 OCSP_SINGLERESP *single;
1260 int reason = -1;
1261
1262 unpack_revinfo(&revtm, &reason, &inst, &invtm,
1263 inf[DB_rev_date2]);
1264 single = OCSP_basic_add1_status(bs, cid,
1265 V_OCSP_CERTSTATUS_REVOKED1,
1266 reason, revtm,
1267 thisupd, nextupd);
1268 if (invtm)
1269 OCSP_SINGLERESP_add1_ext_i2d(single,
1270 NID_invalidity_date142, invtm, 0, 0);
1271 else if (inst)
1272 OCSP_SINGLERESP_add1_ext_i2d(single,
1273 NID_hold_instruction_code430, inst, 0, 0);
1274 ASN1_OBJECT_free(inst);
1275 ASN1_TIME_free(revtm);
1276 ASN1_GENERALIZEDTIME_free(invtm);
1277 }
1278 }
1279
1280 OCSP_copy_nonce(bs, req);
1281
1282 OCSP_basic_sign(bs, rcert, rkey, NULL((void *)0), rother, flags);
1283
1284 *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_SUCCESSFUL0, bs);
1285
1286 end:
1287 ASN1_TIME_free(thisupd);
1288 ASN1_TIME_free(nextupd);
1289 OCSP_CERTID_free(ca_id);
1290 OCSP_BASICRESP_free(bs);
1291 return ret;
1292}
1293
1294static char **
1295lookup_serial(CA_DB *db, ASN1_INTEGER *ser)
1296{
1297 int i;
1298 BIGNUM *bn = NULL((void *)0);
1299 char *itmp, *row[DB_NUMBER6], **rrow;
1300
1301 for (i = 0; i < DB_NUMBER6; i++)
1302 row[i] = NULL((void *)0);
1303 bn = ASN1_INTEGER_to_BN(ser, NULL((void *)0));
1304 OPENSSL_assert(bn)(void)((bn) ? 0 : (OpenSSLDie("/usr/src/usr.bin/openssl/ocsp.c"
, 1304, "bn"),1))
; /* FIXME: should report an error at this
1305 * point and abort */
1306 if (BN_is_zero(bn))
1307 itmp = strdup("00");
1308 else
1309 itmp = BN_bn2hex(bn);
1310 row[DB_serial3] = itmp;
1311 BN_free(bn);
1312 rrow = TXT_DB_get_by_index(db->db, DB_serial3, row);
1313 free(itmp);
1314 return rrow;
1315}
1316
1317/* Quick and dirty OCSP server: read in and parse input request */
1318
1319static BIO *
1320init_responder(char *port)
1321{
1322 BIO *acbio = NULL((void *)0), *bufbio = NULL((void *)0);
1323
1324 bufbio = BIO_new(BIO_f_buffer());
1325 if (!bufbio)
1326 goto err;
1327 acbio = BIO_new_accept(port);
1328 if (!acbio)
1329 goto err;
1330 BIO_set_bind_mode(acbio, BIO_BIND_REUSEADDR)BIO_ctrl(acbio,131,2,((void *)0));
1331 BIO_set_accept_bios(acbio, bufbio)BIO_ctrl(acbio,118,2,(char *)bufbio);
1332 bufbio = NULL((void *)0);
1333
1334 if (BIO_do_accept(acbio)BIO_ctrl(acbio,101,0,((void *)0)) <= 0) {
1335 BIO_printf(bio_err, "Error setting up accept BIO\n");
1336 ERR_print_errors(bio_err);
1337 goto err;
1338 }
1339 return acbio;
1340
1341 err:
1342 BIO_free_all(acbio);
1343 BIO_free(bufbio);
1344 return NULL((void *)0);
1345}
1346
1347static int
1348do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, char *port)
1349{
1350 int have_post = 0, len;
1351 OCSP_REQUEST *req = NULL((void *)0);
1352 char inbuf[1024];
1353 BIO *cbio = NULL((void *)0);
1354
1355 if (BIO_do_accept(acbio)BIO_ctrl(acbio,101,0,((void *)0)) <= 0) {
1356 BIO_printf(bio_err, "Error accepting connection\n");
1357 ERR_print_errors(bio_err);
1358 return 0;
1359 }
1360 cbio = BIO_pop(acbio);
1361 *pcbio = cbio;
1362
1363 for (;;) {
1364 len = BIO_gets(cbio, inbuf, sizeof inbuf);
1365 if (len <= 0)
1366 return 1;
1367 /* Look for "POST" signalling start of query */
1368 if (!have_post) {
1369 if (strncmp(inbuf, "POST", 4)) {
1370 BIO_printf(bio_err, "Invalid request\n");
1371 return 1;
1372 }
1373 have_post = 1;
1374 }
1375 /* Look for end of headers */
1376 if ((inbuf[0] == '\r') || (inbuf[0] == '\n'))
1377 break;
1378 }
1379
1380 /* Try to read OCSP request */
1381
1382 req = d2i_OCSP_REQUEST_bio(cbio, NULL((void *)0));
1383
1384 if (!req) {
1385 BIO_printf(bio_err, "Error parsing OCSP request\n");
1386 ERR_print_errors(bio_err);
1387 }
1388 *preq = req;
1389
1390 return 1;
1391}
1392
1393static int
1394send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp)
1395{
1396 static const char http_resp[] =
1397 "HTTP/1.0 200 OK\r\nContent-type: application/ocsp-response\r\n"
1398 "Content-Length: %d\r\n\r\n";
1399
1400 if (!cbio)
1401 return 0;
1402 BIO_printf(cbio, http_resp, i2d_OCSP_RESPONSE(resp, NULL((void *)0)));
1403 i2d_OCSP_RESPONSE_bio(cbio, resp);
1404 (void) BIO_flush(cbio)(int)BIO_ctrl(cbio,11,0,((void *)0));
1405 return 1;
1406}
1407
1408static OCSP_RESPONSE *
1409query_responder(BIO *err, BIO *cbio, char *path, STACK_OF(CONF_VALUE)struct stack_st_CONF_VALUE *headers,
1410 const char *host, OCSP_REQUEST *req, int req_timeout)
1411{
1412 int fd;
1413 int rv;
1414 int i;
1415 int have_host = 0;
1416 OCSP_REQ_CTX *ctx = NULL((void *)0);
1417 OCSP_RESPONSE *rsp = NULL((void *)0);
1418 struct pollfd pfd[1];
1419
1420 if (req_timeout != -1)
1421 BIO_set_nbio(cbio, 1)BIO_ctrl(cbio,102,(1),((void *)0));
1422
1423 rv = BIO_do_connect(cbio)BIO_ctrl(cbio,101,0,((void *)0));
1424
1425 if ((rv <= 0) && ((req_timeout == -1) || !BIO_should_retry(cbio)BIO_test_flags(cbio, 0x08))) {
1426 BIO_puts(err, "Error connecting BIO\n");
1427 return NULL((void *)0);
1428 }
1429 if (BIO_get_fd(cbio, &fd)BIO_ctrl(cbio,105,0,(char *)&fd) < 0) {
1430 BIO_puts(err, "Can't get connection fd\n");
1431 goto err;
1432 }
1433 if (req_timeout != -1 && rv <= 0) {
1434 pfd[0].fd = fd;
1435 pfd[0].events = POLLOUT0x0004;
1436 rv = poll(pfd, 1, req_timeout * 1000);
1437 if (rv == 0) {
1438 BIO_puts(err, "Timeout on connect\n");
1439 return NULL((void *)0);
1440 }
1441 if (rv == -1) {
1442 BIO_puts(err, "Poll error\n");
1443 return NULL((void *)0);
1444 }
1445 }
1446 ctx = OCSP_sendreq_new(cbio, path, NULL((void *)0), -1);
1447 if (!ctx)
1448 return NULL((void *)0);
1449
1450 for (i = 0; i < sk_CONF_VALUE_num(headers)sk_num(((_STACK*) (1 ? (headers) : (struct stack_st_CONF_VALUE
*)0)))
; i++) {
1451 CONF_VALUE *hdr = sk_CONF_VALUE_value(headers, i)((CONF_VALUE *)sk_value(((_STACK*) (1 ? (headers) : (struct stack_st_CONF_VALUE
*)0)), (i)))
;
1452 if (strcasecmp("host", hdr->name) == 0)
1453 have_host = 1;
1454 if (!OCSP_REQ_CTX_add1_header(ctx, hdr->name, hdr->value))
1455 goto err;
1456 }
1457
1458 if (!have_host) {
1459 if (!OCSP_REQ_CTX_add1_header(ctx, "Host", host))
1460 goto err;
1461 }
1462
1463 if (!OCSP_REQ_CTX_set1_req(ctx, req))
1464 goto err;
1465
1466 for (;;) {
1467 rv = OCSP_sendreq_nbio(&rsp, ctx);
1468 if (rv != -1)
1469 break;
1470 if (req_timeout == -1)
1471 continue;
1472 pfd[0].fd = fd;
1473 if (BIO_should_read(cbio)BIO_test_flags(cbio, 0x01)) {
1474 pfd[0].events = POLLIN0x0001;
1475 } else if (BIO_should_write(cbio)BIO_test_flags(cbio, 0x02)) {
1476 pfd[0].events = POLLOUT0x0004;
1477 } else {
1478 BIO_puts(err, "Unexpected retry condition\n");
1479 goto err;
1480 }
1481 rv = poll(pfd, 1, req_timeout * 1000);
1482 if (rv == 0) {
1483 BIO_puts(err, "Timeout on request\n");
1484 break;
1485 }
1486 if (rv == -1 || (pfd[0].revents & (POLLERR0x0008|POLLNVAL0x0020))) {
1487 BIO_puts(err, "Poll error\n");
1488 break;
1489 }
1490 }
1491
1492 err:
1493 OCSP_REQ_CTX_free(ctx);
1494 return rsp;
1495}
1496
1497OCSP_RESPONSE *
1498process_responder(BIO *err, OCSP_REQUEST *req, char *host, char *path,
1499 char *port, int use_ssl, STACK_OF(CONF_VALUE)struct stack_st_CONF_VALUE *headers, int req_timeout)
1500{
1501 BIO *cbio = NULL((void *)0);
1502 SSL_CTX *ctx = NULL((void *)0);
1503 OCSP_RESPONSE *resp = NULL((void *)0);
1504
1505 cbio = BIO_new_connect(host);
1506 if (!cbio) {
1507 BIO_printf(err, "Error creating connect BIO\n");
1508 goto end;
1509 }
1510 if (port)
1511 BIO_set_conn_port(cbio, port)BIO_ctrl(cbio,100,1,(char *)port);
1512 if (use_ssl == 1) {
1513 BIO *sbio;
1514 ctx = SSL_CTX_new(TLS_client_method());
1515 if (ctx == NULL((void *)0)) {
1516 BIO_printf(err, "Error creating SSL context.\n");
1517 goto end;
1518 }
1519 SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY)SSL_CTX_ctrl((ctx),33,(0x00000004L),((void *)0));
1520 sbio = BIO_new_ssl(ctx, 1);
1521 cbio = BIO_push(sbio, cbio);
1522 }
1523 resp = query_responder(err, cbio, path, headers, host, req, req_timeout);
1524 if (!resp)
1525 BIO_printf(bio_err, "Error querying OCSP responder\n");
1526
1527 end:
1528 BIO_free_all(cbio);
1529 SSL_CTX_free(ctx);
1530 return resp;
1531}
1532#endif