summaryrefslogtreecommitdiff
path: root/src/usr.sbin/ocspcheck/ocspcheck.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr.sbin/ocspcheck/ocspcheck.c')
-rw-r--r--src/usr.sbin/ocspcheck/ocspcheck.c138
1 files changed, 92 insertions, 46 deletions
diff --git a/src/usr.sbin/ocspcheck/ocspcheck.c b/src/usr.sbin/ocspcheck/ocspcheck.c
index df14265370..6038f8817d 100644
--- a/src/usr.sbin/ocspcheck/ocspcheck.c
+++ b/src/usr.sbin/ocspcheck/ocspcheck.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ocspcheck.c,v 1.21 2017/05/08 20:15:34 beck Exp $ */ 1/* $OpenBSD: ocspcheck.c,v 1.22 2017/11/28 23:32:00 beck Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2017 Bob Beck <beck@openbsd.org> 4 * Copyright (c) 2017 Bob Beck <beck@openbsd.org>
@@ -40,6 +40,7 @@
40 40
41#define MAXAGE_SEC (14*24*60*60) 41#define MAXAGE_SEC (14*24*60*60)
42#define JITTER_SEC (60) 42#define JITTER_SEC (60)
43#define OCSP_MAX_RESPONSE_SIZE (20480)
43 44
44typedef struct ocsp_request { 45typedef struct ocsp_request {
45 STACK_OF(X509) *fullchain; 46 STACK_OF(X509) *fullchain;
@@ -505,19 +506,19 @@ int
505main(int argc, char **argv) 506main(int argc, char **argv)
506{ 507{
507 char *host = NULL, *path = "/", *certfile = NULL, *outfile = NULL, 508 char *host = NULL, *path = "/", *certfile = NULL, *outfile = NULL,
508 *cafile = NULL; 509 *cafile = NULL, *instaple = NULL, *infile = NULL;
509 struct addr addrs[MAX_SERVERS_DNS] = {{0}}; 510 struct addr addrs[MAX_SERVERS_DNS] = {{0}};
510 struct source sources[MAX_SERVERS_DNS]; 511 struct source sources[MAX_SERVERS_DNS];
511 int i, ch, staplefd = -1, nonce = 1; 512 int i, ch, staplefd = -1, infd = -1, nonce = 1;
512 ocsp_request *request = NULL; 513 ocsp_request *request = NULL;
513 size_t rescount, httphsz; 514 size_t rescount, httphsz = 0, instaplesz = 0;
514 struct httphead *httph; 515 struct httphead *httph = NULL;
515 struct httpget *hget; 516 struct httpget *hget;
516 X509_STORE *castore; 517 X509_STORE *castore;
517 ssize_t written, w; 518 ssize_t written, w;
518 short port; 519 short port;
519 520
520 while ((ch = getopt(argc, argv, "C:No:v")) != -1) { 521 while ((ch = getopt(argc, argv, "C:i:No:v")) != -1) {
521 switch (ch) { 522 switch (ch) {
522 case 'C': 523 case 'C':
523 cafile = optarg; 524 cafile = optarg;
@@ -528,6 +529,9 @@ main(int argc, char **argv)
528 case 'o': 529 case 'o':
529 outfile = optarg; 530 outfile = optarg;
530 break; 531 break;
532 case 'i':
533 infile = optarg;
534 break;
531 case 'v': 535 case 'v':
532 verbose++; 536 verbose++;
533 break; 537 break;
@@ -551,6 +555,16 @@ main(int argc, char **argv)
551 err(1, "Unable to open output file %s", outfile); 555 err(1, "Unable to open output file %s", outfile);
552 } 556 }
553 557
558 if (infile != NULL) {
559 if (strcmp(infile, "-") == 0)
560 infd = STDIN_FILENO;
561 else
562 infd = open(infile, O_RDONLY);
563 if (infd < 0)
564 err(1, "Unable to open input file %s", infile);
565 nonce = 0; /* Can't validate a nonce on a saved reply */
566 }
567
554 if (pledge("stdio inet rpath dns", NULL) == -1) 568 if (pledge("stdio inet rpath dns", NULL) == -1)
555 err(1, "pledge"); 569 err(1, "pledge");
556 570
@@ -571,50 +585,82 @@ main(int argc, char **argv)
571 certfile); 585 certfile);
572 if (*path == '\0') 586 if (*path == '\0')
573 path = "/"; 587 path = "/";
574 vspew("Using %s to host %s, port %d, path %s\n",
575 port == 443 ? "https" : "http", host, port, path);
576 588
577 rescount = host_dns(host, addrs); 589 if (infd == -1) {
578 for (i = 0; i < rescount; i++) { 590 /* Get a new OCSP response from the indicated server */
579 sources[i].ip = addrs[i].ip;
580 sources[i].family = addrs[i].family;
581 }
582 591
583 /* 592 vspew("Using %s to host %s, port %d, path %s\n",
584 * Do an HTTP post to send our request to the OCSP 593 port == 443 ? "https" : "http", host, port, path);
585 * server, and hopefully get an answer back
586 */
587 hget = http_get(sources, rescount, host, port, path,
588 request->data, request->size);
589 if (hget == NULL)
590 errx(1, "http_get");
591 594
592 /* 595 rescount = host_dns(host, addrs);
593 * Pledge minimally before fiddling with libcrypto init 596 for (i = 0; i < rescount; i++) {
594 * routines and parsing untrusted input from someone's OCSP 597 sources[i].ip = addrs[i].ip;
595 * server. 598 sources[i].family = addrs[i].family;
596 */ 599 }
597 if (pledge("stdio", NULL) == -1)
598 err(1, "pledge");
599
600 httph = http_head_parse(hget->http, hget->xfer, &httphsz);
601 dspew("Server at %s returns:\n", host);
602 for (i = 0; i < httphsz; i++)
603 dspew(" [%s]=[%s]\n", httph[i].key, httph[i].val);
604 dspew(" [Body]=[%zu bytes]\n", hget->bodypartsz);
605 if (hget->bodypartsz <= 0)
606 errx(1, "No body in reply from %s", host);
607
608 if (hget->code != 200)
609 errx(1, "http reply code %d from %s", hget->code, host);
610 600
611 /* 601 /*
612 * Validate the OCSP response we got back 602 * Do an HTTP post to send our request to the OCSP
613 */ 603 * server, and hopefully get an answer back
614 OPENSSL_add_all_algorithms_noconf(); 604 */
615 if (!validate_response(hget->bodypart, hget->bodypartsz, 605 hget = http_get(sources, rescount, host, port, path,
616 request, castore, host, certfile)) 606 request->data, request->size);
617 exit(1); 607 if (hget == NULL)
608 errx(1, "http_get");
609 /*
610 * Pledge minimally before fiddling with libcrypto init
611 * routines and parsing untrusted input from someone's OCSP
612 * server.
613 */
614 if (pledge("stdio", NULL) == -1)
615 err(1, "pledge");
616
617 dspew("Server at %s returns:\n", host);
618 for (i = 0; i < httphsz; i++)
619 dspew(" [%s]=[%s]\n", httph[i].key, httph[i].val);
620 dspew(" [Body]=[%zu bytes]\n", hget->bodypartsz);
621 if (hget->bodypartsz <= 0)
622 errx(1, "No body in reply from %s", host);
623
624 if (hget->code != 200)
625 errx(1, "http reply code %d from %s", hget->code, host);
626
627 /*
628 * Validate the OCSP response we got back
629 */
630 OPENSSL_add_all_algorithms_noconf();
631 if (!validate_response(hget->bodypart, hget->bodypartsz,
632 request, castore, host, certfile))
633 exit(1);
634 } else {
635 size_t nr = 0;
636 instaplesz = 0;
637
638 /*
639 * Pledge minimally before fiddling with libcrypto init
640 */
641 if (pledge("stdio", NULL) == -1)
642 err(1, "pledge");
643
644 dspew("Using ocsp response saved in %s:\n", infile);
645
646 /* Use the existing OCSP response saved in infd */
647 instaple = calloc(OCSP_MAX_RESPONSE_SIZE, 1);
648 if (instaple) {
649 while ((nr = read(infd, instaple + instaplesz,
650 OCSP_MAX_RESPONSE_SIZE - instaplesz)) != -1 &&
651 nr != 0)
652 instaplesz += nr;
653 }
654 if (instaplesz == 0)
655 exit(1);
656 /*
657 * Validate the OCSP staple we read in.
658 */
659 OPENSSL_add_all_algorithms_noconf();
660 if (!validate_response(instaple, instaplesz,
661 request, castore, host, certfile))
662 exit(1);
663 }
618 664
619 /* 665 /*
620 * If we have been given a place to save a staple, 666 * If we have been given a place to save a staple,