summaryrefslogtreecommitdiffstats
path: root/usr.sbin/rpki-client
diff options
context:
space:
mode:
authorclaudio <claudio@openbsd.org>2020-03-30 12:12:51 +0000
committerclaudio <claudio@openbsd.org>2020-03-30 12:12:51 +0000
commitdf95ef8ff31df64c59d126b7c499391a7f8faf67 (patch)
tree42857e46cf10d3770629ba908203825a853c2f47 /usr.sbin/rpki-client
parentPort "mach dtb" code from arm64. (diff)
downloadwireguard-openbsd-df95ef8ff31df64c59d126b7c499391a7f8faf67.tar.xz
wireguard-openbsd-df95ef8ff31df64c59d126b7c499391a7f8faf67.zip
Delay failure in mft parsing until all elements of FileAndHash have been
checked. This way all corrupted or missing files should show up in a single run. This should help operators to get a better idea what and how much is broken. OK benno@
Diffstat (limited to 'usr.sbin/rpki-client')
-rw-r--r--usr.sbin/rpki-client/mft.c52
1 files changed, 30 insertions, 22 deletions
diff --git a/usr.sbin/rpki-client/mft.c b/usr.sbin/rpki-client/mft.c
index bfc5f3a0d32..354e7f4b2ae 100644
--- a/usr.sbin/rpki-client/mft.c
+++ b/usr.sbin/rpki-client/mft.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mft.c,v 1.11 2020/03/30 11:09:03 claudio Exp $ */
+/* $OpenBSD: mft.c,v 1.12 2020/03/30 12:12:51 claudio Exp $ */
/*
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -115,7 +115,7 @@ hex_pton(u_char const *src, size_t srclen, char *target, size_t targlen)
* Return zero on failure, non-zero on success.
*/
static int
-mft_parse_filehash(struct parse *p, const ASN1_OCTET_STRING *os)
+mft_parse_filehash(struct parse *p, const ASN1_OCTET_STRING *os, int just_check)
{
char file_hash[SHA256_DIGEST_STRING_LENGTH];
char cert_hash[SHA256_DIGEST_STRING_LENGTH];
@@ -124,19 +124,18 @@ mft_parse_filehash(struct parse *p, const ASN1_OCTET_STRING *os)
char *fn = NULL;
const unsigned char *d = os->data;
size_t dsz = os->length, sz;
- int rc = 0;
struct mftfile *fent;
char *cp, *path = NULL;
if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
cryptowarnx("%s: RFC 6486 section 4.2.1: FileAndHash: "
"failed ASN.1 sequence parse", p->fn);
- goto out;
+ goto fail;
} else if (sk_ASN1_TYPE_num(seq) != 2) {
warnx("%s: RFC 6486 section 4.2.1: FileAndHash: "
"want 2 elements, have %d", p->fn,
sk_ASN1_TYPE_num(seq));
- goto out;
+ goto fail;
}
/* First is the filename itself. */
@@ -146,7 +145,7 @@ mft_parse_filehash(struct parse *p, const ASN1_OCTET_STRING *os)
warnx("%s: RFC 6486 section 4.2.1: FileAndHash: "
"want ASN.1 IA5 string, have %s (NID %d)",
p->fn, ASN1_tag2str(file->type), file->type);
- goto out;
+ goto fail;
}
fn = strndup((const char *)file->value.ia5string->data,
file->value.ia5string->length);
@@ -163,20 +162,20 @@ mft_parse_filehash(struct parse *p, const ASN1_OCTET_STRING *os)
if (strchr(fn, '/') != NULL) {
warnx("%s: path components disallowed in filename: %s",
p->fn, fn);
- goto out;
+ goto fail;
} else if ((sz = strlen(fn)) <= 4) {
warnx("%s: filename must be large enough for suffix part: %s",
p->fn, fn);
- goto out;
+ goto fail;
}
if (strcasecmp(fn + sz - 4, ".roa") &&
strcasecmp(fn + sz - 4, ".crl") &&
strcasecmp(fn + sz - 4, ".cer")) {
+ /* ignore unknown files */
free(fn);
- fn = NULL;
- rc = 1;
- goto out;
+ sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
+ return 1;
}
/* Now hash value. */
@@ -185,14 +184,14 @@ mft_parse_filehash(struct parse *p, const ASN1_OCTET_STRING *os)
warnx("%s: RFC 6486 section 4.2.1: FileAndHash: "
"want ASN.1 bit string, have %s (NID %d)",
p->fn, ASN1_tag2str(hash->type), hash->type);
- goto out;
+ goto fail;
}
if (hash->value.bit_string->length != SHA256_DIGEST_LENGTH) {
warnx("%s: RFC 6486 section 4.2.1: hash: "
"invalid SHA256 length, have %d",
p->fn, hash->value.bit_string->length);
- goto out;
+ goto fail;
}
if (hex_pton(hash->value.bit_string->data, SHA256_DIGEST_LENGTH,
@@ -207,14 +206,19 @@ mft_parse_filehash(struct parse *p, const ASN1_OCTET_STRING *os)
if (SHA256File(path, file_hash) == NULL) {
warn("%s: referenced file %s", p->fn, fn);
- goto out;
+ goto fail;
}
+ free(path);
+ path = NULL;
if (strcmp(file_hash, cert_hash) != 0) {
warnx("%s: bad message digest for %s", p->fn, fn);
- goto out;
+ goto fail;
}
+ if (just_check)
+ goto fail;
+
/* Insert the filename and hash value. */
p->res->files = reallocarray(p->res->files, p->res->filesz + 1,
@@ -226,15 +230,16 @@ mft_parse_filehash(struct parse *p, const ASN1_OCTET_STRING *os)
memset(fent, 0, sizeof(struct mftfile));
fent->file = fn;
- fn = NULL;
memcpy(fent->hash, hash->value.bit_string->data, SHA256_DIGEST_LENGTH);
- rc = 1;
-out:
+ sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
+ return 1;
+
+fail:
free(path);
free(fn);
sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
- return rc;
+ return 0;
}
/*
@@ -248,7 +253,7 @@ mft_parse_flist(struct parse *p, const ASN1_OCTET_STRING *os)
const ASN1_TYPE *t;
const unsigned char *d = os->data;
size_t dsz = os->length;
- int i, rc = 0;
+ int i, rc = 0, failed = 0;
if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
cryptowarnx("%s: RFC 6486 section 4.2: fileList: "
@@ -263,9 +268,12 @@ mft_parse_flist(struct parse *p, const ASN1_OCTET_STRING *os)
"want ASN.1 sequence, have %s (NID %d)",
p->fn, ASN1_tag2str(t->type), t->type);
goto out;
- } else if (!mft_parse_filehash(p, t->value.octet_string))
- goto out;
+ } else if (!mft_parse_filehash(p, t->value.octet_string,
+ failed))
+ failed = 1;
}
+ if (failed)
+ goto out;
rc = 1;
out: