sync with OpenBSD -current
This commit is contained in:
parent
be76e7e421
commit
f093fb79c9
45 changed files with 620 additions and 360 deletions
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: mft.c,v 1.106 2024/02/05 19:23:58 job Exp $ */
|
||||
/* $OpenBSD: mft.c,v 1.108 2024/02/15 07:01:33 tb Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
|
||||
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
|
@ -49,6 +49,9 @@ extern ASN1_OBJECT *mft_oid;
|
|||
* Types and templates for the Manifest eContent, RFC 6486, section 4.2.
|
||||
*/
|
||||
|
||||
ASN1_ITEM_EXP FileAndHash_it;
|
||||
ASN1_ITEM_EXP Manifest_it;
|
||||
|
||||
typedef struct {
|
||||
ASN1_IA5STRING *file;
|
||||
ASN1_BIT_STRING *hash;
|
||||
|
@ -57,8 +60,13 @@ typedef struct {
|
|||
DECLARE_STACK_OF(FileAndHash);
|
||||
|
||||
#ifndef DEFINE_STACK_OF
|
||||
#define sk_FileAndHash_dup(sk) SKM_sk_dup(FileAndHash, (sk))
|
||||
#define sk_FileAndHash_free(sk) SKM_sk_free(FileAndHash, (sk))
|
||||
#define sk_FileAndHash_num(sk) SKM_sk_num(FileAndHash, (sk))
|
||||
#define sk_FileAndHash_value(sk, i) SKM_sk_value(FileAndHash, (sk), (i))
|
||||
#define sk_FileAndHash_sort(sk) SKM_sk_sort(FileAndHash, (sk))
|
||||
#define sk_FileAndHash_set_cmp_func(sk, cmp) \
|
||||
SKM_sk_set_cmp_func(FileAndHash, (sk), (cmp))
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
|
@ -225,6 +233,76 @@ mft_parse_filehash(struct parse *p, const FileAndHash *fh)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
mft_fh_cmp_name(const FileAndHash *const *a, const FileAndHash *const *b)
|
||||
{
|
||||
if ((*a)->file->length < (*b)->file->length)
|
||||
return -1;
|
||||
if ((*a)->file->length > (*b)->file->length)
|
||||
return 1;
|
||||
|
||||
return memcmp((*a)->file->data, (*b)->file->data, (*b)->file->length);
|
||||
}
|
||||
|
||||
static int
|
||||
mft_fh_cmp_hash(const FileAndHash *const *a, const FileAndHash *const *b)
|
||||
{
|
||||
assert((*a)->hash->length == SHA256_DIGEST_LENGTH);
|
||||
assert((*b)->hash->length == SHA256_DIGEST_LENGTH);
|
||||
|
||||
return memcmp((*a)->hash->data, (*b)->hash->data, (*b)->hash->length);
|
||||
}
|
||||
|
||||
/*
|
||||
* Assuming that the hash lengths are validated, this checks that all file names
|
||||
* and hashes in a manifest are unique. Returns 1 on success, 0 on failure.
|
||||
*/
|
||||
static int
|
||||
mft_has_unique_names_and_hashes(const char *fn, const Manifest *mft)
|
||||
{
|
||||
STACK_OF(FileAndHash) *fhs;
|
||||
int i, ret = 0;
|
||||
|
||||
if ((fhs = sk_FileAndHash_dup(mft->fileList)) == NULL)
|
||||
err(1, NULL);
|
||||
|
||||
(void)sk_FileAndHash_set_cmp_func(fhs, mft_fh_cmp_name);
|
||||
sk_FileAndHash_sort(fhs);
|
||||
|
||||
for (i = 0; i < sk_FileAndHash_num(fhs) - 1; i++) {
|
||||
const FileAndHash *curr = sk_FileAndHash_value(fhs, i);
|
||||
const FileAndHash *next = sk_FileAndHash_value(fhs, i + 1);
|
||||
|
||||
if (mft_fh_cmp_name(&curr, &next) == 0) {
|
||||
warnx("%s: duplicate name: %.*s", fn,
|
||||
curr->file->length, curr->file->data);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
(void)sk_FileAndHash_set_cmp_func(fhs, mft_fh_cmp_hash);
|
||||
sk_FileAndHash_sort(fhs);
|
||||
|
||||
for (i = 0; i < sk_FileAndHash_num(fhs) - 1; i++) {
|
||||
const FileAndHash *curr = sk_FileAndHash_value(fhs, i);
|
||||
const FileAndHash *next = sk_FileAndHash_value(fhs, i + 1);
|
||||
|
||||
if (mft_fh_cmp_hash(&curr, &next) == 0) {
|
||||
warnx("%s: duplicate hash for %.*s and %.*s", fn,
|
||||
curr->file->length, curr->file->data,
|
||||
next->file->length, next->file->data);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
sk_FileAndHash_free(fhs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle the eContent of the manifest object, RFC 6486 sec. 4.2.
|
||||
* Returns 0 on failure and 1 on success.
|
||||
|
@ -313,6 +391,9 @@ mft_parse_econtent(const unsigned char *d, size_t dsz, struct parse *p)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (!mft_has_unique_names_and_hashes(p->fn, mft))
|
||||
goto out;
|
||||
|
||||
rc = 1;
|
||||
out:
|
||||
Manifest_free(mft);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue