summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Beck <beck@cvs.openbsd.org>2017-11-28 23:32:01 +0000
committerBob Beck <beck@cvs.openbsd.org>2017-11-28 23:32:01 +0000
commit6322eed1014b2454587bd5d2fe8e51ebb1be832c (patch)
treeaee39f4e663ed1060aa528b5a47a351d8587b29b
parent1d3a52c99d52ce45a54223243ee2d65360baf947 (diff)
Add option -i to allow oscpcheck to be used to validate an on-disk staple
ok claudio@ benno@
-rw-r--r--usr.sbin/ocspcheck/ocspcheck.814
-rw-r--r--usr.sbin/ocspcheck/ocspcheck.c138
2 files changed, 103 insertions, 49 deletions
diff --git a/usr.sbin/ocspcheck/ocspcheck.8 b/usr.sbin/ocspcheck/ocspcheck.8
index dabac38a65b..2a3f2d61871 100644
--- a/usr.sbin/ocspcheck/ocspcheck.8
+++ b/usr.sbin/ocspcheck/ocspcheck.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: ocspcheck.8,v 1.7 2017/10/17 22:47:58 schwarze Exp $
+.\" $OpenBSD: ocspcheck.8,v 1.8 2017/11/28 23:32:00 beck Exp $
.\"
.\" Copyright (c) 2017 Bob Beck <beck@openbsd.org>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: October 17 2017 $
+.Dd $Mdocdate: November 28 2017 $
.Dt OCSPCHECK 8
.Os
.Sh NAME
@@ -45,10 +45,18 @@ By default no certificates are used beyond those in the
certificate chain provided by the
.Ar file
argument.
+.It Fl i Ar staplefile
+Specify an input filename from which a DER encoded OCSP response
+will be read instead of fetching it from the OCSP server.
+A filename
+of
+.Sq -
+will read the response from standard input.
.It Fl N
Do not use a nonce value in the OCSP request, or validate that the
nonce was returned in the OCSP response.
-By default a nonce is always used and validated.
+By default a nonce is always used and validated when retrieving
+a response from an OCSP server.
The use of this flag is a security risk as it will allow OCSP
responses to be replayed.
It should not be used unless the OCSP server does not support the
diff --git a/usr.sbin/ocspcheck/ocspcheck.c b/usr.sbin/ocspcheck/ocspcheck.c
index df142653702..6038f8817d1 100644
--- a/usr.sbin/ocspcheck/ocspcheck.c
+++ b/usr.sbin/ocspcheck/ocspcheck.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ocspcheck.c,v 1.21 2017/05/08 20:15:34 beck Exp $ */
+/* $OpenBSD: ocspcheck.c,v 1.22 2017/11/28 23:32:00 beck Exp $ */
/*
* Copyright (c) 2017 Bob Beck <beck@openbsd.org>
@@ -40,6 +40,7 @@
#define MAXAGE_SEC (14*24*60*60)
#define JITTER_SEC (60)
+#define OCSP_MAX_RESPONSE_SIZE (20480)
typedef struct ocsp_request {
STACK_OF(X509) *fullchain;
@@ -505,19 +506,19 @@ int
main(int argc, char **argv)
{
char *host = NULL, *path = "/", *certfile = NULL, *outfile = NULL,
- *cafile = NULL;
+ *cafile = NULL, *instaple = NULL, *infile = NULL;
struct addr addrs[MAX_SERVERS_DNS] = {{0}};
struct source sources[MAX_SERVERS_DNS];
- int i, ch, staplefd = -1, nonce = 1;
+ int i, ch, staplefd = -1, infd = -1, nonce = 1;
ocsp_request *request = NULL;
- size_t rescount, httphsz;
- struct httphead *httph;
+ size_t rescount, httphsz = 0, instaplesz = 0;
+ struct httphead *httph = NULL;
struct httpget *hget;
X509_STORE *castore;
ssize_t written, w;
short port;
- while ((ch = getopt(argc, argv, "C:No:v")) != -1) {
+ while ((ch = getopt(argc, argv, "C:i:No:v")) != -1) {
switch (ch) {
case 'C':
cafile = optarg;
@@ -528,6 +529,9 @@ main(int argc, char **argv)
case 'o':
outfile = optarg;
break;
+ case 'i':
+ infile = optarg;
+ break;
case 'v':
verbose++;
break;
@@ -551,6 +555,16 @@ main(int argc, char **argv)
err(1, "Unable to open output file %s", outfile);
}
+ if (infile != NULL) {
+ if (strcmp(infile, "-") == 0)
+ infd = STDIN_FILENO;
+ else
+ infd = open(infile, O_RDONLY);
+ if (infd < 0)
+ err(1, "Unable to open input file %s", infile);
+ nonce = 0; /* Can't validate a nonce on a saved reply */
+ }
+
if (pledge("stdio inet rpath dns", NULL) == -1)
err(1, "pledge");
@@ -571,50 +585,82 @@ main(int argc, char **argv)
certfile);
if (*path == '\0')
path = "/";
- vspew("Using %s to host %s, port %d, path %s\n",
- port == 443 ? "https" : "http", host, port, path);
- rescount = host_dns(host, addrs);
- for (i = 0; i < rescount; i++) {
- sources[i].ip = addrs[i].ip;
- sources[i].family = addrs[i].family;
- }
+ if (infd == -1) {
+ /* Get a new OCSP response from the indicated server */
- /*
- * Do an HTTP post to send our request to the OCSP
- * server, and hopefully get an answer back
- */
- hget = http_get(sources, rescount, host, port, path,
- request->data, request->size);
- if (hget == NULL)
- errx(1, "http_get");
+ vspew("Using %s to host %s, port %d, path %s\n",
+ port == 443 ? "https" : "http", host, port, path);
- /*
- * Pledge minimally before fiddling with libcrypto init
- * routines and parsing untrusted input from someone's OCSP
- * server.
- */
- if (pledge("stdio", NULL) == -1)
- err(1, "pledge");
-
- httph = http_head_parse(hget->http, hget->xfer, &httphsz);
- dspew("Server at %s returns:\n", host);
- for (i = 0; i < httphsz; i++)
- dspew(" [%s]=[%s]\n", httph[i].key, httph[i].val);
- dspew(" [Body]=[%zu bytes]\n", hget->bodypartsz);
- if (hget->bodypartsz <= 0)
- errx(1, "No body in reply from %s", host);
-
- if (hget->code != 200)
- errx(1, "http reply code %d from %s", hget->code, host);
+ rescount = host_dns(host, addrs);
+ for (i = 0; i < rescount; i++) {
+ sources[i].ip = addrs[i].ip;
+ sources[i].family = addrs[i].family;
+ }
- /*
- * Validate the OCSP response we got back
- */
- OPENSSL_add_all_algorithms_noconf();
- if (!validate_response(hget->bodypart, hget->bodypartsz,
- request, castore, host, certfile))
- exit(1);
+ /*
+ * Do an HTTP post to send our request to the OCSP
+ * server, and hopefully get an answer back
+ */
+ hget = http_get(sources, rescount, host, port, path,
+ request->data, request->size);
+ if (hget == NULL)
+ errx(1, "http_get");
+ /*
+ * Pledge minimally before fiddling with libcrypto init
+ * routines and parsing untrusted input from someone's OCSP
+ * server.
+ */
+ if (pledge("stdio", NULL) == -1)
+ err(1, "pledge");
+
+ dspew("Server at %s returns:\n", host);
+ for (i = 0; i < httphsz; i++)
+ dspew(" [%s]=[%s]\n", httph[i].key, httph[i].val);
+ dspew(" [Body]=[%zu bytes]\n", hget->bodypartsz);
+ if (hget->bodypartsz <= 0)
+ errx(1, "No body in reply from %s", host);
+
+ if (hget->code != 200)
+ errx(1, "http reply code %d from %s", hget->code, host);
+
+ /*
+ * Validate the OCSP response we got back
+ */
+ OPENSSL_add_all_algorithms_noconf();
+ if (!validate_response(hget->bodypart, hget->bodypartsz,
+ request, castore, host, certfile))
+ exit(1);
+ } else {
+ size_t nr = 0;
+ instaplesz = 0;
+
+ /*
+ * Pledge minimally before fiddling with libcrypto init
+ */
+ if (pledge("stdio", NULL) == -1)
+ err(1, "pledge");
+
+ dspew("Using ocsp response saved in %s:\n", infile);
+
+ /* Use the existing OCSP response saved in infd */
+ instaple = calloc(OCSP_MAX_RESPONSE_SIZE, 1);
+ if (instaple) {
+ while ((nr = read(infd, instaple + instaplesz,
+ OCSP_MAX_RESPONSE_SIZE - instaplesz)) != -1 &&
+ nr != 0)
+ instaplesz += nr;
+ }
+ if (instaplesz == 0)
+ exit(1);
+ /*
+ * Validate the OCSP staple we read in.
+ */
+ OPENSSL_add_all_algorithms_noconf();
+ if (!validate_response(instaple, instaplesz,
+ request, castore, host, certfile))
+ exit(1);
+ }
/*
* If we have been given a place to save a staple,