Right now a file can only exist in one place in the rpki-client cache.
This will change when we split valid data to its own repo.
One step to get closer to that is to alter valid_filehash() to take an
open filedescriptor instead of using open(2) itself. This allows the
callers to decide which file to pass. valid_filehash() handles fd == -1
and so the open call does not need to be checked for error.
Additionally move mft_check() from mft.c to parser.c. It simplifies later
work.
--
:wq Claudio
Index: extern.h
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
retrieving revision 1.101
diff -u -p -r1.101 extern.h
--- extern.h 11 Jan 2022 13:06:07 -0000 1.101
+++ extern.h 13 Jan 2022 12:56:56 -0000
@@ -445,7 +445,7 @@ int valid_cert(const char *, struct au
const struct cert *);
int valid_roa(const char *, struct auth_tree *, struct roa *);
int valid_filename(const char *);
-int valid_filehash(const char *, const char *, size_t);
+int valid_filehash(int, const char *, size_t);
int valid_uri(const char *, size_t, const char *);
int valid_origin(const char *, const char *);
Index: mft.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/mft.c,v
retrieving revision 1.44
diff -u -p -r1.44 mft.c
--- mft.c 11 Jan 2022 13:06:07 -0000 1.44
+++ mft.c 13 Jan 2022 12:56:38 -0000
@@ -20,7 +20,6 @@
#include <limits.h>
#include <stdarg.h>
#include <stdint.h>
-#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -456,44 +455,6 @@ out:
}
free(cms);
return p.res;
-}
-
-/*
- * Check all files and their hashes in a MFT structure.
- * Return zero on failure, non-zero on success.
- */
-int
-mft_check(const char *fn, struct mft *p)
-{
- size_t i;
- int rc = 1;
- char *cp, *h, *path = NULL;
-
- /* Check hash of file now, but first build path for it */
- cp = strrchr(fn, '/');
- assert(cp != NULL);
- assert(cp - fn < INT_MAX);
-
- for (i = 0; i < p->filesz; i++) {
- const struct mftfile *m = &p->files[i];
- if (!valid_filename(m->file)) {
- if (base64_encode(m->hash, sizeof(m->hash), &h) == -1)
- errx(1, "base64_encode failed in %s", __func__);
- warnx("%s: unsupported filename for %s", fn, h);
- free(h);
- continue;
- }
- if (asprintf(&path, "%.*s/%s", (int)(cp - fn), fn,
- m->file) == -1)
- err(1, NULL);
- if (!valid_filehash(path, m->hash, sizeof(m->hash))) {
- warnx("%s: bad message digest for %s", fn, m->file);
- rc = 0;
- }
- free(path);
- }
-
- return rc;
}
/*
Index: parser.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/parser.c,v
retrieving revision 1.34
diff -u -p -r1.34 parser.c
--- parser.c 11 Jan 2022 13:06:07 -0000 1.34
+++ parser.c 13 Jan 2022 13:00:27 -0000
@@ -22,6 +22,7 @@
#include <assert.h>
#include <err.h>
+#include <fcntl.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
@@ -218,6 +219,45 @@ proc_parser_roa(char *file, const unsign
X509_free(x509);
return roa;
+}
+
+/*
+ * Check all files and their hashes in a MFT structure.
+ * Return zero on failure, non-zero on success.
+ */
+int
+mft_check(const char *fn, struct mft *p)
+{
+ size_t i;
+ int fd, rc = 1;
+ char *cp, *h, *path = NULL;
+
+ /* Check hash of file now, but first build path for it */
+ cp = strrchr(fn, '/');
+ assert(cp != NULL);
+ assert(cp - fn < INT_MAX);
+
+ for (i = 0; i < p->filesz; i++) {
+ const struct mftfile *m = &p->files[i];
+ if (!valid_filename(m->file)) {
+ if (base64_encode(m->hash, sizeof(m->hash), &h) == -1)
+ errx(1, "base64_encode failed in %s", __func__);
+ warnx("%s: unsupported filename for %s", fn, h);
+ free(h);
+ continue;
+ }
+ if (asprintf(&path, "%.*s/%s", (int)(cp - fn), fn,
+ m->file) == -1)
+ err(1, NULL);
+ fd = open(path, O_RDONLY);
+ if (!valid_filehash(fd, m->hash, sizeof(m->hash))) {
+ warnx("%s: bad message digest for %s", fn, m->file);
+ rc = 0;
+ }
+ free(path);
+ }
+
+ return rc;
}
/*
Index: repo.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/repo.c,v
retrieving revision 1.21
diff -u -p -r1.21 repo.c
--- repo.c 13 Jan 2022 11:47:44 -0000 1.21
+++ repo.c 13 Jan 2022 13:00:10 -0000
@@ -823,8 +823,9 @@ rrdp_handle_file(unsigned int id, enum p
if ((fn = rrdp_filename(rr, uri, 1)) == NULL)
return 0;
}
- if (!valid_filehash(fn, hash, hlen)) {
- warnx("%s: bad message digest", fn);
+ fd = open(fn, O_RDONLY);
+ if (!valid_filehash(fd, hash, hlen)) {
+ warnx("%s: bad file digest for %s", rr->notifyuri, fn);
free(fn);
return 0;
}
Index: validate.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/validate.c,v
retrieving revision 1.23
diff -u -p -r1.23 validate.c
--- validate.c 26 Dec 2021 12:32:28 -0000 1.23
+++ validate.c 13 Jan 2022 12:07:54 -0000
@@ -269,29 +269,29 @@ valid_filename(const char *fn)
/*
* Validate a file by verifying the SHA256 hash of that file.
- * Returns 1 if valid, 0 otherwise.
+ * The file is passed a an open filedescriptor fd which can be -1.
+ * Returns 1 if valid, 0 otherwise. Closes fd when done.
*/
int
-valid_filehash(const char *fn, const char *hash, size_t hlen)
+valid_filehash(int fd, const char *hash, size_t hlen)
{
SHA256_CTX ctx;
char filehash[SHA256_DIGEST_LENGTH];
char buffer[8192];
ssize_t nr;
- int fd;
if (hlen != sizeof(filehash))
errx(1, "bad hash size");
- if ((fd = open(fn, O_RDONLY)) == -1)
+ if (fd == -1)
return 0;
SHA256_Init(&ctx);
while ((nr = read(fd, buffer, sizeof(buffer))) > 0)
SHA256_Update(&ctx, buffer, nr);
close(fd);
-
SHA256_Final(filehash, &ctx);
+
if (memcmp(hash, filehash, sizeof(filehash)) != 0)
return 0;