On Thu, Jan 27, 2022 at 09:38:54AM +0100, Claudio Jeker wrote:
> On Thu, Jan 27, 2022 at 07:46:32AM +0100, Theo Buehler wrote:
> > On Wed, Jan 26, 2022 at 04:42:04PM +0100, Claudio Jeker wrote:
> > > So the RFC is not very clear but in general the idea is that if multiple
> > > MFTs are available the newest one (highest manifest number) should be
> > > used.
> > > 
> > > In our case there are two possible MFTs available the previously valid on
> > > and the now downloaded one. So adjust the parser code so that both files
> > > are opened and parsed and the x509 is verified. Checks like the
> > > thisUpdate/nextUpdate validity and FileAndHash sequence are postponed.
> > > Compare these two mfts and decide which one should be used.
> > > Now check everything that was postponed.
> > > 
> > > When checking the hash of files in the MFT check both locations and
> > > remember which file was the actual match. It is important that later on
> > > the same file is opened.
> > > 
> > > The error checking around MFTs had to be adjusted in some places since it
> > > turned out to be too noisy on stale caches.
> > > 
> > > Please test and report unexpected behaviour.
> > 
> > This seems to work fine here. I have read the diff and it looks good,
> > but have not reviewed it thoroughly. Do you consider it ready for that?
> 
> I have parts I'm not super happy with but have no better idea yet.
> Mainly the changes to parse_entity() make that function even more complex
> and error prone. proc_parser_mft_check() is the other function where I'm
> not sure. So happy for any feedback to improve those bits.

The only suggestion I have is the usual one: factor the complicated bits
into a function. The diff below changes two things:

1. Add error checking to mft_compare()
2. Factor the RTYPE_MFT handling into parse_load_mft()

I think I like the more symmetric ownership handling of the two files
better this way. This could probably be improved quite a bit by tweaking
mft_compare() and by choosing better variable names than foo1 and foo2.
In a next pass we could polish the other RTYPE_* cases in entity_parse()
to resemble each other more.

I'm also happy to land your initial diff (ok tb for that) and improve
things in tree.

Index: extern.h
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
retrieving revision 1.115
diff -u -p -r1.115 extern.h
--- extern.h    24 Jan 2022 17:29:37 -0000      1.115
+++ extern.h    27 Jan 2022 09:13:19 -0000
@@ -164,12 +164,19 @@ enum rtype {
        RTYPE_FILE,
 };
 
+enum location {
+       DIR_UNKNOWN,
+       DIR_TEMP,
+       DIR_VALID,
+};
+
 /*
  * 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 */
+       enum location    location;      /* temporary or valid directory */
        unsigned char    hash[SHA256_DIGEST_LENGTH]; /* sha256 of body */
 };
 
@@ -181,11 +188,13 @@ struct mftfile {
 struct mft {
        char            *path; /* relative path to directory of the MFT */
        struct mftfile  *files; /* file and hash */
-       size_t           filesz; /* number of filenames */
        char            *seqnum; /* manifestNumber */
        char            *aia; /* AIA */
        char            *aki; /* AKI */
        char            *ski; /* SKI */
+       time_t           valid_from;
+       time_t           valid_until;
+       size_t           filesz; /* number of filenames */
        unsigned int     repoid;
        int              stale; /* if a stale manifest */
 };
@@ -349,6 +358,7 @@ struct entity {
        unsigned int     repoid;        /* repository identifier */
        int              talid;         /* tal identifier */
        enum rtype       type;          /* type of entity (not RTYPE_EOF) */
+       enum location    location;      /* which directroy the file lives in */
 };
 TAILQ_HEAD(entityq, entity);
 
@@ -416,12 +426,13 @@ struct cert       *ta_parse(const char *, cons
 struct cert    *cert_read(struct ibuf *);
 void            cert_insert_brks(struct brk_tree *, struct cert *);
 
+enum rtype      rtype_from_file_extension(const char *);
 void            mft_buffer(struct ibuf *, const struct mft *);
 void            mft_free(struct mft *);
 struct mft     *mft_parse(X509 **, const char *, const unsigned char *,
                    size_t);
 struct mft     *mft_read(struct ibuf *);
-enum rtype      rtype_from_file_extension(const char *);
+int             mft_compare(const struct mft *, const struct mft *);
 
 void            roa_buffer(struct ibuf *, const struct roa *);
 void            roa_free(struct roa *);
Index: main.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/main.c,v
retrieving revision 1.186
diff -u -p -r1.186 main.c
--- main.c      26 Jan 2022 14:42:39 -0000      1.186
+++ main.c      27 Jan 2022 09:13:19 -0000
@@ -120,6 +120,7 @@ void
 entity_read_req(struct ibuf *b, struct entity *ent)
 {
        io_read_buf(b, &ent->type, sizeof(ent->type));
+       io_read_buf(b, &ent->location, sizeof(ent->location));
        io_read_buf(b, &ent->repoid, sizeof(ent->repoid));
        io_read_buf(b, &ent->talid, sizeof(ent->talid));
        io_read_str(b, &ent->path);
@@ -138,6 +139,7 @@ entity_write_req(const struct entity *en
 
        b = io_new_buffer();
        io_simple_buffer(b, &ent->type, sizeof(ent->type));
+       io_simple_buffer(b, &ent->location, sizeof(ent->location));
        io_simple_buffer(b, &ent->repoid, sizeof(ent->repoid));
        io_simple_buffer(b, &ent->talid, sizeof(ent->talid));
        io_str_buffer(b, ent->path);
@@ -151,6 +153,7 @@ entity_write_repo(struct repo *rp)
 {
        struct ibuf *b;
        enum rtype type = RTYPE_REPO;
+       enum location loc = DIR_UNKNOWN;
        unsigned int repoid;
        char *path, *altpath;
        int talid = 0;
@@ -160,6 +163,7 @@ entity_write_repo(struct repo *rp)
        altpath = repo_basedir(rp, 1);
        b = io_new_buffer();
        io_simple_buffer(b, &type, sizeof(type));
+       io_simple_buffer(b, &loc, sizeof(loc));
        io_simple_buffer(b, &repoid, sizeof(repoid));
        io_simple_buffer(b, &talid, sizeof(talid));
        io_str_buffer(b, path);
@@ -192,8 +196,8 @@ entityq_flush(struct entityq *q, struct 
  * Add the heap-allocated file to the queue for processing.
  */
 static void
-entityq_add(char *path, char *file, enum rtype type, struct repo *rp,
-    unsigned char *data, size_t datasz, int talid)
+entityq_add(char *path, char *file, enum rtype type, enum location loc,
+    struct repo *rp, unsigned char *data, size_t datasz, int talid)
 {
        struct entity   *p;
 
@@ -201,6 +205,7 @@ entityq_add(char *path, char *file, enum
                err(1, NULL);
 
        p->type = type;
+       p->location = loc;
        p->talid = talid;
        p->path = path;
        if (rp != NULL)
@@ -341,7 +346,7 @@ queue_add_from_mft(const char *path, con
        if ((nfile = strdup(file->file)) == NULL)
                err(1, NULL);
 
-       entityq_add(npath, nfile, file->type, rp, NULL, 0, -1);
+       entityq_add(npath, nfile, file->type, file->location, rp, NULL, 0, -1);
 }
 
 /*
@@ -400,7 +405,7 @@ queue_add_file(const char *file, enum rt
        if ((nfile = strdup(file)) == NULL)
                err(1, NULL);
        /* Not in a repository, so directly add to queue. */
-       entityq_add(NULL, nfile, type, NULL, buf, len, talid);
+       entityq_add(NULL, nfile, type, DIR_UNKNOWN, NULL, buf, len, talid);
 }
 
 /*
@@ -434,7 +439,8 @@ queue_add_from_tal(struct tal *tal)
        /* steal the pkey from the tal structure */
        data = tal->pkey;
        tal->pkey = NULL;
-       entityq_add(NULL, nfile, RTYPE_CER, repo, data, tal->pkeysz, tal->id);
+       entityq_add(NULL, nfile, RTYPE_CER, DIR_VALID, repo, data,
+           tal->pkeysz, tal->id);
 }
 
 /*
@@ -477,7 +483,7 @@ queue_add_from_cert(const struct cert *c
                        err(1, NULL);
        }
 
-       entityq_add(npath, nfile, RTYPE_MFT, repo, NULL, 0, -1);
+       entityq_add(npath, nfile, RTYPE_MFT, DIR_UNKNOWN, repo, NULL, 0, -1);
 }
 
 /*
Index: mft.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/mft.c,v
retrieving revision 1.51
diff -u -p -r1.51 mft.c
--- mft.c       24 Jan 2022 17:29:37 -0000      1.51
+++ mft.c       28 Jan 2022 08:21:08 -0000
@@ -42,23 +42,6 @@ struct       parse {
 
 extern ASN1_OBJECT    *mft_oid;
 
-static const char *
-gentime2str(const ASN1_GENERALIZEDTIME *time)
-{
-       static char     buf[64];
-       BIO             *mem;
-
-       if ((mem = BIO_new(BIO_s_mem())) == NULL)
-               cryptoerrx("BIO_new");
-       if (!ASN1_GENERALIZEDTIME_print(mem, time))
-               cryptoerrx("ASN1_GENERALIZEDTIME_print");
-       if (BIO_gets(mem, buf, sizeof(buf)) < 0)
-               cryptoerrx("BIO_gets");
-
-       BIO_free(mem);
-       return buf;
-}
-
 /*
  * Convert an ASN1_GENERALIZEDTIME to a struct tm.
  * Returns 1 on success, 0 on failure.
@@ -79,45 +62,33 @@ generalizedtime_to_tm(const ASN1_GENERAL
 
 /*
  * Validate and verify the time validity of the mft.
- * Returns 1 if all is good, 0 if mft is stale, any other case -1.
+ * Returns 1 if all is good and for any other case 0.
  */
 static int
-check_validity(const ASN1_GENERALIZEDTIME *from,
-    const ASN1_GENERALIZEDTIME *until, const char *fn)
+mft_parse_time(const ASN1_GENERALIZEDTIME *from,
+    const ASN1_GENERALIZEDTIME *until, struct parse *p)
 {
-       time_t now = time(NULL);
-       struct tm tm_from, tm_until, tm_now;
-
-       if (gmtime_r(&now, &tm_now) == NULL) {
-               warnx("%s: could not get current time", fn);
-               return -1;
-       }
+       struct tm tm_from, tm_until;
 
        if (!generalizedtime_to_tm(from, &tm_from)) {
-               warnx("%s: embedded from time format invalid", fn);
-               return -1;
+               warnx("%s: embedded from time format invalid", p->fn);
+               return 0;
        }
        if (!generalizedtime_to_tm(until, &tm_until)) {
-               warnx("%s: embedded until time format invalid", fn);
-               return -1;
+               warnx("%s: embedded until time format invalid", p->fn);
+               return 0;
        }
 
        /* check that until is not before from */
        if (ASN1_time_tm_cmp(&tm_until, &tm_from) < 0) {
-               warnx("%s: bad update interval", fn);
-               return -1;
-       }
-       /* check that now is not before from */
-       if (ASN1_time_tm_cmp(&tm_from, &tm_now) > 0) {
-               warnx("%s: mft not yet valid %s", fn, gentime2str(from));
-               return -1;
-       }
-       /* check that now is not after until */
-       if (ASN1_time_tm_cmp(&tm_until, &tm_now) < 0) {
-               warnx("%s: mft expired on %s", fn, gentime2str(until));
+               warnx("%s: bad update interval", p->fn);
                return 0;
        }
 
+       if ((p->res->valid_from = mktime(&tm_from)) == -1 ||
+           (p->res->valid_until = mktime(&tm_until)) == -1)
+               errx(1, "%s: mktime failed", p->fn);
+
        return 1;
 }
 
@@ -426,15 +397,8 @@ mft_parse_econtent(const unsigned char *
        }
        until = t->value.generalizedtime;
 
-       switch (check_validity(from, until, p->fn)) {
-       case 0:
-               p->res->stale = 1;
-               /* FALLTHROUGH */
-       case 1:
-               break;
-       case -1:
+       if (!mft_parse_time(from, until, p))
                goto out;
-       }
 
        /* File list algorithm. */
 
@@ -570,6 +534,8 @@ mft_buffer(struct ibuf *b, const struct 
                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].location,
+                   sizeof(p->files[i].location));
                io_simple_buffer(b, p->files[i].hash, SHA256_DIGEST_LENGTH);
        }
 }
@@ -603,8 +569,43 @@ 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].location,
+                   sizeof(p->files[i].location));
                io_read_buf(b, p->files[i].hash, SHA256_DIGEST_LENGTH);
        }
 
        return p;
+}
+
+/*
+ * Compare two MFT files, returns 1 if first MFT is better and 0 if second
+ * should be used.
+ */
+int
+mft_compare(const struct mft *a, const struct mft *b)
+{
+       BIGNUM *abn = NULL, *bbn = NULL;
+       int r;
+
+       if (b == NULL)
+               return 1;
+       if (a == NULL)
+               return 0;
+
+       if (!BN_hex2bn(&abn, a->seqnum))
+               errx(1, "BN_hex2bn");
+       if (!BN_hex2bn(&bbn, b->seqnum))
+               errx(1, "BN_hex2bn");
+       r = BN_cmp(abn, bbn);
+       BN_free(abn);
+       BN_free(bbn);
+
+       if (r < 0)
+               return 0;
+
+       /*
+        * Equal sequence numbers should not happen for different content.
+        * In this case we prefer the newer MFT.
+        */
+       return 1;
 }
Index: parser.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/parser.c,v
retrieving revision 1.56
diff -u -p -r1.56 parser.c
--- parser.c    26 Jan 2022 14:42:39 -0000      1.56
+++ parser.c    28 Jan 2022 08:13:29 -0000
@@ -91,49 +91,48 @@ repo_add(unsigned int id, char *path, ch
                errx(1, "repository already added: id %d, %s", id, path);
 }
 
+static char *
+time2str(time_t t)
+{
+       static char buf[64];
+       struct tm tm;
+
+       if (gmtime_r(&t, &tm) == NULL)
+               return "could not convert time";
+
+       strftime(buf, sizeof(buf), "%h %d %T %Y %Z", &tm);
+       return buf;
+}
+
 /*
- * Build access path to file based on repoid, path and file values.
- * If wantalt == 1 the function can return NULL, if wantalt == 0 it
- * can not fail.
+ * Build access path to file based on repoid, path, location and file values.
  */
 static char *
 parse_filepath(unsigned int repoid, const char *path, const char *file,
-    int wantalt)
+    enum location loc)
 {
        struct parse_repo       *rp;
        char                    *fn, *repopath;
 
        /* build file path based on repoid, entity path and filename */
        rp = repo_get(repoid);
-       if (rp == NULL) {
-               /* no repo so no alternative path. */
-               if (wantalt)
-                       return NULL;
-
-               if (path == NULL) {
-                       if ((fn = strdup(file)) == NULL)
-                               err(1, NULL);
-               } else {
-                       if (asprintf(&fn, "%s/%s", path, file) == -1)
-                               err(1, NULL);
-               }
-       } else {
-               if (wantalt || rp->path == NULL)
-                       repopath = rp->validpath;
-               else
-                       repopath = rp->path;
+       if (rp == NULL)
+               return NULL;
+       
+       if (loc == DIR_VALID)
+               repopath = rp->validpath;
+       else
+               repopath = rp->path;
 
-               if (repopath == NULL)
-                       return NULL;
+       if (repopath == NULL)
+               return NULL;
 
-               if (path == NULL) {
-                       if (asprintf(&fn, "%s/%s", repopath, file) == -1)
-                               err(1, NULL);
-               } else {
-                       if (asprintf(&fn, "%s/%s/%s", repopath, path,
-                           file) == -1)
-                               err(1, NULL);
-               }
+       if (path == NULL) {
+               if (asprintf(&fn, "%s/%s", repopath, file) == -1)
+                       err(1, NULL);
+       } else {
+               if (asprintf(&fn, "%s/%s/%s", repopath, path, file) == -1)
+                       err(1, NULL);
        }
        return fn;
 }
@@ -205,7 +204,7 @@ verify_cb(int ok, X509_STORE_CTX *store_
  */
 static int
 valid_x509(char *file, X509 *x509, struct auth *a, struct crl *crl,
-    unsigned long flags)
+    unsigned long flags, int nowarn)
 {
        STACK_OF(X509)          *chain;
        STACK_OF(X509_CRL)      *crls = NULL;
@@ -229,7 +228,8 @@ valid_x509(char *file, X509 *x509, struc
 
        if (X509_verify_cert(ctx) <= 0) {
                c = X509_STORE_CTX_get_error(ctx);
-               warnx("%s: %s", file, X509_verify_cert_error_string(c));
+               if (!nowarn || verbose > 1)
+                       warnx("%s: %s", file, X509_verify_cert_error_string(c));
                X509_STORE_CTX_cleanup(ctx);
                sk_X509_free(chain);
                sk_X509_CRL_free(crls);
@@ -261,7 +261,7 @@ proc_parser_roa(char *file, const unsign
        a = valid_ski_aki(file, &auths, roa->ski, roa->aki);
        crl = get_crl(a);
 
-       if (!valid_x509(file, x509, a, crl, X509_V_FLAG_CRL_CHECK)) {
+       if (!valid_x509(file, x509, a, crl, X509_V_FLAG_CRL_CHECK, 0)) {
                X509_free(x509);
                roa_free(roa);
                return NULL;
@@ -303,28 +303,35 @@ proc_parser_roa(char *file, const unsign
 static int
 proc_parser_mft_check(const char *fn, struct mft *p)
 {
-       size_t  i;
-       int     rc = 1;
+       const enum location loc[2] = { DIR_TEMP, DIR_VALID };
+       size_t   i;
+       int      rc = 1;
        char    *path;
 
        for (i = 0; i < p->filesz; i++) {
-               const struct mftfile *m = &p->files[i];
-               int fd = -1, try = 0;
-
-               path = NULL;
-               do {
-                       free(path);
+               struct mftfile *m = &p->files[i];
+               int try, fd = -1, noent = 0, valid = 0;
+               for (try = 0; try < 2 && !valid; try++) {
                        if ((path = parse_filepath(p->repoid, p->path, m->file,
-                           try++)) == NULL)
-                               break;
+                           loc[try])) == NULL)
+                               continue;
                        fd = open(path, O_RDONLY);
-               } while (fd == -1 && try < 2);
+                       if (fd == -1 && errno == ENOENT)
+                               noent++;
+                       free(path);
 
-               free(path);
+                       /* remember which path was checked */
+                       m->location = loc[try];
+                       valid = valid_filehash(fd, m->hash, sizeof(m->hash));
+               }
 
-               if (!valid_filehash(fd, m->hash, sizeof(m->hash))) {
+               if (!valid) {
+                       /* silently skip not-existing unknown files */
+                       if (m->type == RTYPE_INVALID && noent == 2)
+                               continue;
                        warnx("%s: bad message digest for %s", fn, m->file);
                        rc = 0;
+                       continue;
                }
        }
 
@@ -332,7 +339,9 @@ proc_parser_mft_check(const char *fn, st
 }
 
 /*
- * Parse and validate a manifest file.
+ * Parse and validate a manifest file. Skip checking the fileandhash
+ * this is done in the post check. After this step we know the mft is
+ * valid and can be compared.
  * Here we *don't* validate against the list of CRLs, because the
  * certificate used to sign the manifest may specify a CRL that the root
  * certificate didn't, and we haven't scanned for it yet.
@@ -342,8 +351,7 @@ proc_parser_mft_check(const char *fn, st
  * Return the mft on success or NULL on failure.
  */
 static struct mft *
-proc_parser_mft(char *file, const unsigned char *der, size_t len,
-    const char *path, unsigned int repoid)
+proc_parser_mft_pre(char *file, const unsigned char *der, size_t len)
 {
        struct mft              *mft;
        X509                    *x509;
@@ -355,13 +363,45 @@ proc_parser_mft(char *file, const unsign
        a = valid_ski_aki(file, &auths, mft->ski, mft->aki);
 
        /* CRL checks disabled here because CRL is referenced from mft */
-       if (!valid_x509(file, x509, a, NULL, 0)) {
+       if (!valid_x509(file, x509, a, NULL, 0, 1)) {
                mft_free(mft);
                X509_free(x509);
                return NULL;
        }
        X509_free(x509);
 
+       return mft;
+}
+
+/*
+ * Do the end of manifest validation.
+ * Return the mft on success or NULL on failure.
+ */
+static struct mft *
+proc_parser_mft_post(char *file, struct mft *mft, const char *path,
+    unsigned int repoid)
+{
+       /* check that now is not before from */
+       time_t now = time(NULL);
+
+       if (mft == NULL) {
+               warnx("%s: no valid mft available", file);
+               return NULL;
+       }
+
+       /* check that now is not before from */
+       if (now < mft->valid_from) {
+               warnx("%s: mft not yet valid %s", file,
+                   time2str(mft->valid_from));
+               mft->stale = 1;
+       }
+       /* check that now is not after until */
+       if (now > mft->valid_until) {
+               warnx("%s: mft expired on %s", file,
+                   time2str(mft->valid_until));
+               mft->stale = 1;
+       }
+
        mft->repoid = repoid;
        if (path != NULL)
                if ((mft->path = strdup(path)) == NULL)
@@ -376,6 +416,57 @@ proc_parser_mft(char *file, const unsign
        return mft;
 }
 
+static char *
+parse_load_mft(struct entity *entp, unsigned char **f, size_t *flen,
+    struct mft **mft)
+{
+       char            *file, *file1, *file2;
+       struct mft      *mft1 = NULL, *mft2 = NULL;
+       unsigned char   *f1, *f2;
+       size_t           flen1, flen2;
+
+       file1 = parse_filepath(entp->repoid, entp->path, entp->file, DIR_VALID);
+       if (file1 != NULL) {
+               f1 = load_file(file1, &flen1);
+               if (f1 == NULL && errno != ENOENT)
+                       warn("parse file %s", file1);
+               mft1 = proc_parser_mft_pre(file1, f1, flen1);
+       }
+
+       file2 = parse_filepath(entp->repoid, entp->path, entp->file, DIR_TEMP);
+       if (file2 != NULL) {
+               f2 = load_file(file2, &flen2);
+               if (f2 == NULL && errno != ENOENT)
+                       warn("parse file %s", file2);
+               mft2 = proc_parser_mft_pre(file2, f2, flen2);
+       }
+
+       if (mft_compare(mft1, mft2) == 0) {
+               free(f1);
+               free(file1);
+               mft_free(mft1);
+
+               *f = f2;
+               *flen = flen2;
+               *mft = mft2;
+
+               file = file2;
+       } else {
+               free(f2);
+               free(file2);
+               mft_free(mft2);
+
+               *f = f1;
+               *flen = flen1;
+               *mft = mft1;
+
+               file = file1;
+       }
+
+       *mft = proc_parser_mft_post(file, *mft, entp->path, entp->repoid);
+
+       return file;
+}
 /*
  * Validate a certificate, if invalid free the resouces and return NULL.
  */
@@ -388,7 +479,7 @@ proc_parser_cert_validate(char *file, st
        a = valid_ski_aki(file, &auths, cert->ski, cert->aki);
        crl = get_crl(a);
 
-       if (!valid_x509(file, cert->x509, a, crl, X509_V_FLAG_CRL_CHECK)) {
+       if (!valid_x509(file, cert->x509, a, crl, X509_V_FLAG_CRL_CHECK, 0)) {
                cert_free(cert);
                return NULL;
        }
@@ -537,7 +628,7 @@ proc_parser_gbr(char *file, const unsign
        crl = get_crl(a);
 
        /* return value can be ignored since nothing happens here */
-       valid_x509(file, x509, a, crl, X509_V_FLAG_CRL_CHECK);
+       valid_x509(file, x509, a, crl, X509_V_FLAG_CRL_CHECK, 0);
 
        X509_free(x509);
        gbr_free(gbr);
@@ -599,41 +690,23 @@ build_crls(const struct crl *crl, STACK_
                err(1, "sk_X509_CRL_push");
 }
 
+/*
+ * Load the file specified by the entity information.
+ */
 static char *
 parse_load_file(struct entity *entp, unsigned char **f, size_t *flen)
 {
-       char *file, *nfile;
-
-       file = parse_filepath(entp->repoid, entp->path, entp->file, 0);
+       char *file;
 
-       /* TAL files include the data already */
-       if (entp->type == RTYPE_TAL) {
-               *f = NULL;
-               *flen = 0;
-               return file;
-       }
+       file = parse_filepath(entp->repoid, entp->path, entp->file,
+           entp->location);
+       if (file == NULL)
+               errx(1, "no path to file");
 
        *f = load_file(file, flen);
-       if (*f != NULL)
-               return file;
-
-       if (errno != ENOENT)
-               goto fail;
-
-       /* try alternate file location */
-       nfile = parse_filepath(entp->repoid, entp->path, entp->file, 1);
-       if (nfile == NULL)
-               goto fail;
-
-       free(file);
-       file = nfile;
+       if (*f == NULL)
+               warn("parse file %s", file);
 
-       *f = load_file(file, flen);
-       if (*f != NULL)
-               return file;
-
-fail:
-       warn("parse file %s", file);
        return file;
 }
 
@@ -664,15 +737,15 @@ parse_entity(struct entityq *q, struct m
                        continue;
                }
 
-               file = parse_load_file(entp, &f, &flen);
-
                /* pass back at least type, repoid and filename */
                b = io_new_buffer();
                io_simple_buffer(b, &entp->type, sizeof(entp->type));
-               io_str_buffer(b, file);
+               file = NULL;
+               f = NULL;
 
                switch (entp->type) {
                case RTYPE_TAL:
+                       io_str_buffer(b, entp->file);
                        if ((tal = tal_parse(entp->file, entp->data,
                            entp->datasz)) == NULL)
                                errx(1, "%s: could not parse tal file",
@@ -682,6 +755,8 @@ parse_entity(struct entityq *q, struct m
                        tal_free(tal);
                        break;
                case RTYPE_CER:
+                       file = parse_load_file(entp, &f, &flen);
+                       io_str_buffer(b, file);
                        if (entp->data != NULL)
                                cert = proc_parser_root_cert(file,
                                    f, flen, entp->data, entp->datasz,
@@ -695,15 +770,17 @@ parse_entity(struct entityq *q, struct m
                        /*
                         * The parsed certificate data "cert" is now
                         * managed in the "auths" table, so don't free
-                        * it here (see the loop after "out").
+                        * it here.
                         */
                        break;
                case RTYPE_CRL:
+                       file = parse_load_file(entp, &f, &flen);
+                       io_str_buffer(b, file);
                        proc_parser_crl(file, f, flen);
                        break;
                case RTYPE_MFT:
-                       mft = proc_parser_mft(file, f, flen,
-                           entp->path, entp->repoid);
+                       file = parse_load_mft(entp, &f, &flen, &mft);
+                       io_str_buffer(b, file);
                        c = (mft != NULL);
                        io_simple_buffer(b, &c, sizeof(int));
                        if (mft != NULL)
@@ -711,6 +788,8 @@ parse_entity(struct entityq *q, struct m
                        mft_free(mft);
                        break;
                case RTYPE_ROA:
+                       file = parse_load_file(entp, &f, &flen);
+                       io_str_buffer(b, file);
                        roa = proc_parser_roa(file, f, flen);
                        c = (roa != NULL);
                        io_simple_buffer(b, &c, sizeof(int));
@@ -719,6 +798,8 @@ parse_entity(struct entityq *q, struct m
                        roa_free(roa);
                        break;
                case RTYPE_GBR:
+                       file = parse_load_file(entp, &f, &flen);
+                       io_str_buffer(b, file);
                        proc_parser_gbr(file, f, flen);
                        break;
                default:
@@ -981,7 +1062,7 @@ proc_parser_file(char *file, unsigned ch
                a = auth_find(&auths, aki);
                crl = get_crl(a);
 
-               if (valid_x509(file, x509, a, crl, verify_flags))
+               if (valid_x509(file, x509, a, crl, verify_flags, 0))
                        printf("Validation: OK\n");
                else
                        printf("Validation: Failed\n");

Reply via email to