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;
 

Reply via email to