diff options
author | tb <> | 2020-01-23 03:53:39 +0000 |
---|---|---|
committer | tb <> | 2020-01-23 03:53:39 +0000 |
commit | 130f32cc7004f9434c10db4fc8a7e8b1db9082a5 (patch) | |
tree | 4d9d69b009f469def034872876e1caec106f28a1 | |
parent | 61fedc0310a1ba6f15f2242f24fbba7b3b8d3d8f (diff) | |
download | openbsd-130f32cc7004f9434c10db4fc8a7e8b1db9082a5.tar.gz openbsd-130f32cc7004f9434c10db4fc8a7e8b1db9082a5.tar.bz2 openbsd-130f32cc7004f9434c10db4fc8a7e8b1db9082a5.zip |
The X509_LOOKUP code tries to grope around in /etc/ssl/cert/ to find
CA certs it couldn't find otherwise. This may lead to a pledge rpath
violation reported by Kor, son of Rynar. Unfortunately, providing certs
inside a directory is common in linuxes, so we need to keep this
functionality for portable.
Check if /etc/ssl/cert.pem and /etc/ssl/cert exist and pledge
accordingly. Add unveils to restrict this program further on a
default OpenBSD install. Fix -C to look only inside the provided
root bundle.
Input from jsing and sthen, tests by sthen and Kor
ok beck, jsing, sthen (after much back and forth)
-rw-r--r-- | src/usr.sbin/ocspcheck/ocspcheck.c | 97 |
1 files changed, 67 insertions, 30 deletions
diff --git a/src/usr.sbin/ocspcheck/ocspcheck.c b/src/usr.sbin/ocspcheck/ocspcheck.c index 41700f91a0..ea06c128c4 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.25 2019/05/15 13:44:18 bcook Exp $ */ | 1 | /* $OpenBSD: ocspcheck.c,v 1.26 2020/01/23 03:53:39 tb Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2017 Bob Beck <beck@openbsd.org> | 4 | * Copyright (c) 2017 Bob Beck <beck@openbsd.org> |
@@ -184,35 +184,41 @@ parse_ocsp_time(ASN1_GENERALIZEDTIME *gt) | |||
184 | } | 184 | } |
185 | 185 | ||
186 | static X509_STORE * | 186 | static X509_STORE * |
187 | read_cacerts(char *file) | 187 | read_cacerts(const char *file, const char *dir) |
188 | { | 188 | { |
189 | X509_STORE *store; | 189 | X509_STORE *store = NULL; |
190 | X509_LOOKUP *lookup; | 190 | X509_LOOKUP *lookup; |
191 | 191 | ||
192 | if ((store = X509_STORE_new()) == NULL) { | 192 | if (file == NULL && dir == NULL) { |
193 | warnx("Malloc failed"); | 193 | warnx("No CA certs to load"); |
194 | goto end; | 194 | goto end; |
195 | } | 195 | } |
196 | if ((lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())) == | 196 | if ((store = X509_STORE_new()) == NULL) { |
197 | NULL) { | 197 | warnx("Malloc failed"); |
198 | warnx("Unable to load CA certs from file %s", file); | ||
199 | goto end; | 198 | goto end; |
200 | } | 199 | } |
201 | if (file) { | 200 | if (file != NULL) { |
201 | if ((lookup = X509_STORE_add_lookup(store, | ||
202 | X509_LOOKUP_file())) == NULL) { | ||
203 | warnx("Unable to load CA cert file"); | ||
204 | goto end; | ||
205 | } | ||
202 | if (!X509_LOOKUP_load_file(lookup, file, X509_FILETYPE_PEM)) { | 206 | if (!X509_LOOKUP_load_file(lookup, file, X509_FILETYPE_PEM)) { |
203 | warnx("Unable to load CA certs from file %s", file); | 207 | warnx("Unable to load CA certs from file %s", file); |
204 | goto end; | 208 | goto end; |
205 | } | 209 | } |
206 | } else | ||
207 | X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); | ||
208 | |||
209 | if ((lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir())) == | ||
210 | NULL) { | ||
211 | warnx("Unable to load CA certs from file %s", file); | ||
212 | goto end; | ||
213 | } | 210 | } |
214 | X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); | 211 | if (dir != NULL) { |
215 | ERR_clear_error(); | 212 | if ((lookup = X509_STORE_add_lookup(store, |
213 | X509_LOOKUP_hash_dir())) == NULL) { | ||
214 | warnx("Unable to load CA cert directory"); | ||
215 | goto end; | ||
216 | } | ||
217 | if (!X509_LOOKUP_add_dir(lookup, dir, X509_FILETYPE_PEM)) { | ||
218 | warnx("Unable to load CA certs from directory %s", dir); | ||
219 | goto end; | ||
220 | } | ||
221 | } | ||
216 | return store; | 222 | return store; |
217 | 223 | ||
218 | end: | 224 | end: |
@@ -289,7 +295,7 @@ issuer_from_chain(STACK_OF(X509) *fullchain) | |||
289 | } | 295 | } |
290 | 296 | ||
291 | static ocsp_request * | 297 | static ocsp_request * |
292 | ocsp_request_new_from_cert(char *file, int nonce) | 298 | ocsp_request_new_from_cert(const char *cadir, char *file, int nonce) |
293 | { | 299 | { |
294 | X509 *cert = NULL; | 300 | X509 *cert = NULL; |
295 | int count = 0; | 301 | int count = 0; |
@@ -308,10 +314,11 @@ ocsp_request_new_from_cert(char *file, int nonce) | |||
308 | return NULL; | 314 | return NULL; |
309 | 315 | ||
310 | request->fullchain = read_fullchain(file, &count); | 316 | request->fullchain = read_fullchain(file, &count); |
311 | /* Drop rpath from pledge, we don't need to read anymore */ | 317 | if (cadir == NULL) { |
312 | if (pledge("stdio inet dns", NULL) == -1) | 318 | /* Drop rpath from pledge, we don't need to read anymore */ |
313 | err(1, "pledge"); | 319 | if (pledge("stdio inet dns", NULL) == -1) |
314 | 320 | err(1, "pledge"); | |
321 | } | ||
315 | if (request->fullchain == NULL) | 322 | if (request->fullchain == NULL) |
316 | return NULL; | 323 | return NULL; |
317 | if (count <= 1) { | 324 | if (count <= 1) { |
@@ -506,8 +513,9 @@ usage(void) | |||
506 | int | 513 | int |
507 | main(int argc, char **argv) | 514 | main(int argc, char **argv) |
508 | { | 515 | { |
516 | const char *cafile = NULL, *cadir = NULL; | ||
509 | char *host = NULL, *path = "/", *certfile = NULL, *outfile = NULL, | 517 | char *host = NULL, *path = "/", *certfile = NULL, *outfile = NULL, |
510 | *cafile = NULL, *instaple = NULL, *infile = NULL; | 518 | *instaple = NULL, *infile = NULL; |
511 | struct addr addrs[MAX_SERVERS_DNS] = {{0}}; | 519 | struct addr addrs[MAX_SERVERS_DNS] = {{0}}; |
512 | struct source sources[MAX_SERVERS_DNS]; | 520 | struct source sources[MAX_SERVERS_DNS]; |
513 | int i, ch, staplefd = -1, infd = -1, nonce = 1; | 521 | int i, ch, staplefd = -1, infd = -1, nonce = 1; |
@@ -566,6 +574,24 @@ main(int argc, char **argv) | |||
566 | nonce = 0; /* Can't validate a nonce on a saved reply */ | 574 | nonce = 0; /* Can't validate a nonce on a saved reply */ |
567 | } | 575 | } |
568 | 576 | ||
577 | if (cafile == NULL) { | ||
578 | if (access(X509_get_default_cert_file(), R_OK) == 0) | ||
579 | cafile = X509_get_default_cert_file(); | ||
580 | if (access(X509_get_default_cert_dir(), F_OK) == 0) | ||
581 | cadir = X509_get_default_cert_dir(); | ||
582 | } | ||
583 | |||
584 | if (cafile != NULL) { | ||
585 | if (unveil(cafile, "r") == -1) | ||
586 | err(1, "unveil"); | ||
587 | } | ||
588 | if (cadir != NULL) { | ||
589 | if (unveil(cadir, "r") == -1) | ||
590 | err(1, "unveil"); | ||
591 | } | ||
592 | if (unveil(certfile, "r") == -1) | ||
593 | err(1, "unveil"); | ||
594 | |||
569 | if (pledge("stdio inet rpath dns", NULL) == -1) | 595 | if (pledge("stdio inet rpath dns", NULL) == -1) |
570 | err(1, "pledge"); | 596 | err(1, "pledge"); |
571 | 597 | ||
@@ -574,9 +600,10 @@ main(int argc, char **argv) | |||
574 | * OCSP request based on the full certificate chain | 600 | * OCSP request based on the full certificate chain |
575 | * we have been given to check. | 601 | * we have been given to check. |
576 | */ | 602 | */ |
577 | if ((castore = read_cacerts(cafile)) == NULL) | 603 | if ((castore = read_cacerts(cafile, cadir)) == NULL) |
578 | exit(1); | 604 | exit(1); |
579 | if ((request = ocsp_request_new_from_cert(certfile, nonce)) == NULL) | 605 | if ((request = ocsp_request_new_from_cert(cadir, certfile, nonce)) |
606 | == NULL) | ||
580 | exit(1); | 607 | exit(1); |
581 | 608 | ||
582 | dspew("Built an %zu byte ocsp request\n", request->size); | 609 | dspew("Built an %zu byte ocsp request\n", request->size); |
@@ -612,8 +639,13 @@ main(int argc, char **argv) | |||
612 | * routines and parsing untrusted input from someone's OCSP | 639 | * routines and parsing untrusted input from someone's OCSP |
613 | * server. | 640 | * server. |
614 | */ | 641 | */ |
615 | if (pledge("stdio", NULL) == -1) | 642 | if (cadir == NULL) { |
616 | err(1, "pledge"); | 643 | if (pledge("stdio", NULL) == -1) |
644 | err(1, "pledge"); | ||
645 | } else { | ||
646 | if (pledge("stdio rpath", NULL) == -1) | ||
647 | err(1, "pledge"); | ||
648 | } | ||
617 | 649 | ||
618 | dspew("Server at %s returns:\n", host); | 650 | dspew("Server at %s returns:\n", host); |
619 | for (i = 0; i < httphsz; i++) | 651 | for (i = 0; i < httphsz; i++) |
@@ -641,8 +673,13 @@ main(int argc, char **argv) | |||
641 | /* | 673 | /* |
642 | * Pledge minimally before fiddling with libcrypto init | 674 | * Pledge minimally before fiddling with libcrypto init |
643 | */ | 675 | */ |
644 | if (pledge("stdio", NULL) == -1) | 676 | if (cadir == NULL) { |
645 | err(1, "pledge"); | 677 | if (pledge("stdio", NULL) == -1) |
678 | err(1, "pledge"); | ||
679 | } else { | ||
680 | if (pledge("stdio rpath", NULL) == -1) | ||
681 | err(1, "pledge"); | ||
682 | } | ||
646 | 683 | ||
647 | dspew("Using ocsp response saved in %s:\n", infile); | 684 | dspew("Using ocsp response saved in %s:\n", infile); |
648 | 685 | ||