Add function to determine the file type from the file name extension
authortb <tb@openbsd.org>
Fri, 21 Jan 2022 18:49:44 +0000 (18:49 +0000)
committertb <tb@openbsd.org>
Fri, 21 Jan 2022 18:49:44 +0000 (18:49 +0000)
rpki-client uses the same idiom to determine the file type in too many
places. Use one function that determines the appropriate RTYPE from the
file name. Add that type to struct mftfile and use this new member to
simplify queue_add_from_mft*().

input/ok claudio

usr.sbin/rpki-client/extern.h
usr.sbin/rpki-client/main.c
usr.sbin/rpki-client/mft.c
usr.sbin/rpki-client/parser.c
usr.sbin/rpki-client/validate.c

index 7b52516..e6f9b00 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: extern.h,v 1.110 2022/01/20 09:24:08 claudio Exp $ */
+/*     $OpenBSD: extern.h,v 1.111 2022/01/21 18:49:44 tb Exp $ */
 /*
  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -148,11 +148,28 @@ struct tal {
        int              id; /* ID of this 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, authcmp);
 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 */
@@ -451,6 +452,8 @@ 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 *,
                    const unsigned char *, size_t,
index 8c8cf37..bad5685 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: main.c,v 1.180 2022/01/21 14:08:33 tb Exp $ */
+/*     $OpenBSD: main.c,v 1.181 2022/01/21 18:49:44 tb Exp $ */
 /*
  * Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -331,7 +331,7 @@ rrdp_http_done(unsigned int id, enum http_result res, const char *last_mod)
  */
 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, const struct mftfile *file,
        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, const struct mftfile *file,
 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 e393d25..779cd24 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: mft.c,v 1.48 2022/01/18 16:24:55 claudio Exp $ */
+/*     $OpenBSD: mft.c,v 1.49 2022/01/21 18:49:44 tb Exp $ */
 /*
  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -130,6 +130,7 @@ mft_parse_filehash(struct parse *p, const ASN1_OCTET_STRING *os)
        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, const ASN1_OCTET_STRING *os)
                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, const ASN1_OCTET_STRING *os)
        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 mft *p)
        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 70b198f..c6d0e5c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: parser.c,v 1.48 2022/01/21 14:08:33 tb Exp $ */
+/*     $OpenBSD: parser.c,v 1.49 2022/01/21 18:49:44 tb Exp $ */
 /*
  * Copyright (c) 2019 Claudio Jeker <claudio@openbsd.org>
  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -912,25 +912,9 @@ proc_parser_file(char *file, unsigned char *buf, size_t len)
        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 797fada..9f696d5 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: validate.c,v 1.24 2022/01/13 13:46:03 claudio Exp $ */
+/*     $OpenBSD: validate.c,v 1.25 2022/01/21 18:49:44 tb Exp $ */
 /*
  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -233,6 +233,35 @@ valid_roa(const char *fn, struct auth_tree *auths, struct roa *roa)
        return 1;
 }
 
+/*
+ * 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
@@ -241,13 +270,8 @@ valid_roa(const char *fn, struct auth_tree *auths, struct roa *roa)
 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;
+       }
 }
 
 /*