Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ocsp.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -fno-rounding-math -mconstructor-aliases -munwind-tables -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/lib/clang/13.0.0 -D LIBRESSL_INTERNAL -internal-isystem /usr/local/lib/clang/13.0.0/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 -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/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/openssl/ocsp.c
1/* $OpenBSD: ocsp.c,v 1.21 2020/10/13 18:25:35 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} ocsp_config;
147
148static int
149ocsp_opt_cert(char *arg)
150{
151 X509_free(ocsp_config.cert);
152 ocsp_config.cert = load_cert(bio_err, arg, FORMAT_PEM3, NULL((void*)0),
153 "certificate");
154 if (ocsp_config.cert == NULL((void*)0)) {
155 ocsp_config.no_usage = 1;
156 return (1);
157 }
158 if (ocsp_config.cert_id_md == NULL((void*)0))
159 ocsp_config.cert_id_md = EVP_sha1();
160 if (!add_ocsp_cert(&ocsp_config.req, ocsp_config.cert,
161 ocsp_config.cert_id_md, ocsp_config.issuer, ocsp_config.ids)) {
162 ocsp_config.no_usage = 1;
163 return (1);
164 }
165 if (!sk_OPENSSL_STRING_push(ocsp_config.reqnames, arg)sk_push(((_STACK*) (1 ? ocsp_config.reqnames : (struct stack_st_OPENSSL_STRING
*)0)), ((void*) (1 ? arg : (char*)0)))
) {
166 ocsp_config.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 ((ocsp_config.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], &ocsp_config.headers)) {
194 ocsp_config.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 (ocsp_config.use_ssl != -1)
206 return (1);
207
208 ocsp_config.host = arg;
209 return (0);
210}
211
212static int
213ocsp_opt_issuer(char *arg)
214{
215 X509_free(ocsp_config.issuer);
216 ocsp_config.issuer = load_cert(bio_err, arg, FORMAT_PEM3, NULL((void*)0),
217 "issuer certificate");
218 if (ocsp_config.issuer == NULL((void*)0)) {
219 ocsp_config.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 ocsp_config.ndays = strtonum(arg, 0, INT_MAX2147483647, &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 ocsp_config.nmin = strtonum(arg, 0, INT_MAX2147483647, &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 (ocsp_config.ndays != -1)
252 return (1);
253
254 ocsp_config.ndays = 0;
255 return (0);
256}
257
258static int
259ocsp_opt_nrequest(char *arg)
260{
261 const char *errstr = NULL((void*)0);
262
263 ocsp_config.accept_count = strtonum(arg, 0, INT_MAX2147483647, &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 (ocsp_config.use_ssl != -1)
276 return (1);
277
278 ocsp_config.port = arg;
279 return (0);
280}
281
282static int
283ocsp_opt_serial(char *arg)
284{
285 if (ocsp_config.cert_id_md == NULL((void*)0))
286 ocsp_config.cert_id_md = EVP_sha1();
287 if (!add_ocsp_serial(&ocsp_config.req, arg, ocsp_config.cert_id_md,
288 ocsp_config.issuer, ocsp_config.ids)) {
289 ocsp_config.no_usage = 1;
290 return (1);
291 }
292 if (!sk_OPENSSL_STRING_push(ocsp_config.reqnames, arg)sk_push(((_STACK*) (1 ? ocsp_config.reqnames : (struct stack_st_OPENSSL_STRING
*)0)), ((void*) (1 ? arg : (char*)0)))
) {
293 ocsp_config.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 ocsp_config.maxage = strtonum(arg, 0, LONG_MAX9223372036854775807L, &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 ocsp_config.req_text = 1;
317 ocsp_config.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 ocsp_config.req_timeout = strtonum(arg, 0, INT_MAX2147483647, &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 (ocsp_config.host == NULL((void*)0) && ocsp_config.port == NULL((void*)0) &&
339 ocsp_config.path == NULL((void*)0)) {
340 if (!OCSP_parse_url(arg, &ocsp_config.host, &ocsp_config.port,
341 &ocsp_config.path, &ocsp_config.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 ocsp_config.verify_certfile = arg;
353 ocsp_config.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 ocsp_config.nsec = strtonum(arg, 0, LONG_MAX9223372036854775807L, &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 = &ocsp_config.rca_filename,
378 },
379 {
380 .name = "CAfile",
381 .argname = "file",
382 .desc = "Trusted certificates file",
383 .type = OPTION_ARG,
384 .opt.arg = &ocsp_config.CAfile,
385 },
386 {
387 .name = "CApath",
388 .argname = "directory",
389 .desc = "Trusted certificates directory",
390 .type = OPTION_ARG,
391 .opt.arg = &ocsp_config.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 = &ocsp_config.ignore_err,
419 },
420 {
421 .name = "index",
422 .argname = "indexfile",
423 .desc = "Certificate status index file",
424 .type = OPTION_ARG,
425 .opt.arg = &ocsp_config.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 = &ocsp_config.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 = &ocsp_config.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 = &ocsp_config.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 = &ocsp_config.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 = &ocsp_config.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 = &ocsp_config.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 = &ocsp_config.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 = &ocsp_config.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 = &ocsp_config.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 = &ocsp_config.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 = &ocsp_config.outfile,
530 },
531 {
532 .name = "path",
533 .argname = "path",
534 .desc = "Path to use in OCSP request",
535 .type = OPTION_ARG,
536 .opt.arg = &ocsp_config.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 = &ocsp_config.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 = &ocsp_config.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 = &ocsp_config.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 = &ocsp_config.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 = &ocsp_config.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 = &ocsp_config.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 = &ocsp_config.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 = &ocsp_config.respout,
598 },
599 {
600 .name = "rkey",
601 .argname = "file",
602 .desc = "Responder key to sign responses with",
603 .type = OPTION_ARG,
604 .opt.arg = &ocsp_config.rkeyfile,
605 },
606 {
607 .name = "rother",
608 .argname = "file",
609 .desc = "Other certificates to include in response",
610 .type = OPTION_ARG,
611 .opt.arg = &ocsp_config.rcertfile,
612 },
613 {
614 .name = "rsigner",
615 .argname = "file",
616 .desc = "Responder certificate to sign responses with",
617 .type = OPTION_ARG,
618 .opt.arg = &ocsp_config.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 = &ocsp_config.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 = &ocsp_config.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 = &ocsp_config.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 = &ocsp_config.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 = &ocsp_config.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 (single_execution) {
754 if (pledge("stdio cpath wpath rpath inet dns tty", NULL((void*)0)) == -1) {
755 perror("pledge");
756 exit(1);
757 }
758 }
759
760 memset(&ocsp_config, 0, sizeof(ocsp_config));
761 ocsp_config.accept_count = -1;
762 ocsp_config.add_nonce = 1;
763 if ((ocsp_config.ids = sk_OCSP_CERTID_new_null()((struct stack_st_OCSP_CERTID *)sk_new_null())) == NULL((void*)0))
764 goto end;
765 ocsp_config.maxage = -1;
766 ocsp_config.ndays = -1;
767 ocsp_config.nsec = MAX_VALIDITY_PERIOD(5 * 60);
768 ocsp_config.req_timeout = -1;
769 if ((ocsp_config.reqnames = sk_OPENSSL_STRING_new_null()((struct stack_st_OPENSSL_STRING *)sk_new_null())) == NULL((void*)0))
770 goto end;
771 ocsp_config.use_ssl = -1;
772
773 if (options_parse(argc, argv, ocsp_options, NULL((void*)0), NULL((void*)0)) != 0) {
774 if (ocsp_config.no_usage)
775 goto end;
776 else
777 badarg = 1;
778 }
779
780 /* Have we anything to do? */
781 if (!ocsp_config.req && !ocsp_config.reqin && !ocsp_config.respin &&
782 !(ocsp_config.port && ocsp_config.ridx_filename))
783 badarg = 1;
784
785 if (badarg) {
786 ocsp_usage();
787 goto end;
788 }
789 if (ocsp_config.outfile)
790 out = BIO_new_file(ocsp_config.outfile, "w");
791 else
792 out = BIO_new_fp(stdout(&__sF[1]), BIO_NOCLOSE0x00);
793
794 if (!out) {
795 BIO_printf(bio_err, "Error opening output file\n");
796 goto end;
797 }
798 if (!ocsp_config.req && (ocsp_config.add_nonce != 2))
799 ocsp_config.add_nonce = 0;
800
801 if (!ocsp_config.req && ocsp_config.reqin) {
802 derbio = BIO_new_file(ocsp_config.reqin, "rb");
803 if (!derbio) {
804 BIO_printf(bio_err,
805 "Error Opening OCSP request file\n");
806 goto end;
807 }
808 ocsp_config.req = d2i_OCSP_REQUEST_bio(derbio, NULL((void*)0));
809 BIO_free(derbio);
810 if (!ocsp_config.req) {
811 BIO_printf(bio_err, "Error reading OCSP request\n");
812 goto end;
813 }
814 }
815 if (!ocsp_config.req && ocsp_config.port) {
816 acbio = init_responder(ocsp_config.port);
817 if (!acbio)
818 goto end;
819 }
820 if (ocsp_config.rsignfile && !rdb) {
821 if (!ocsp_config.rkeyfile)
822 ocsp_config.rkeyfile = ocsp_config.rsignfile;
823 rsigner = load_cert(bio_err, ocsp_config.rsignfile, FORMAT_PEM3,
824 NULL((void*)0), "responder certificate");
825 if (!rsigner) {
826 BIO_printf(bio_err,
827 "Error loading responder certificate\n");
828 goto end;
829 }
830 rca_cert = load_cert(bio_err, ocsp_config.rca_filename,
831 FORMAT_PEM3, NULL((void*)0), "CA certificate");
832 if (ocsp_config.rcertfile) {
833 rother = load_certs(bio_err, ocsp_config.rcertfile,
834 FORMAT_PEM3, NULL((void*)0), "responder other certificates");
835 if (!rother)
836 goto end;
837 }
838 rkey = load_key(bio_err, ocsp_config.rkeyfile, FORMAT_PEM3, 0,
839 NULL((void*)0), "responder private key");
840 if (!rkey)
841 goto end;
842 }
843 if (acbio)
844 BIO_printf(bio_err, "Waiting for OCSP client connections...\n");
845
846 redo_accept:
847
848 if (acbio) {
849 if (!do_responder(&ocsp_config.req, &cbio, acbio,
850 ocsp_config.port))
851 goto end;
852 if (!ocsp_config.req) {
853 resp = OCSP_response_create(
854 OCSP_RESPONSE_STATUS_MALFORMEDREQUEST1, NULL((void*)0));
855 send_ocsp_response(cbio, resp);
856 goto done_resp;
857 }
858 }
859 if (!ocsp_config.req &&
860 (ocsp_config.signfile || ocsp_config.reqout || ocsp_config.host ||
861 ocsp_config.add_nonce || ocsp_config.ridx_filename)) {
862 BIO_printf(bio_err,
863 "Need an OCSP request for this operation!\n");
864 goto end;
865 }
866 if (ocsp_config.req && ocsp_config.add_nonce)
867 OCSP_request_add1_nonce(ocsp_config.req, NULL((void*)0), -1);
868
869 if (ocsp_config.signfile) {
870 if (!ocsp_config.keyfile)
871 ocsp_config.keyfile = ocsp_config.signfile;
872 signer = load_cert(bio_err, ocsp_config.signfile, FORMAT_PEM3,
873 NULL((void*)0), "signer certificate");
874 if (!signer) {
875 BIO_printf(bio_err,
876 "Error loading signer certificate\n");
877 goto end;
878 }
879 if (ocsp_config.sign_certfile) {
880 sign_other = load_certs(bio_err,
881 ocsp_config.sign_certfile, FORMAT_PEM3, NULL((void*)0),
882 "signer certificates");
883 if (!sign_other)
884 goto end;
885 }
886 key = load_key(bio_err, ocsp_config.keyfile, FORMAT_PEM3, 0,
887 NULL((void*)0), "signer private key");
888 if (!key)
889 goto end;
890
891 if (!OCSP_request_sign(ocsp_config.req, signer, key, NULL((void*)0),
892 sign_other, ocsp_config.sign_flags)) {
893 BIO_printf(bio_err, "Error signing OCSP request\n");
894 goto end;
895 }
896 }
897 if (ocsp_config.req_text && ocsp_config.req)
898 OCSP_REQUEST_print(out, ocsp_config.req, 0);
899
900 if (ocsp_config.reqout) {
901 derbio = BIO_new_file(ocsp_config.reqout, "wb");
902 if (!derbio) {
903 BIO_printf(bio_err, "Error opening file %s\n",
904 ocsp_config.reqout);
905 goto end;
906 }
907 i2d_OCSP_REQUEST_bio(derbio, ocsp_config.req);
908 BIO_free(derbio);
909 }
910 if (ocsp_config.ridx_filename && (!rkey || !rsigner || !rca_cert)) {
911 BIO_printf(bio_err,
912 "Need a responder certificate, key and CA for this operation!\n");
913 goto end;
914 }
915 if (ocsp_config.ridx_filename && !rdb) {
916 rdb = load_index(ocsp_config.ridx_filename, NULL((void*)0));
917 if (!rdb)
918 goto end;
919 if (!index_index(rdb))
920 goto end;
921 }
922 if (rdb) {
923 i = make_ocsp_response(&resp, ocsp_config.req, rdb, rca_cert,
Value stored to 'i' is never read
924 rsigner, rkey, rother, ocsp_config.rflags,
925 ocsp_config.nmin, ocsp_config.ndays);
926 if (cbio)
927 send_ocsp_response(cbio, resp);
928 } else if (ocsp_config.host) {
929 resp = process_responder(bio_err, ocsp_config.req,
930 ocsp_config.host,
931 ocsp_config.path ? ocsp_config.path : "/",
932 ocsp_config.port, ocsp_config.use_ssl, ocsp_config.headers,
933 ocsp_config.req_timeout);
934 if (!resp)
935 goto end;
936 } else if (ocsp_config.respin) {
937 derbio = BIO_new_file(ocsp_config.respin, "rb");
938 if (!derbio) {
939 BIO_printf(bio_err,
940 "Error Opening OCSP response file\n");
941 goto end;
942 }
943 resp = d2i_OCSP_RESPONSE_bio(derbio, NULL((void*)0));
944 BIO_free(derbio);
945 if (!resp) {
946 BIO_printf(bio_err, "Error reading OCSP response\n");
947 goto end;
948 }
949 } else {
950 ret = 0;
951 goto end;
952 }
953
954 done_resp:
955
956 if (ocsp_config.respout) {
957 derbio = BIO_new_file(ocsp_config.respout, "wb");
958 if (!derbio) {
959 BIO_printf(bio_err, "Error opening file %s\n",
960 ocsp_config.respout);
961 goto end;
962 }
963 i2d_OCSP_RESPONSE_bio(derbio, resp);
964 BIO_free(derbio);
965 }
966 i = OCSP_response_status(resp);
967
968 if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL0) {
969 BIO_printf(bio_err, "Responder Error: %s (%d)\n",
970 OCSP_response_status_str(i), i);
971 if (ocsp_config.ignore_err)
972 goto redo_accept;
973 ret = 1;
974 goto end;
975 }
976 if (ocsp_config.resp_text)
977 OCSP_RESPONSE_print(out, resp, 0);
978
979 /* If running as responder don't verify our own response */
980 if (cbio) {
981 if (ocsp_config.accept_count > 0)
982 ocsp_config.accept_count--;
983 /* Redo if more connections needed */
984 if (ocsp_config.accept_count) {
985 BIO_free_all(cbio);
986 cbio = NULL((void*)0);
987 OCSP_REQUEST_free(ocsp_config.req);
988 ocsp_config.req = NULL((void*)0);
989 OCSP_RESPONSE_free(resp);
990 resp = NULL((void*)0);
991 goto redo_accept;
992 }
993 goto end;
994 }
995 if (!store)
996 store = setup_verify(bio_err, ocsp_config.CAfile,
997 ocsp_config.CApath);
998 if (!store)
999 goto end;
1000 if (ocsp_config.verify_certfile) {
1001 verify_other = load_certs(bio_err, ocsp_config.verify_certfile,
1002 FORMAT_PEM3, NULL((void*)0), "validator certificate");
1003 if (!verify_other)
1004 goto end;
1005 }
1006 bs = OCSP_response_get1_basic(resp);
1007
1008 if (!bs) {
1009 BIO_printf(bio_err, "Error parsing response\n");
1010 goto end;
1011 }
1012 if (!ocsp_config.noverify) {
1013 if (ocsp_config.req &&
1014 ((i = OCSP_check_nonce(ocsp_config.req, bs)) <= 0)) {
1015 if (i == -1) {
1016 BIO_printf(bio_err,
1017 "WARNING: no nonce in response\n");
1018 } else {
1019 BIO_printf(bio_err, "Nonce Verify error\n");
1020 goto end;
1021 }
1022 }
1023 i = OCSP_basic_verify(bs, verify_other, store,
1024 ocsp_config.verify_flags);
1025 if (i < 0)
1026 i = OCSP_basic_verify(bs, NULL((void*)0), store, 0);
1027
1028 if (i <= 0) {
1029 BIO_printf(bio_err, "Response Verify Failure\n");
1030 ERR_print_errors(bio_err);
1031 } else {
1032 BIO_printf(bio_err, "Response verify OK\n");
1033 }
1034 }
1035 if (!print_ocsp_summary(out, bs, ocsp_config.req, ocsp_config.reqnames,
1036 ocsp_config.ids, ocsp_config.nsec, ocsp_config.maxage))
1037 goto end;
1038
1039 ret = 0;
1040
1041 end:
1042 ERR_print_errors(bio_err);
1043 X509_free(signer);
1044 X509_STORE_free(store);
1045 EVP_PKEY_free(key);
1046 EVP_PKEY_free(rkey);
1047 X509_free(ocsp_config.issuer);
1048 X509_free(ocsp_config.cert);
1049 X509_free(rsigner);
1050 X509_free(rca_cert);
1051 free_index(rdb);
1052 BIO_free_all(cbio);
1053 BIO_free_all(acbio);
1054 BIO_free(out);
1055 OCSP_REQUEST_free(ocsp_config.req);
1056 OCSP_RESPONSE_free(resp);
1057 OCSP_BASICRESP_free(bs);
1058 sk_OPENSSL_STRING_free(ocsp_config.reqnames)sk_free(((_STACK*) (1 ? ocsp_config.reqnames : (struct stack_st_OPENSSL_STRING
*)0)))
;
1059 sk_OCSP_CERTID_free(ocsp_config.ids)sk_free(((_STACK*) (1 ? (ocsp_config.ids) : (struct stack_st_OCSP_CERTID
*)0)))
;
1060 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))))
;
1061 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))))
;
1062 sk_CONF_VALUE_pop_free(ocsp_config.headers, X509V3_conf_free)sk_pop_free(((_STACK*) (1 ? (ocsp_config.headers) : (struct stack_st_CONF_VALUE
*)0)), ((void (*)(void *)) ((1 ? (X509V3_conf_free) : (void (
*)(CONF_VALUE *))0))))
;
1063
1064 if (ocsp_config.use_ssl != -1) {
1065 free(ocsp_config.host);
1066 free(ocsp_config.port);
1067 free(ocsp_config.path);
1068 }
1069 return (ret);
1070}
1071
1072static int
1073add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, const EVP_MD *cert_id_md,
1074 X509 *issuer, STACK_OF(OCSP_CERTID)struct stack_st_OCSP_CERTID *ids)
1075{
1076 OCSP_CERTID *id;
1077
1078 if (!issuer) {
1079 BIO_printf(bio_err, "No issuer certificate specified\n");
1080 return 0;
1081 }
1082 if (!*req)
1083 *req = OCSP_REQUEST_new();
1084 if (!*req)
1085 goto err;
1086 id = OCSP_cert_to_id(cert_id_md, cert, issuer);
1087 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)))
)
1088 goto err;
1089 if (!OCSP_request_add0_id(*req, id))
1090 goto err;
1091 return 1;
1092
1093 err:
1094 BIO_printf(bio_err, "Error Creating OCSP request\n");
1095 return 0;
1096}
1097
1098static int
1099add_ocsp_serial(OCSP_REQUEST **req, char *serial, const EVP_MD *cert_id_md,
1100 X509 *issuer, STACK_OF(OCSP_CERTID)struct stack_st_OCSP_CERTID *ids)
1101{
1102 OCSP_CERTID *id;
1103 X509_NAME *iname;
1104 ASN1_BIT_STRING *ikey;
1105 ASN1_INTEGER *sno;
1106
1107 if (!issuer) {
1108 BIO_printf(bio_err, "No issuer certificate specified\n");
1109 return 0;
1110 }
1111 if (!*req)
1112 *req = OCSP_REQUEST_new();
1113 if (!*req)
1114 goto err;
1115 iname = X509_get_subject_name(issuer);
1116 ikey = X509_get0_pubkey_bitstr(issuer);
1117 sno = s2i_ASN1_INTEGER(NULL((void*)0), serial);
1118 if (!sno) {
1119 BIO_printf(bio_err, "Error converting serial number %s\n",
1120 serial);
1121 return 0;
1122 }
1123 id = OCSP_cert_id_new(cert_id_md, iname, ikey, sno);
1124 ASN1_INTEGER_free(sno);
1125 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)))
)
1126 goto err;
1127 if (!OCSP_request_add0_id(*req, id))
1128 goto err;
1129 return 1;
1130
1131 err:
1132 BIO_printf(bio_err, "Error Creating OCSP request\n");
1133 return 0;
1134}
1135
1136static int
1137print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
1138 STACK_OF(OPENSSL_STRING)struct stack_st_OPENSSL_STRING *names, STACK_OF(OCSP_CERTID)struct stack_st_OCSP_CERTID *ids, long nsec,
1139 long maxage)
1140{
1141 OCSP_CERTID *id;
1142 char *name;
1143 int i;
1144 int status, reason;
1145
1146 ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
1147
1148 if (!bs || !req || !sk_OPENSSL_STRING_num(names)sk_num(((_STACK*) (1 ? names : (struct stack_st_OPENSSL_STRING
*)0)))
||
1149 !sk_OCSP_CERTID_num(ids)sk_num(((_STACK*) (1 ? (ids) : (struct stack_st_OCSP_CERTID*)
0)))
)
1150 return 1;
1151
1152 for (i = 0; i < sk_OCSP_CERTID_num(ids)sk_num(((_STACK*) (1 ? (ids) : (struct stack_st_OCSP_CERTID*)
0)))
; i++) {
1153 id = sk_OCSP_CERTID_value(ids, i)((OCSP_CERTID *)sk_value(((_STACK*) (1 ? (ids) : (struct stack_st_OCSP_CERTID
*)0)), (i)))
;
1154 name = sk_OPENSSL_STRING_value(names, i)((OPENSSL_STRING)sk_value(((_STACK*) (1 ? names : (struct stack_st_OPENSSL_STRING
*)0)), i))
;
1155 BIO_printf(out, "%s: ", name);
1156
1157 if (!OCSP_resp_find_status(bs, id, &status, &reason,
1158 &rev, &thisupd, &nextupd)) {
1159 BIO_puts(out, "ERROR: No Status found.\n");
1160 continue;
1161 }
1162 /*
1163 * Check validity: if invalid write to output BIO so we know
1164 * which response this refers to.
1165 */
1166 if (!OCSP_check_validity(thisupd, nextupd, nsec, maxage)) {
1167 BIO_puts(out, "WARNING: Status times invalid.\n");
1168 ERR_print_errors(out);
1169 }
1170 BIO_printf(out, "%s\n", OCSP_cert_status_str(status));
1171
1172 BIO_puts(out, "\tThis Update: ");
1173 ASN1_GENERALIZEDTIME_print(out, thisupd);
1174 BIO_puts(out, "\n");
1175
1176 if (nextupd) {
1177 BIO_puts(out, "\tNext Update: ");
1178 ASN1_GENERALIZEDTIME_print(out, nextupd);
1179 BIO_puts(out, "\n");
1180 }
1181 if (status != V_OCSP_CERTSTATUS_REVOKED1)
1182 continue;
1183
1184 if (reason != -1)
1185 BIO_printf(out, "\tReason: %s\n",
1186 OCSP_crl_reason_str(reason));
1187
1188 BIO_puts(out, "\tRevocation Time: ");
1189 ASN1_GENERALIZEDTIME_print(out, rev);
1190 BIO_puts(out, "\n");
1191 }
1192
1193 return 1;
1194}
1195
1196
1197static int
1198make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req, CA_DB *db,
1199 X509 *ca, X509 *rcert, EVP_PKEY *rkey, STACK_OF(X509)struct stack_st_X509 *rother,
1200 unsigned long flags, int nmin, int ndays)
1201{
1202 ASN1_TIME *thisupd = NULL((void*)0), *nextupd = NULL((void*)0);
1203 OCSP_CERTID *cid, *ca_id = NULL((void*)0);
1204 OCSP_BASICRESP *bs = NULL((void*)0);
1205 int i, id_count, ret = 1;
1206
1207 id_count = OCSP_request_onereq_count(req);
1208
1209 if (id_count <= 0) {
1210 *resp = OCSP_response_create(
1211 OCSP_RESPONSE_STATUS_MALFORMEDREQUEST1, NULL((void*)0));
1212 goto end;
1213 }
1214 bs = OCSP_BASICRESP_new();
1215 thisupd = X509_gmtime_adj(NULL((void*)0), 0);
1216 if (ndays != -1)
1217 nextupd = X509_gmtime_adj(NULL((void*)0), nmin * 60 + ndays * 3600 * 24);
1218
1219 /* Examine each certificate id in the request */
1220 for (i = 0; i < id_count; i++) {
1221 OCSP_ONEREQ *one;
1222 ASN1_INTEGER *serial;
1223 char **inf;
1224 ASN1_OBJECT *cert_id_md_oid;
1225 const EVP_MD *cert_id_md;
1226 one = OCSP_request_onereq_get0(req, i);
1227 cid = OCSP_onereq_get0_id(one);
1228
1229 OCSP_id_get0_info(NULL((void*)0), &cert_id_md_oid, NULL((void*)0), NULL((void*)0), cid);
1230
1231 cert_id_md = EVP_get_digestbyobj(cert_id_md_oid)EVP_get_digestbyname(OBJ_nid2sn(OBJ_obj2nid(cert_id_md_oid)));
1232 if (!cert_id_md) {
1233 *resp = OCSP_response_create(
1234 OCSP_RESPONSE_STATUS_INTERNALERROR2, NULL((void*)0));
1235 goto end;
1236 }
1237 OCSP_CERTID_free(ca_id);
1238 ca_id = OCSP_cert_to_id(cert_id_md, NULL((void*)0), ca);
1239
1240 /* Is this request about our CA? */
1241 if (OCSP_id_issuer_cmp(ca_id, cid)) {
1242 OCSP_basic_add1_status(bs, cid,
1243 V_OCSP_CERTSTATUS_UNKNOWN2, 0, NULL((void*)0),
1244 thisupd, nextupd);
1245 continue;
1246 }
1247 OCSP_id_get0_info(NULL((void*)0), NULL((void*)0), NULL((void*)0), &serial, cid);
1248 inf = lookup_serial(db, serial);
1249 if (!inf) {
1250 OCSP_basic_add1_status(bs, cid,
1251 V_OCSP_CERTSTATUS_UNKNOWN2, 0, NULL((void*)0),
1252 thisupd, nextupd);
1253 } else if (inf[DB_type0][0] == DB_TYPE_VAL'V') {
1254 OCSP_basic_add1_status(bs, cid,
1255 V_OCSP_CERTSTATUS_GOOD0, 0, NULL((void*)0),
1256 thisupd, nextupd);
1257 } else if (inf[DB_type0][0] == DB_TYPE_REV'R') {
1258 ASN1_OBJECT *inst = NULL((void*)0);
1259 ASN1_TIME *revtm = NULL((void*)0);
1260 ASN1_GENERALIZEDTIME *invtm = NULL((void*)0);
1261 OCSP_SINGLERESP *single;
1262 int reason = -1;
1263
1264 unpack_revinfo(&revtm, &reason, &inst, &invtm,
1265 inf[DB_rev_date2]);
1266 single = OCSP_basic_add1_status(bs, cid,
1267 V_OCSP_CERTSTATUS_REVOKED1,
1268 reason, revtm,
1269 thisupd, nextupd);
1270 if (invtm)
1271 OCSP_SINGLERESP_add1_ext_i2d(single,
1272 NID_invalidity_date142, invtm, 0, 0);
1273 else if (inst)
1274 OCSP_SINGLERESP_add1_ext_i2d(single,
1275 NID_hold_instruction_code430, inst, 0, 0);
1276 ASN1_OBJECT_free(inst);
1277 ASN1_TIME_free(revtm);
1278 ASN1_GENERALIZEDTIME_free(invtm);
1279 }
1280 }
1281
1282 OCSP_copy_nonce(bs, req);
1283
1284 OCSP_basic_sign(bs, rcert, rkey, NULL((void*)0), rother, flags);
1285
1286 *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_SUCCESSFUL0, bs);
1287
1288 end:
1289 ASN1_TIME_free(thisupd);
1290 ASN1_TIME_free(nextupd);
1291 OCSP_CERTID_free(ca_id);
1292 OCSP_BASICRESP_free(bs);
1293 return ret;
1294}
1295
1296static char **
1297lookup_serial(CA_DB *db, ASN1_INTEGER *ser)
1298{
1299 int i;
1300 BIGNUM *bn = NULL((void*)0);
1301 char *itmp, *row[DB_NUMBER6], **rrow;
1302
1303 for (i = 0; i < DB_NUMBER6; i++)
1304 row[i] = NULL((void*)0);
1305 bn = ASN1_INTEGER_to_BN(ser, NULL((void*)0));
1306 OPENSSL_assert(bn)(void)((bn) ? 0 : (OpenSSLDie("/usr/src/usr.bin/openssl/ocsp.c"
, 1306, "bn"),1))
; /* FIXME: should report an error at this
1307 * point and abort */
1308 if (BN_is_zero(bn)((bn)->top == 0))
1309 itmp = strdup("00");
1310 else
1311 itmp = BN_bn2hex(bn);
1312 row[DB_serial3] = itmp;
1313 BN_free(bn);
1314 rrow = TXT_DB_get_by_index(db->db, DB_serial3, row);
1315 free(itmp);
1316 return rrow;
1317}
1318
1319/* Quick and dirty OCSP server: read in and parse input request */
1320
1321static BIO *
1322init_responder(char *port)
1323{
1324 BIO *acbio = NULL((void*)0), *bufbio = NULL((void*)0);
1325
1326 bufbio = BIO_new(BIO_f_buffer());
1327 if (!bufbio)
1328 goto err;
1329 acbio = BIO_new_accept(port);
1330 if (!acbio)
1331 goto err;
1332 BIO_set_bind_mode(acbio, BIO_BIND_REUSEADDR)BIO_ctrl(acbio,131,2,((void*)0));
1333 BIO_set_accept_bios(acbio, bufbio)BIO_ctrl(acbio,118,2,(char *)bufbio);
1334 bufbio = NULL((void*)0);
1335
1336 if (BIO_do_accept(acbio)BIO_ctrl(acbio,101,0,((void*)0)) <= 0) {
1337 BIO_printf(bio_err, "Error setting up accept BIO\n");
1338 ERR_print_errors(bio_err);
1339 goto err;
1340 }
1341 return acbio;
1342
1343 err:
1344 BIO_free_all(acbio);
1345 BIO_free(bufbio);
1346 return NULL((void*)0);
1347}
1348
1349static int
1350do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, char *port)
1351{
1352 int have_post = 0, len;
1353 OCSP_REQUEST *req = NULL((void*)0);
1354 char inbuf[1024];
1355 BIO *cbio = NULL((void*)0);
1356
1357 if (BIO_do_accept(acbio)BIO_ctrl(acbio,101,0,((void*)0)) <= 0) {
1358 BIO_printf(bio_err, "Error accepting connection\n");
1359 ERR_print_errors(bio_err);
1360 return 0;
1361 }
1362 cbio = BIO_pop(acbio);
1363 *pcbio = cbio;
1364
1365 for (;;) {
1366 len = BIO_gets(cbio, inbuf, sizeof inbuf);
1367 if (len <= 0)
1368 return 1;
1369 /* Look for "POST" signalling start of query */
1370 if (!have_post) {
1371 if (strncmp(inbuf, "POST", 4)) {
1372 BIO_printf(bio_err, "Invalid request\n");
1373 return 1;
1374 }
1375 have_post = 1;
1376 }
1377 /* Look for end of headers */
1378 if ((inbuf[0] == '\r') || (inbuf[0] == '\n'))
1379 break;
1380 }
1381
1382 /* Try to read OCSP request */
1383
1384 req = d2i_OCSP_REQUEST_bio(cbio, NULL((void*)0));
1385
1386 if (!req) {
1387 BIO_printf(bio_err, "Error parsing OCSP request\n");
1388 ERR_print_errors(bio_err);
1389 }
1390 *preq = req;
1391
1392 return 1;
1393}
1394
1395static int
1396send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp)
1397{
1398 static const char http_resp[] =
1399 "HTTP/1.0 200 OK\r\nContent-type: application/ocsp-response\r\n"
1400 "Content-Length: %d\r\n\r\n";
1401
1402 if (!cbio)
1403 return 0;
1404 BIO_printf(cbio, http_resp, i2d_OCSP_RESPONSE(resp, NULL((void*)0)));
1405 i2d_OCSP_RESPONSE_bio(cbio, resp);
1406 (void) BIO_flush(cbio)(int)BIO_ctrl(cbio,11,0,((void*)0));
1407 return 1;
1408}
1409
1410static OCSP_RESPONSE *
1411query_responder(BIO *err, BIO *cbio, char *path, STACK_OF(CONF_VALUE)struct stack_st_CONF_VALUE *headers,
1412 const char *host, OCSP_REQUEST *req, int req_timeout)
1413{
1414 int fd;
1415 int rv;
1416 int i;
1417 int have_host = 0;
1418 OCSP_REQ_CTX *ctx = NULL((void*)0);
1419 OCSP_RESPONSE *rsp = NULL((void*)0);
1420 struct pollfd pfd[1];
1421
1422 if (req_timeout != -1)
1423 BIO_set_nbio(cbio, 1)BIO_ctrl(cbio,102,(1),((void*)0));
1424
1425 rv = BIO_do_connect(cbio)BIO_ctrl(cbio,101,0,((void*)0));
1426
1427 if ((rv <= 0) && ((req_timeout == -1) || !BIO_should_retry(cbio)BIO_test_flags(cbio, 0x08))) {
1428 BIO_puts(err, "Error connecting BIO\n");
1429 return NULL((void*)0);
1430 }
1431 if (BIO_get_fd(cbio, &fd)BIO_ctrl(cbio,105,0,(char *)&fd) < 0) {
1432 BIO_puts(err, "Can't get connection fd\n");
1433 goto err;
1434 }
1435 if (req_timeout != -1 && rv <= 0) {
1436 pfd[0].fd = fd;
1437 pfd[0].events = POLLOUT0x0004;
1438 rv = poll(pfd, 1, req_timeout * 1000);
1439 if (rv == 0) {
1440 BIO_puts(err, "Timeout on connect\n");
1441 return NULL((void*)0);
1442 }
1443 if (rv == -1) {
1444 BIO_puts(err, "Poll error\n");
1445 return NULL((void*)0);
1446 }
1447 }
1448 ctx = OCSP_sendreq_new(cbio, path, NULL((void*)0), -1);
1449 if (!ctx)
1450 return NULL((void*)0);
1451
1452 for (i = 0; i < sk_CONF_VALUE_num(headers)sk_num(((_STACK*) (1 ? (headers) : (struct stack_st_CONF_VALUE
*)0)))
; i++) {
1453 CONF_VALUE *hdr = sk_CONF_VALUE_value(headers, i)((CONF_VALUE *)sk_value(((_STACK*) (1 ? (headers) : (struct stack_st_CONF_VALUE
*)0)), (i)))
;
1454 if (strcasecmp("host", hdr->name) == 0)
1455 have_host = 1;
1456 if (!OCSP_REQ_CTX_add1_header(ctx, hdr->name, hdr->value))
1457 goto err;
1458 }
1459
1460 if (!have_host) {
1461 if (!OCSP_REQ_CTX_add1_header(ctx, "Host", host))
1462 goto err;
1463 }
1464
1465 if (!OCSP_REQ_CTX_set1_req(ctx, req))
1466 goto err;
1467
1468 for (;;) {
1469 rv = OCSP_sendreq_nbio(&rsp, ctx);
1470 if (rv != -1)
1471 break;
1472 if (req_timeout == -1)
1473 continue;
1474 pfd[0].fd = fd;
1475 if (BIO_should_read(cbio)BIO_test_flags(cbio, 0x01)) {
1476 pfd[0].events = POLLIN0x0001;
1477 } else if (BIO_should_write(cbio)BIO_test_flags(cbio, 0x02)) {
1478 pfd[0].events = POLLOUT0x0004;
1479 } else {
1480 BIO_puts(err, "Unexpected retry condition\n");
1481 goto err;
1482 }
1483 rv = poll(pfd, 1, req_timeout * 1000);
1484 if (rv == 0) {
1485 BIO_puts(err, "Timeout on request\n");
1486 break;
1487 }
1488 if (rv == -1 || (pfd[0].revents & (POLLERR0x0008|POLLNVAL0x0020))) {
1489 BIO_puts(err, "Poll error\n");
1490 break;
1491 }
1492 }
1493
1494 err:
1495 OCSP_REQ_CTX_free(ctx);
1496 return rsp;
1497}
1498
1499OCSP_RESPONSE *
1500process_responder(BIO *err, OCSP_REQUEST *req, char *host, char *path,
1501 char *port, int use_ssl, STACK_OF(CONF_VALUE)struct stack_st_CONF_VALUE *headers, int req_timeout)
1502{
1503 BIO *cbio = NULL((void*)0);
1504 SSL_CTX *ctx = NULL((void*)0);
1505 OCSP_RESPONSE *resp = NULL((void*)0);
1506
1507 cbio = BIO_new_connect(host);
1508 if (!cbio) {
1509 BIO_printf(err, "Error creating connect BIO\n");
1510 goto end;
1511 }
1512 if (port)
1513 BIO_set_conn_port(cbio, port)BIO_ctrl(cbio,100,1,(char *)port);
1514 if (use_ssl == 1) {
1515 BIO *sbio;
1516 ctx = SSL_CTX_new(TLS_client_method());
1517 if (ctx == NULL((void*)0)) {
1518 BIO_printf(err, "Error creating SSL context.\n");
1519 goto end;
1520 }
1521 SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY)SSL_CTX_ctrl((ctx),33,(0x00000004L),((void*)0));
1522 sbio = BIO_new_ssl(ctx, 1);
1523 cbio = BIO_push(sbio, cbio);
1524 }
1525 resp = query_responder(err, cbio, path, headers, host, req, req_timeout);
1526 if (!resp)
1527 BIO_printf(bio_err, "Error querying OCSP responder\n");
1528
1529 end:
1530 BIO_free_all(cbio);
1531 SSL_CTX_free(ctx);
1532 return resp;
1533}
1534#endif