if (expected->bits_unused != 0)
return pr_val_err("Hash string has unused bits.");
- do {
- error = hash_file(uri, actual, &actual_len);
- if (!error)
- break;
-
- if (error == EACCES || error == ENOENT) {
- if (incidence(INID_MFT_FILE_NOT_FOUND,
- "File '%s' listed at manifest doesn't exist.",
- uri_val_get_printable(uri)))
- return -EINVAL;
-
- return error;
- }
- /* Any other error (crypto, enomem, file read) */
+ error = hash_file(uri, actual, &actual_len);
+ switch (error) {
+ case 0:
+ break;
+ case EACCES:
+ case ENOENT:
+ if (incidence(INID_MFT_FILE_NOT_FOUND,
+ "File '%s' listed at manifest doesn't exist.",
+ uri_val_get_printable(uri)))
+ return -EINVAL;
+ return error;
+ default:
return ENSURE_NEGATIVE(error);
- } while (0);
+ }
if (!hash_matches(expected->buf, expected->size, actual, actual_len)) {
return incidence(INID_MFT_FILE_HASH_NOT_MATCH,
}
}
+/*
+ * Contract:
+ * - Length = 4 (includes dot)
+ * - Not NULL-terminated!
+ * - Can return NULL
+ */
+static char *
+get_extension(IA5String_t *file)
+{
+ return (file->size < 4) ? NULL : (((char *)file->buf) + file->size - 4);
+}
+
static int
build_rpp(struct Manifest *mft, struct rpki_uri *notif,
struct rpki_uri *mft_uri, struct rpp **pp)
char const *tal;
unsigned int i;
struct FileAndHash *fah;
+ char *ext;
+ int (*rpp_add)(struct rpp *pp, struct rpki_uri *uri);
struct rpki_uri *uri;
int error;
for (i = 0; i < mft->fileList.list.count; i++) {
fah = mft->fileList.list.array[i];
+ /*
+ * rsync filters unknown files. We don't want absent unknown
+ * files to induce RPP rejection, so we'll skip them.
+ * This contradicts rfc9286#6.4, but it's necessary evil because
+ * we can't trust the repositories to not accidentally serve
+ * garbage.
+ *
+ * This includes .mft; They're presently not supposed to be
+ * listed.
+ */
+ ext = get_extension(&fah->file);
+ if (ext == NULL)
+ continue;
+ else if (strncmp(ext, ".cer", 4) == 0)
+ rpp_add = rpp_add_cer;
+ else if (strncmp(ext, ".roa", 4) == 0)
+ rpp_add = rpp_add_roa;
+ else if (strncmp(ext, ".crl", 4) == 0)
+ rpp_add = rpp_add_crl;
+ else if (strncmp(ext, ".gbr", 4) == 0)
+ rpp_add = rpp_add_gbr;
+ else
+ continue;
+
error = uri_create_mft(&uri, tal, notif, mft_uri, &fah->file);
/*
* Not handling ENOTRSYNC is fine because the manifest URL
continue;
}
- if (uri_has_extension(uri, ".cer"))
- rpp_add_cert(*pp, uri);
- else if (uri_has_extension(uri, ".roa"))
- rpp_add_roa(*pp, uri);
- else if (uri_has_extension(uri, ".crl"))
- error = rpp_add_crl(*pp, uri);
- else if (uri_has_extension(uri, ".gbr"))
- rpp_add_ghostbusters(*pp, uri);
- else
- uri_refput(uri); /* ignore it. */
-
+ error = rpp_add(*pp, uri);
if (error) {
uri_refput(uri);
goto fail;
}
/** Steals ownership of @uri. */
-void
-rpp_add_cert(struct rpp *pp, struct rpki_uri *uri)
+int
+rpp_add_cer(struct rpp *pp, struct rpki_uri *uri)
{
uris_add(&pp->certs, uri);
+ return 0;
}
/** Steals ownership of @uri. */
-void
+int
rpp_add_roa(struct rpp *pp, struct rpki_uri *uri)
{
uris_add(&pp->roas, uri);
+ return 0;
}
/** Steals ownership of @uri. */
-void
-rpp_add_ghostbusters(struct rpp *pp, struct rpki_uri *uri)
+int
+rpp_add_gbr(struct rpp *pp, struct rpki_uri *uri)
{
uris_add(&pp->ghostbusters, uri);
+ return 0;
}
/** Steals ownership of @uri. */
void rpp_refget(struct rpp *pp);
void rpp_refput(struct rpp *pp);
-void rpp_add_cert(struct rpp *, struct rpki_uri *);
+int rpp_add_cer(struct rpp *, struct rpki_uri *);
int rpp_add_crl(struct rpp *, struct rpki_uri *);
-void rpp_add_roa(struct rpp *, struct rpki_uri *);
-void rpp_add_ghostbusters(struct rpp *, struct rpki_uri *);
+int rpp_add_roa(struct rpp *, struct rpki_uri *);
+int rpp_add_gbr(struct rpp *, struct rpki_uri *);
struct rpki_uri *rpp_get_crl(struct rpp const *);
int rpp_crl(struct rpp *, STACK_OF(X509_CRL) **);