On Fri, Jan 21, 2022 at 02:58:57PM +0100, Claudio Jeker wrote:
> On Wed, Jan 19, 2022 at 06:01:38PM +0100, Theo Buehler wrote:
> > Not sure if it is that much of a win, but it saves some repetition and
> > makes sure we don't forget checking the file name to be longer than 4
> > another time (missed on review in main() and proc_parser_file()).
> 
> I like the diff. It is a good first step.
> One thing below but the diff is OK claudio@

Thanks. I had a stupid logic error in rtype_from_file_extension() which
is fixed below.

[...]

> I was a bit confused here because you did not adjust the first for loop
> that just checks for .crl. I wonder if we should pass the RTYPE value in
> struct mftfile. This would make this code a lot simpler.

I didn't like that part of the diff either.

Here's a diff that extends struct mftfile as you suggested and
simplifies queue_add_from_mft*() using the new type member.

One thing I don't like is that we call rtype_from_file_extension() twice
from mft_parse_filehash(), once in valid_filename() and once directly.

It would make more sense to change valid_filename() to return an enum
rtype directly. The only reason I didn't do it is that I couldn't come
up with a good name (type = valid_filename(fn) looks weird).

Index: extern.h
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
retrieving revision 1.110
diff -u -p -r1.110 extern.h
--- extern.h    20 Jan 2022 09:24:08 -0000      1.110
+++ extern.h    21 Jan 2022 15:00:16 -0000
@@ -149,10 +149,27 @@ struct tal {
 };
 
 /*
+ * Resource types specified by the RPKI profiles.
+ * There might be others we don't consider.
+ */
+enum rtype {
+       RTYPE_INVALID,
+       RTYPE_TAL,
+       RTYPE_MFT,
+       RTYPE_ROA,
+       RTYPE_CER,
+       RTYPE_CRL,
+       RTYPE_GBR,
+       RTYPE_REPO,
+       RTYPE_FILE,
+};
+
+/*
  * Files specified in an MFT have their bodies hashed with SHA256.
  */
 struct mftfile {
        char            *file; /* filename (CER/ROA/CRL, no path) */
+       enum rtype       type; /* file type as determined by extension */
        unsigned char    hash[SHA256_DIGEST_LENGTH]; /* sha256 of body */
 };
 
@@ -281,22 +298,6 @@ RB_PROTOTYPE(auth_tree, auth, entry, aut
 struct auth    *auth_find(struct auth_tree *, const char *);
 void            auth_insert(struct auth_tree *, struct cert *, struct auth *);
 
-/*
- * Resource types specified by the RPKI profiles.
- * There might be others we don't consider.
- */
-enum rtype {
-       RTYPE_EOF = 0,
-       RTYPE_TAL,
-       RTYPE_MFT,
-       RTYPE_ROA,
-       RTYPE_CER,
-       RTYPE_CRL,
-       RTYPE_GBR,
-       RTYPE_REPO,
-       RTYPE_FILE,
-};
-
 enum http_result {
        HTTP_FAILED,    /* anything else */
        HTTP_OK,        /* 200 OK */
@@ -450,6 +451,8 @@ int          valid_filename(const char *);
 int             valid_filehash(int, const char *, size_t);
 int             valid_uri(const char *, size_t, const char *);
 int             valid_origin(const char *, const char *);
+
+enum rtype      rtype_from_file_extension(const char *);
 
 /* Working with CMS. */
 unsigned char  *cms_parse_validate(X509 **, const char *,
Index: main.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/main.c,v
retrieving revision 1.180
diff -u -p -r1.180 main.c
--- main.c      21 Jan 2022 14:08:33 -0000      1.180
+++ main.c      21 Jan 2022 15:30:03 -0000
@@ -331,7 +331,7 @@ rrdp_http_done(unsigned int id, enum htt
  */
 static void
 queue_add_from_mft(const char *path, const struct mftfile *file,
-    enum rtype type, struct repo *rp)
+    struct repo *rp)
 {
        char            *nfile, *npath = NULL;
 
@@ -341,7 +341,7 @@ queue_add_from_mft(const char *path, con
        if ((nfile = strdup(file->file)) == NULL)
                err(1, NULL);
 
-       entityq_add(npath, nfile, type, rp, NULL, 0, -1);
+       entityq_add(npath, nfile, file->type, rp, NULL, 0, -1);
 }
 
 /*
@@ -355,33 +355,29 @@ queue_add_from_mft(const char *path, con
 static void
 queue_add_from_mft_set(const struct mft *mft, const char *name, struct repo 
*rp)
 {
-       size_t                   i, sz;
+       size_t                   i;
        const struct mftfile    *f;
 
        for (i = 0; i < mft->filesz; i++) {
                f = &mft->files[i];
-               sz = strlen(f->file);
-               assert(sz > 4);
-               if (strcasecmp(f->file + sz - 4, ".crl") != 0)
+               if (f->type != RTYPE_CRL)
                        continue;
-               queue_add_from_mft(mft->path, f, RTYPE_CRL, rp);
+               queue_add_from_mft(mft->path, f, rp);
        }
 
        for (i = 0; i < mft->filesz; i++) {
                f = &mft->files[i];
-               sz = strlen(f->file);
-               assert(sz > 4);
-               if (strcasecmp(f->file + sz - 4, ".crl") == 0)
+               switch (f->type) {
+               case RTYPE_CER:
+               case RTYPE_ROA:
+               case RTYPE_GBR:
+                       queue_add_from_mft(mft->path, f, rp);
+                       break;
+               case RTYPE_CRL:
                        continue;
-               else if (strcasecmp(f->file + sz - 4, ".cer") == 0)
-                       queue_add_from_mft(mft->path, f, RTYPE_CER, rp);
-               else if (strcasecmp(f->file + sz - 4, ".roa") == 0)
-                       queue_add_from_mft(mft->path, f, RTYPE_ROA, rp);
-               else if (strcasecmp(f->file + sz - 4, ".gbr") == 0)
-                       queue_add_from_mft(mft->path, f, RTYPE_GBR, rp);
-               else
-                       logx("%s: unsupported file type: %s", name,
-                           f->file);
+               default:
+                       logx("%s: unsupported file type: %s", name, f->file);
+               }
        }
 }
 
@@ -839,17 +835,7 @@ main(int argc, char *argv[])
                goto usage;
        }
        if (file != NULL) {
-               size_t sz;
-
-               sz = strlen(file);
-               if (sz < 5)
-                       errx(1, "unsupported or invalid file: %s", file);
-               if (strcasecmp(file + sz - 4, ".tal") != 0 &&
-                   strcasecmp(file + sz - 4, ".cer") != 0 &&
-                   strcasecmp(file + sz - 4, ".crl") != 0 &&
-                   strcasecmp(file + sz - 4, ".mft") != 0 &&
-                   strcasecmp(file + sz - 4, ".roa") != 0 &&
-                   strcasecmp(file + sz - 4, ".gbr") != 0)
+               if (rtype_from_file_extension(file) == RTYPE_INVALID)
                        errx(1, "unsupported or invalid file: %s", file);
 
                outputdir = NULL;
Index: mft.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/mft.c,v
retrieving revision 1.48
diff -u -p -r1.48 mft.c
--- mft.c       18 Jan 2022 16:24:55 -0000      1.48
+++ mft.c       21 Jan 2022 15:29:25 -0000
@@ -130,6 +130,7 @@ mft_parse_filehash(struct parse *p, cons
        ASN1_SEQUENCE_ANY       *seq;
        const ASN1_TYPE         *file, *hash;
        char                    *fn = NULL;
+       enum rtype               type;
        const unsigned char     *d = os->data;
        size_t                   dsz = os->length;
        int                      rc = 0;
@@ -165,6 +166,8 @@ mft_parse_filehash(struct parse *p, cons
                goto out;
        }
 
+       type = rtype_from_file_extension(fn);
+
        /* Now hash value. */
 
        hash = sk_ASN1_TYPE_value(seq, 1);
@@ -186,6 +189,7 @@ mft_parse_filehash(struct parse *p, cons
        fent = &p->res->files[p->res->filesz++];
 
        fent->file = fn;
+       fent->type = type;
        fn = NULL;
        memcpy(fent->hash, hash->value.bit_string->data, SHA256_DIGEST_LENGTH);
 
@@ -495,6 +499,8 @@ mft_buffer(struct ibuf *b, const struct 
        io_simple_buffer(b, &p->filesz, sizeof(size_t));
        for (i = 0; i < p->filesz; i++) {
                io_str_buffer(b, p->files[i].file);
+               io_simple_buffer(b, &p->files[i].type,
+                   sizeof(p->files[i].type));
                io_simple_buffer(b, p->files[i].hash, SHA256_DIGEST_LENGTH);
        }
 }
@@ -527,6 +533,7 @@ mft_read(struct ibuf *b)
 
        for (i = 0; i < p->filesz; i++) {
                io_read_str(b, &p->files[i].file);
+               io_read_buf(b, &p->files[i].type, sizeof(p->files[i].type));
                io_read_buf(b, p->files[i].hash, SHA256_DIGEST_LENGTH);
        }
 
Index: parser.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/parser.c,v
retrieving revision 1.48
diff -u -p -r1.48 parser.c
--- parser.c    21 Jan 2022 14:08:33 -0000      1.48
+++ parser.c    21 Jan 2022 15:31:54 -0000
@@ -912,25 +912,9 @@ proc_parser_file(char *file, unsigned ch
        struct tal *tal = NULL;
        enum rtype type;
        char *aia = NULL, *aki = NULL, *ski = NULL;
-       size_t sz;
        unsigned long verify_flags = X509_V_FLAG_CRL_CHECK;
 
-       sz = strlen(file);
-       if (sz < 5)
-               errx(1, "%s: unsupported file type", file);
-       if (strcasecmp(file + sz - 4, ".tal") == 0)
-               type = RTYPE_TAL;
-       else if (strcasecmp(file + sz - 4, ".cer") == 0)
-               type = RTYPE_CER;
-       else if (strcasecmp(file + sz - 4, ".crl") == 0)
-               type = RTYPE_CRL;
-       else if (strcasecmp(file + sz - 4, ".mft") == 0)
-               type = RTYPE_MFT;
-       else if (strcasecmp(file + sz - 4, ".roa") == 0)
-               type = RTYPE_ROA;
-       else if (strcasecmp(file + sz - 4, ".gbr") == 0)
-               type = RTYPE_GBR;
-       else
+       if ((type = rtype_from_file_extension(file)) == RTYPE_INVALID)
                errx(1, "%s: unsupported file type", file);
 
        switch (type) {
Index: validate.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/validate.c,v
retrieving revision 1.24
diff -u -p -r1.24 validate.c
--- validate.c  13 Jan 2022 13:46:03 -0000      1.24
+++ validate.c  21 Jan 2022 15:24:00 -0000
@@ -234,6 +234,35 @@ valid_roa(const char *fn, struct auth_tr
 }
 
 /*
+ * Determine rtype corresponding to file extension. Returns RTYPE_INVALID
+ * on error or unkown extension.
+ */
+enum rtype
+rtype_from_file_extension(const char *fn)
+{
+       size_t   sz;
+
+       sz = strlen(fn);
+       if (sz < 5)
+               return RTYPE_INVALID;
+
+       if (strcasecmp(fn + sz - 4, ".tal") == 0)
+               return RTYPE_TAL;
+       if (strcasecmp(fn + sz - 4, ".cer") == 0)
+               return RTYPE_CER;
+       if (strcasecmp(fn + sz - 4, ".crl") == 0)
+               return RTYPE_CRL;
+       if (strcasecmp(fn + sz - 4, ".mft") == 0)
+               return RTYPE_MFT;
+       if (strcasecmp(fn + sz - 4, ".roa") == 0)
+               return RTYPE_ROA;
+       if (strcasecmp(fn + sz - 4, ".gbr") == 0)
+               return RTYPE_GBR;
+
+       return RTYPE_INVALID;
+}
+
+/*
  * Validate a filename listed on a Manifest.
  * draft-ietf-sidrops-6486bis section 4.2.2
  * Returns 1 if filename is valid, otherwise 0.
@@ -241,13 +270,8 @@ valid_roa(const char *fn, struct auth_tr
 int
 valid_filename(const char *fn)
 {
-       size_t                   sz;
        const unsigned char     *c;
 
-       sz = strlen(fn);
-       if (sz < 5)
-               return 0;
-
        for (c = fn; *c != '\0'; ++c)
                if (!isalnum(*c) && *c != '-' && *c != '_' && *c != '.')
                        return 0;
@@ -255,16 +279,15 @@ valid_filename(const char *fn)
        if (strchr(fn, '.') != strrchr(fn, '.'))
                return 0;
 
-       if (strcasecmp(fn + sz - 4, ".cer") == 0)
-               return 1;
-       if (strcasecmp(fn + sz - 4, ".crl") == 0)
+       switch (rtype_from_file_extension(fn)) {
+       case RTYPE_CER:
+       case RTYPE_CRL:
+       case RTYPE_GBR:
+       case RTYPE_ROA:
                return 1;
-       if (strcasecmp(fn + sz - 4, ".gbr") == 0)
-               return 1;
-       if (strcasecmp(fn + sz - 4, ".roa") == 0)
-               return 1;
-
-       return 0;
+       default:
+               return 0;
+       }
 }
 
 /*

Reply via email to