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