]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Week of work after August detours
authorAlberto Leiva Popper <ydahhrk@gmail.com>
Sat, 7 Sep 2024 02:42:39 +0000 (20:42 -0600)
committerAlberto Leiva Popper <ydahhrk@gmail.com>
Sat, 7 Sep 2024 02:42:39 +0000 (20:42 -0600)
23 files changed:
src/cache.c
src/cert_stack.c
src/cert_stack.h
src/certificate_refs.c
src/config.c
src/hash.c
src/incidence.h
src/object/certificate.c
src/object/crl.c
src/object/crl.h
src/object/ghostbusters.c
src/object/manifest.c
src/object/roa.c
src/print_file.c
src/rpp.c
src/rpp.h
src/rrdp.c
src/slurm/db_slurm.c
src/types/map.c
src/types/map.h
src/types/path.c
src/types/path.h
src/types/url.c

index 6713860fd1356939af5d30bfb7ace5acb384a87f..aaf975ac891e49c00c7bb7833c7455867c87de89 100644 (file)
@@ -588,8 +588,7 @@ try_uri(char const *uri, struct cache_node *root,
        }
 
        map.url = rpp->url;
-       map.path = rpp->path;
-       map.tmppath = rpp->tmppath;
+       map.path = (download != NULL) ? rpp->tmppath : rpp->path;
        error = validate(&map, arg);
        if (error) {
                pr_val_debug("RPP validation failed.");
index a9186b481ab2787202bb3d794d0a4dfe845db1fc..7858955b137db7019f167a0ff47099d29ed043b9 100644 (file)
@@ -175,15 +175,17 @@ certstack_destroy(struct cert_stack *stack)
 }
 
 void
-deferstack_push(struct cert_stack *stack, struct deferred_cert *deferred)
+deferstack_push(struct cert_stack *stack, struct cache_mapping *map,
+    struct rpp *pp)
 {
        struct defer_node *node;
 
        node = pmalloc(sizeof(struct defer_node));
 
        node->type = DNT_CERT;
-       node->deferred = *deferred;
-       rpp_refget(deferred->pp);
+       node->deferred.map = *map;
+       node->deferred.pp = pp;
+       rpp_refget(pp);
        SLIST_INSERT_HEAD(&stack->defers, node, next);
 }
 
index 3d938148f18760d709019675da37a7be7753ff32..1e5c62494f14113c96c1e83dc9bddbdf18a916ad 100644 (file)
@@ -38,7 +38,7 @@ struct deferred_cert {
 int certstack_create(struct cert_stack **);
 void certstack_destroy(struct cert_stack *);
 
-void deferstack_push(struct cert_stack *, struct deferred_cert *cert);
+void deferstack_push(struct cert_stack *, struct cache_mapping *, struct rpp *);
 int deferstack_pop(struct cert_stack *, struct deferred_cert *cert);
 bool deferstack_is_empty(struct cert_stack *);
 
index b94f6d31cdddcc19b7b55644992d95b4cbbb0dc4..87cc0b1c6cfda02864571ecff042760750b3f51a 100644 (file)
@@ -27,7 +27,7 @@ validate_cdp(struct certificate_refs *refs, struct rpp const *pp)
        if (refs->crldp == NULL)
                pr_crit("Certificate's CRL Distribution Point was not recorded.");
 
-       crl_url = rpp_get_crl(pp);
+       crl_url = rpp_get_crl_url(pp);
        if (crl_url == NULL)
                pr_crit("Manifest's CRL was not recorded.");
 
index 2a86fe7a9265a49e9378a5412b7aa3fb486cef42..a6346e3643706d0e90fce067c19937fb6831757e 100644 (file)
@@ -1243,6 +1243,12 @@ config_get_local_repository(void)
        return rpki_config.local_repository;
 }
 
+time_t
+cfg_cache_threshold(void)
+{
+       return 86400; // XXX
+}
+
 unsigned int
 config_get_max_cert_depth(void)
 {
index ec78b65355e1806bddc3ee183c7e1210c7bc811a..4612d33523bd0e57f46693e87f0f7d1ab9b740e1 100644 (file)
@@ -165,6 +165,10 @@ hash_validate_file(struct hash_algorithm const *algorithm, char const *path,
 
        pr_val_debug("Validating file hash: %s", path);
 
+       if (expected_len != hash_get_size(algorithm))
+               return pr_val_err("%s string has bogus size: %zu",
+                   hash_get_name(algorithm), expected_len);
+
        error = hash_file(algorithm, path, actual, &actual_len);
        if (error)
                return error;
index 015c303e7f5ad21075c272aaae178f5ad2c7c4ea..93e97998b8b7821ba40b3107af225c796befbb1c 100644 (file)
@@ -10,8 +10,8 @@
 enum incidence_id {
        INID_HASHALG_HAS_PARAMS,
        INID_OBJ_NOT_DER,
-       INID_MFT_FILE_NOT_FOUND,
-       INID_MFT_FILE_HASH_NOT_MATCH,
+       INID_MFT_FILE_NOT_FOUND, // XXX deprecate and no-op
+       INID_MFT_FILE_HASH_NOT_MATCH, // XXX deprecate and no-op
        INID_MFT_STALE,
        INID_CRL_STALE,
 
index 072032ede68dbb1d043c22f8a5b9fe9af0798b12..7a547bdcc0a1732e73f2dee7aba0f7e4e2762a56 100644 (file)
@@ -32,6 +32,7 @@
 #include "rrdp.h"
 #include "thread_var.h"
 #include "types/name.h"
+#include "types/path.h"
 #include "types/str.h"
 
 /*
@@ -1799,6 +1800,27 @@ certificate_validate_aia(char const *caIssuers, X509 *cert)
        return 0;
 }
 
+static int
+check_rpp(struct cache_mapping *map_rpp, void *rpkiManifest)
+{
+       struct cache_mapping mft;
+       struct rpp *pp;
+       int error;
+
+       mft.url = rpkiManifest;
+       mft.path = join_paths(map_rpp->path, strrchr(mft.url, '/')); // XXX
+
+       error = handle_manifest(&mft, &pp);
+       if (error)
+               goto end;
+
+       rpp_traverse(pp);
+       rpp_refput(pp);
+
+end:   free(mft.path);
+       return error;
+}
+
 /** Boilerplate code for CA certificate validation and recursive traversal. */
 int
 certificate_traverse(struct rpp *rpp_parent, struct cache_mapping *cert_map)
@@ -1810,7 +1832,6 @@ certificate_traverse(struct rpp *rpp_parent, struct cache_mapping *cert_map)
        struct sia_uris sia_uris;
        enum rpki_policy policy;
        enum cert_type certype;
-       struct rpp *pp;
        int error;
 
        state = state_retrieve();
@@ -1828,9 +1849,11 @@ certificate_traverse(struct rpp *rpp_parent, struct cache_mapping *cert_map)
                    map_val_get_printable(cert_map));
        fnstack_push_map(cert_map);
 
-       error = rpp_crl(rpp_parent, &rpp_parent_crl);
-       if (error)
+       rpp_parent_crl = rpp_crl(rpp_parent);
+       if (rpp_parent_crl == NULL) {
+               error = -EINVAL;
                goto revert_fnstack_and_debug;
+       }
 
        /* -- Validate the certificate (@cert) -- */
        error = certificate_load(cert_map, &x509);
@@ -1873,25 +1896,15 @@ certificate_traverse(struct rpp *rpp_parent, struct cache_mapping *cert_map)
        if (error)
                goto revert_uris;
 
-       error = cache_download_alt(&sia_uris, NULL, NULL);
-       if (error)
-               goto revert_uris;
-
        error = x509stack_push(validation_certstack(state), cert_map, x509,
            policy, certype);
        if (error)
                goto revert_uris;
        x509 = NULL; /* Ownership stolen */
 
-       error = handle_manifest(sia_uris.rpkiManifest, &pp);
-       if (error) {
+       error = cache_download_alt(&sia_uris, check_rpp, sia_uris.rpkiManifest);
+       if (error)
                x509stack_cancel(validation_certstack(state));
-               goto revert_uris;
-       }
-
-       /* -- Validate & traverse the RPP (@pp) described by the manifest -- */
-       rpp_traverse(pp);
-       rpp_refput(pp);
 
 revert_uris:
        sias_cleanup(&sia_uris);
index 74781073221c52203deb2ec8f8e14da89bf5717b..e4a197519bf38fa7fb3e677a9cbba00ebb6835c7 100644 (file)
@@ -11,7 +11,7 @@
 #include "types/name.h"
 
 static int
-__crl_load(struct cache_mapping *map, X509_CRL **result)
+__crl_load(char const *path, X509_CRL **result)
 {
        X509_CRL *crl;
        BIO *bio;
@@ -20,16 +20,14 @@ __crl_load(struct cache_mapping *map, X509_CRL **result)
        bio = BIO_new(BIO_s_file());
        if (bio == NULL)
                return val_crypto_err("BIO_new(BIO_s_file()) returned NULL");
-       if (BIO_read_filename(bio, map_get_path(map)) <= 0) {
-               error = val_crypto_err("Error reading CRL '%s'",
-                   map_val_get_printable(map));
+       if (BIO_read_filename(bio, path) <= 0) {
+               error = val_crypto_err("Error reading CRL '%s'", path);
                goto end;
        }
 
        crl = d2i_X509_CRL_bio(bio, NULL);
        if (crl == NULL) {
-               error = val_crypto_err("Error parsing CRL '%s'",
-                   map_val_get_printable(map));
+               error = val_crypto_err("Error parsing CRL '%s'", path);
                goto end;
        }
 
@@ -152,13 +150,13 @@ crl_validate(X509_CRL *crl)
 }
 
 int
-crl_load(struct cache_mapping *map, X509_CRL **result)
+crl_load(char const *path, X509_CRL **result)
 {
        int error;
 
-       pr_val_debug("CRL '%s' {", map_val_get_printable(map));
+       pr_val_debug("CRL '%s' {", path);
 
-       error = __crl_load(map, result);
+       error = __crl_load(path, result);
        if (error)
                goto end;
 
index 6e4915bc6b112a4f1e745734f2a47c957d05c3b6..aecffed4ea2caff16e7632289ea0e67a776b0fe5 100644 (file)
@@ -3,8 +3,6 @@
 
 #include <openssl/x509.h>
 
-#include "types/map.h"
-
-int crl_load(struct cache_mapping *, X509_CRL **);
+int crl_load(char const *, X509_CRL **);
 
 #endif /* SRC_OBJECT_CRL_H_ */
index bb47c8e847ac7dc566d36429dfd364a92a41887f..5d655ff4236a44170b5aab35631a849c4744cd0b 100644 (file)
@@ -1,5 +1,7 @@
 #include "object/ghostbusters.h"
 
+#include <errno.h>
+
 #include "asn1/oid.h"
 #include "log.h"
 #include "object/signed_object.h"
@@ -34,9 +36,11 @@ ghostbusters_traverse(struct cache_mapping *map, struct rpp *pp)
                goto revert_log;
 
        /* Prepare validation arguments */
-       error = rpp_crl(pp, &crl);
-       if (error)
+       crl = rpp_crl(pp);
+       if (crl == NULL) {
+               error = -EINVAL;
                goto revert_sobj;
+       }
        eecert_init(&ee, crl, true);
 
        /* Validate everything */
index 0afaf6182c110fdb96b1ced7595f7586539102ce..bb302dd2f0e923f056145861e7c33335f01a71d3 100644 (file)
@@ -14,6 +14,7 @@
 #include "object/roa.h"
 #include "object/signed_object.h"
 #include "thread_var.h"
+#include "types/path.h"
 
 static int
 decode_manifest(struct signed_object *sobj, struct Manifest **result)
@@ -181,7 +182,7 @@ is_valid_mft_file_chara(uint8_t chara)
            || (chara == '_');
 }
 
-/* RFC 6486bis, section 4.2.2 */
+/* RFC 9286, section 4.2.2 */
 static int
 validate_mft_file(IA5String_t *ia5)
 {
@@ -192,99 +193,65 @@ validate_mft_file(IA5String_t *ia5)
                return pr_val_err("File name is too short (%zu < 5).", ia5->size);
        dot = ia5->size - 4;
        if (ia5->buf[dot] != '.')
-               return pr_val_err("File name seems to lack a three-letter extension.");
+               return pr_val_err("File name is missing three-letter extension.");
 
-       for (i = 0; i < ia5->size; i++) {
-               if (i != dot && !is_valid_mft_file_chara(ia5->buf[i])) {
+       for (i = 0; i < ia5->size; i++)
+               if (i != dot && !is_valid_mft_file_chara(ia5->buf[i]))
                        return pr_val_err("File name contains illegal character #%u",
                            ia5->buf[i]);
-               }
-       }
 
        /*
-        * Actual extension doesn't matter; if there's no handler,
-        * we'll naturally ignore the file.
+        * Well... the RFC says the extension must match a IANA listing,
+        * but rejecting unknown extensions is a liability since they keep
+        * adding new ones, and people rarely updates.
+        * If we don't have a handler, we'll naturally ignore the file.
         */
        return 0;
 }
 
-///**
-// * Computes the hash of the file @map, and compares it to @expected (The
-// * "expected" hash).
-// *
-// * Returns:
-// *   0 if no errors happened and the hashes match, or the hash doesn't match
-// *     but there's an incidence to ignore such error.
-// * < 0 if there was an error that can't be ignored.
-// * > 0 if there was an error but it can be ignored (file not found and there's
-// *     an incidence to ignore this).
-// */
-//static int
-//hash_validate_mft_file(struct cache_mapping *map, BIT_STRING_t const *expected)
-//{
-//     struct hash_algorithm const *algorithm;
-//     size_t hash_size;
-//     unsigned char actual[EVP_MAX_MD_SIZE];
-//     int error;
-//
-//     algorithm = hash_get_sha256();
-//     hash_size = hash_get_size(algorithm);
-//
-//     if (expected->size != hash_size)
-//             return pr_val_err("%s string has bogus size: %zu",
-//                 hash_get_name(algorithm), expected->size);
-//     if (expected->bits_unused != 0)
-//             return pr_val_err("Hash string has unused bits.");
-//
-//     /*
-//      * TODO (#82) This is atrocious. Implement RFC 9286, and probably reuse
-//      * hash_validate_file().
-//      */
-//
-//     error = hash_file(algorithm, map_get_path(map), actual, NULL);
-//     if (error) {
-//             if (error == EACCES || error == ENOENT) {
-//                     /* FIXME .................. */
-//                     if (incidence(INID_MFT_FILE_NOT_FOUND,
-//                         "File '%s' listed at manifest doesn't exist.",
-//                         map_val_get_printable(map)))
-//                             return -EINVAL;
-//
-//                     return error;
-//             }
-//             /* Any other error (crypto, file read) */
-//             return ENSURE_NEGATIVE(error);
-//     }
-//
-//     if (memcmp(expected->buf, actual, hash_size) != 0) {
-//             return incidence(INID_MFT_FILE_HASH_NOT_MATCH,
-//                 "File '%s' does not match its manifest hash.",
-//                 map_val_get_printable(map));
-//     }
-//
-//     return 0;
-//}
+static int
+check_file_and_hash(struct FileAndHash *fah, char const *path)
+{
+       if (fah->hash.bits_unused != 0)
+               return pr_val_err("Hash string has unused bits.");
+
+       /* Includes file exists validation, obv. */
+       return hash_validate_file(hash_get_sha256(), path,
+           fah->hash.buf, fah->hash.size);
+}
+
+#define INFER_CHILD(parent, fah) \
+       path_childn(parent, (char const *)fah->file.buf, fah->file.size)
+
+/*
+ * XXX
+ *
+ * revoked manifest: 6.6
+ * CRL not in fileList: 6.6
+ * fileList file in different folder: 6.6
+ * manifest is identified by id-ad-rpkiManifest. (A directory will have more
+ * than 1 on rollover.)
+ * id-ad-rpkiManifest not found: 6.6
+ * invalid manifest: 6.6
+ * stale manifest: 6.6
+ * fileList file not found: 6.6
+ * bad hash: 6.6
+ * 6.6: warning, fallback to previous version. Children inherit this.
+ */
 
 static int
-build_rpp(struct Manifest *mft, char const *mft_url, struct rpp **pp)
+build_rpp(struct cache_mapping *mft_map, struct Manifest *mft,
+    struct rpp **result)
 {
-       char *rpp_url, *slash;
-       size_t rpp_url_len;
+       struct cache_mapping pp_map;
+       struct rpp *pp;
        int i;
        struct FileAndHash *fah;
-       char *file_url;
-       size_t file_url_len;
-       int written;
-       char const *extension;
+       struct cache_mapping map;
        int error;
 
-       *pp = rpp_create();
-
-       slash = strrchr(mft_url, '/');
-       if (!slash)
-               ; // XXX
-       rpp_url_len = slash - mft_url;
-       rpp_url = pstrndup(mft_url, rpp_url_len);
+       map_parent(mft_map, &pp_map);
+       pp = rpp_create();
 
        for (i = 0; i < mft->fileList.list.count; i++) {
                fah = mft->fileList.list.array[i];
@@ -292,76 +259,40 @@ build_rpp(struct Manifest *mft, char const *mft_url, struct rpp **pp)
                /*
                 * IA5String is a subset of ASCII. However, IA5String_t doesn't
                 * seem to be guaranteed to be NULL-terminated.
-                * `(char *) ia5->buf` is fair, but `strlen(ia5->buf)` is not.
                 */
 
                error = validate_mft_file(&fah->file);
                if (error)
-                       ; // XXX
-
-               file_url_len = rpp_url_len + fah->file.size + 2;
-               file_url = pmalloc(file_url_len);
-               written = snprintf(file_url, file_url_len, "%s/%.*s", rpp_url,
-                   (int)fah->file.size, fah->file.buf);
-               if (written >= file_url_len)
-                       ; // XXX
-
-//             /*
-//              * XXX I think this should be moved somewhere else.
-//              *
-//              * Expect:
-//              * - Negative value: an error not to be ignored, the whole
-//              *   manifest will be discarded.
-//              * - Zero value: hash at manifest matches file's hash, or it
-//              *   doesn't match its hash but there's an incidence to ignore
-//              *   such error.
-//              * - Positive value: file doesn't exist and keep validating
-//              *   manifest.
-//              */
-//             error = hash_validate_mft_file(map, &fah->hash);
-//             if (error < 0) {
-//                     free(file_url);
-//                     goto fail;
-//             }
-//             if (error > 0) {
-//                     free(file_url);
-//                     continue;
-//             }
-
-               extension = ((char const *)fah->file.buf) + fah->file.size - 4;
-               if (strcmp(extension, ".cer") == 0)
-                       rpp_add_cert(*pp, file_url);
-               else if (strcmp(extension, ".roa") == 0)
-                       rpp_add_roa(*pp, file_url);
-               else if (strcmp(extension, ".crl") == 0) {
-                       error = rpp_add_crl(*pp, file_url);
-                       if (error) {
-                               free(file_url);
-                               goto fail;
-                       }
-               } else if (strcmp(extension, ".gbr") == 0)
-                       rpp_add_ghostbusters(*pp, file_url);
-               else
-                       free(file_url); /* ignore it. */
+                       goto fail;
+
+               map.url = INFER_CHILD(pp_map.url, fah);
+               map.path = INFER_CHILD(pp_map.path, fah);
+
+               error = check_file_and_hash(fah, map.path);
+               if (error)
+                       goto fail;
+
+               error = rpp_add_file(pp, &map);
+               if (error)
+                       goto fail;
        }
 
        /* rfc6486#section-7 */
-       if (rpp_get_crl(*pp) == NULL) {
+       if (rpp_crl(pp) == NULL) {
                error = pr_val_err("Manifest lacks a CRL.");
                goto fail;
        }
 
+       map_cleanup(&pp_map);
+       *result = pp;
        return 0;
 
-fail:
-       rpp_refput(*pp);
+fail:  map_cleanup(&pp_map);
+       rpp_refput(pp);
        return error;
 }
 
-/**
- * Validates the manifest pointed by @uri, returns the RPP described by it in
- * @pp.
- */
+/* Validates the manifest @map, returns the RPP described by it in @pp. */
 int
 handle_manifest(struct cache_mapping *map, struct rpp **pp)
 {
@@ -385,15 +316,17 @@ handle_manifest(struct cache_mapping *map, struct rpp **pp)
        if (error)
                goto revert_sobj;
 
-       /* Initialize out parameter (@pp) */
-       error = build_rpp(mft, map->url, pp);
+       /* Initialize @pp */
+       error = build_rpp(map, mft, pp);
        if (error)
                goto revert_manifest;
 
        /* Prepare validation arguments */
-       error = rpp_crl(*pp, &crl);
-       if (error)
+       crl = rpp_crl(*pp);
+       if (crl == NULL) {
+               error = -EINVAL;
                goto revert_rpp;
+       }
        eecert_init(&ee, crl, false);
 
        /* Validate everything */
index 7d495a50c8e35234fc83b45e8b0aaf971aa0321e..93c979cf3a4dbfa26f1a0e331b88ad986d9dc3b2 100644 (file)
@@ -270,9 +270,11 @@ roa_traverse(struct cache_mapping *map, struct rpp *pp)
                goto revert_sobj;
 
        /* Prepare validation arguments */
-       error = rpp_crl(pp, &crl);
-       if (error)
+       crl = rpp_crl(pp);
+       if (crl == NULL) {
+               error = -EINVAL;
                goto revert_roa;
+       }
        eecert_init(&ee, crl, false);
 
        /* Validate and handle everything */
index 57abee2da47646f718d6d46368a3b5696070a543..b5c1ad966c4d5acba4b455c9f78d07e3d56ef1ec 100644 (file)
@@ -66,19 +66,22 @@ end:        pb_cleanup(&pb);
 static BIO *
 rsync2bio_cache(char const *src)
 {
-       char *dst;
-       BIO *bio;
-
-       dst = url2path(src);
-       if (!dst) {
-               pr_op_err("Unparseable rsync URI.");
-               return NULL;
-       }
-
-       bio = __rsync2bio(src, dst);
+       pr_op_err("Disabled for now."); // XXX
+       return NULL;
 
-       free(dst);
-       return bio;
+//     char *dst;
+//     BIO *bio;
+//
+//     dst = url2path(src);
+//     if (!dst) {
+//             pr_op_err("Unparseable rsync URI.");
+//             return NULL;
+//     }
+//
+//     bio = __rsync2bio(src, dst);
+//
+//     free(dst);
+//     return bio;
 }
 
 static BIO *
index 59a12287a11c97fd11166bd273f2418974d9f064..cd70ae02c7cb093fadf90955e8933b3a23bf858c 100644 (file)
--- a/src/rpp.c
+++ b/src/rpp.c
@@ -2,6 +2,7 @@
 
 #include "alloc.h"
 #include "cert_stack.h"
+#include "common.h"
 #include "log.h"
 #include "object/certificate.h"
 #include "object/crl.h"
 #include "thread_var.h"
 #include "types/str.h"
 
+STATIC_ARRAY_LIST(filelist, struct cache_mapping)
+
 /* A Repository Publication Point (RFC 6481), as described by some manifest. */
 struct rpp {
-       struct strlist certs;
+       struct filelist files;
 
-       /*
-        * map NULL implies stack NULL and error 0.
-        * If map is set, stack might or might not be set.
-        * error is only relevant when map is set and stack is unset.
-        */
        struct {
-               char *url;
-               /*
-                * CRL in libcrypto-friendly form.
-                * Initialized lazily; access via rpp_crl().
-                */
+               struct cache_mapping map;
                STACK_OF(X509_CRL) *stack;
-               /*
-                * Some error code if we already tried to initialize @stack but
-                * failed. Prevents us from wasting time doing it again, and
-                * flooding the log with identical error messages.
-                */
-               int error;
        } crl;
 
-       /* The Manifest is not needed for now. */
-       struct strlist roas;
-       struct strlist ghostbusters;
-
        /*
         * Note that the reference counting functions are not prepared for
         * multithreading, because this is not atomic.
@@ -48,18 +32,10 @@ struct rpp {
 struct rpp *
 rpp_create(void)
 {
-       struct rpp *result;
-
-       result = pmalloc(sizeof(struct rpp));
-
-       strlist_init(&result->certs);
-       result->crl.url = NULL;
-       result->crl.stack = NULL;
-       result->crl.error = 0;
-       strlist_init(&result->roas);
-       strlist_init(&result->ghostbusters);
+       struct rpp *result = pmalloc(sizeof(struct rpp));
+       filelist_init(&result->files);
+       memset(&result->crl, 0, sizeof(result->crl));
        result->references = 1;
-
        return result;
 }
 
@@ -74,158 +50,75 @@ rpp_refput(struct rpp *pp)
 {
        pp->references--;
        if (pp->references == 0) {
-               strlist_cleanup(&pp->certs);
-               free(pp->crl.url);
+               filelist_cleanup(&pp->files, map_cleanup);
+               free(pp->crl.map.url);
+               free(pp->crl.map.path);
                sk_X509_CRL_pop_free(pp->crl.stack, X509_CRL_free);
-               strlist_cleanup(&pp->roas);
-               strlist_cleanup(&pp->ghostbusters);
                free(pp);
        }
 }
 
-/* Steals ownership of @url */
-void
-rpp_add_cert(struct rpp *pp, char *url)
-{
-       strlist_add(&pp->certs, url);
-}
-
-/* Steals ownership of @url */
-void
-rpp_add_roa(struct rpp *pp, char *url)
-{
-       strlist_add(&pp->roas, url);
-}
-
-/* Steals ownership of @url */
-void
-rpp_add_ghostbusters(struct rpp *pp, char *url)
-{
-       strlist_add(&pp->ghostbusters, url);
-}
-
-/* Steals ownership of @url */
-int
-rpp_add_crl(struct rpp *pp, char *url)
-{
-       /* rfc6481#section-2.2 */
-       if (pp->crl.url)
-               return pr_val_err("Repository Publication Point has more than one CRL.");
-
-       pp->crl.url = url;
-       return 0;
-}
-
-char const *
-rpp_get_crl(struct rpp const *pp)
-{
-       return pp->crl.url;
-}
-
 static int
-add_crl_to_stack(struct rpp *pp, STACK_OF(X509_CRL) *crls)
+set_crl(struct rpp *pp, struct cache_mapping *map)
 {
        X509_CRL *crl;
        int error;
-       int idx;
 
-       fnstack_push(pp->crl.url);
+       /* rfc6481#section-2.2 */
+       if (pp->crl.stack != NULL)
+               return pr_val_err("Repository Publication Point has more than one CRL.");
 
-       error = crl_load(pp->crl.url, &crl);
+       error = crl_load(map->path, &crl);
        if (error)
-               goto end;
+               return error;
 
-       idx = sk_X509_CRL_push(crls, crl);
-       if (idx <= 0) {
-               error = val_crypto_err("Could not add CRL to a CRL stack");
+       pp->crl.stack = sk_X509_CRL_new_null();
+       if (pp->crl.stack == NULL)
+               enomem_panic();
+       if (sk_X509_CRL_push(pp->crl.stack, crl) <= 0) {
                X509_CRL_free(crl);
-               goto end;
+               sk_X509_CRL_pop_free(pp->crl.stack, X509_CRL_free);
+               pp->crl.stack = NULL;
+               return val_crypto_err("Could not add CRL to a CRL stack");
        }
 
-end:
-       fnstack_pop();
-       return error;
+       pp->crl.map = *map;
+       return 0;
 }
 
-/*
- * Returns the pp's CRL in stack form (which is how libcrypto functions want
- * it).
- * The stack belongs to @pp and should not be released. Can be NULL, in which
- * case you're currently validating the TA (since it lacks governing CRL).
- */
+/* Steals ownership of @map->* */
 int
-rpp_crl(struct rpp *pp, STACK_OF(X509_CRL) **result)
+rpp_add_file(struct rpp *pp, struct cache_mapping *map)
 {
-       STACK_OF(X509_CRL) *stack;
+       if (str_ends_with(map->url, ".crl") == 0)
+               return set_crl(pp, map);
 
-       /* -- Short circuits -- */
-       if (pp == NULL) {
-               /* No pp = currently validating TA. There's no CRL. */
-               *result = NULL;
-               return 0;
-       }
-       if (pp->crl.url == NULL) {
-               /* rpp_crl() assumes the rpp has been populated already. */
-               pr_crit("RPP lacks a CRL.");
-       }
-       if (pp->crl.stack != NULL) {
-               /* Result already cached. */
-               *result = pp->crl.stack;
-               return 0;
-       }
-       if (pp->crl.error) {
-               /* Pretend that we did everything below. */
-               return pp->crl.error;
-       }
-
-       /* -- Actually initialize pp->crl.stack. -- */
-       stack = sk_X509_CRL_new_null();
-       if (stack == NULL)
-               enomem_panic();
-       pp->crl.error = add_crl_to_stack(pp, stack);
-       if (pp->crl.error) {
-               sk_X509_CRL_pop_free(stack, X509_CRL_free);
-               return pp->crl.error;
-       }
-
-       pp->crl.stack = stack;
-       *result = stack;
+       filelist_add(&pp->files, map);
        return 0;
 }
 
-static int
-__cert_traverse(struct rpp *pp)
+char const *
+rpp_get_crl_url(struct rpp const *pp)
 {
-       struct validation *state;
-       struct cert_stack *certstack;
-       ssize_t i;
-       struct deferred_cert deferred;
-
-       if (pp->certs.len == 0)
-               return 0;
-
-       state = state_retrieve();
-       certstack = validation_certstack(state);
-
-       deferred.pp = pp;
-       /*
-        * The for is inverted, to achieve FIFO behavior since the separator.
-        * Not really important; it simply makes the traversal order more
-        * intuitive.
-        */
-       for (i = pp->certs.len - 1; i >= 0; i--) {
-               deferred.map = pp->certs.array[i];
-               deferstack_push(certstack, &deferred);
-       }
+       return pp->crl.map.url;
+}
 
-       return 0;
+/*
+ * The stack belongs to @pp and should not be released. Can be NULL, in which
+ * case you're currently validating the TA (since it lacks governing CRL).
+ */
+STACK_OF(X509_CRL) *
+rpp_crl(struct rpp *pp)
+{
+       return pp->crl.stack;
 }
 
 /* Traverses through all of @pp's known files, validating them. */
 void
 rpp_traverse(struct rpp *pp)
 {
-       char **url;
+       struct cert_stack *certstack;
+       struct cache_mapping *map;
 
        /*
         * A subtree should not invalidate the rest of the tree, so error codes
@@ -234,21 +127,21 @@ rpp_traverse(struct rpp *pp)
         */
 
        /*
-        * Certificates cannot be validated now, because then the algorithm
-        * would be recursive.
-        * Store them in the defer stack (see cert_stack.h), will get back to
-        * them later.
+        * Certificates cannot be validated now, because then
+        * the algorithm would be recursive.
+        * Store them in the defer stack (see cert_stack.h),
+        * will get back to them later.
         */
-       __cert_traverse(pp);
 
-       /* Validate ROAs, apply validation_handler on them. */
-       ARRAYLIST_FOREACH(&pp->roas, url)
-               roa_traverse(*url, pp);
+       certstack = validation_certstack(state_retrieve());
 
-       /*
-        * We don't do much with the ghostbusters right now.
-        * Just validate them.
-        */
-       ARRAYLIST_FOREACH(&pp->ghostbusters, url)
-               ghostbusters_traverse(*url, pp);
+       ARRAYLIST_FOREACH(&pp->files, map) {
+               char const *ext = map->url + strlen(map->url) - 4;
+               if (strcmp(ext, ".cer") == 0)
+                       deferstack_push(certstack, map, pp);
+               else if (strcmp(ext, ".roa") == 0)
+                       roa_traverse(map, pp);
+               else if (strcmp(ext, ".gbr") == 0)
+                       ghostbusters_traverse(map, pp);
+       }
 }
index 8999b4dc03bbd0a3c4b85deb29fc1fd8d34fef4f..15a15e3a8cc2ef7dd2fa778cea3c179cdab7b959 100644 (file)
--- a/src/rpp.h
+++ b/src/rpp.h
@@ -4,19 +4,18 @@
 #include <openssl/safestack.h>
 #include <openssl/x509.h>
 
+#include "types/map.h"
+
 struct rpp;
 
 struct rpp *rpp_create(void);
-void rpp_refget(struct rpp *pp);
-void rpp_refput(struct rpp *pp);
+void rpp_refget(struct rpp *);
+void rpp_refput(struct rpp *);
 
-void rpp_add_cert(struct rpp *, char *);
-int rpp_add_crl(struct rpp *, char *);
-void rpp_add_roa(struct rpp *, char *);
-void rpp_add_ghostbusters(struct rpp *, char *);
+int rpp_add_file(struct rpp *, struct cache_mapping *);
 
-char const *rpp_get_crl(struct rpp const *);
-int rpp_crl(struct rpp *, STACK_OF(X509_CRL) **);
+char const *rpp_get_crl_url(struct rpp const *);
+STACK_OF(X509_CRL) *rpp_crl(struct rpp *);
 
 void rpp_traverse(struct rpp *);
 
index 6107df514fbfe239ef8dd63a3a5125502ffc5ef0..be11c554a92cb71f8b3576abcb5d4ef41c730412 100644 (file)
@@ -6,6 +6,8 @@
 #include "alloc.h"
 #include "base64.h"
 #include "cache.h"
+#include "cachent.h"
+#include "cachetmp.h"
 #include "common.h"
 #include "config.h"
 #include "file.h"
index 5a34cfcc3fd75a0b1b79d52cf350a1cc65442718..f93fe45e2496690e7f811149c92f9f23c8d78f16 100644 (file)
@@ -97,7 +97,6 @@ int
 db_slurm_create(struct slurm_csum_list *csums, struct db_slurm **result)
 {
        struct db_slurm *db;
-       int error;
 
        db = pmalloc(sizeof(struct db_slurm));
 
index f2e620f178e95982da9489366c017d5e1f5623d3..b7260c078b4ab2f50d0d3a55d60fa5c3c7c8298f 100644 (file)
@@ -1,8 +1,11 @@
 #include "types/map.h"
 
 #include <string.h>
+
+#include "alloc.h"
 #include "config.h"
 #include "log.h"
+#include "types/path.h"
 
 static char const *
 get_filename(char const *file_path)
@@ -38,3 +41,29 @@ map_op_get_printable(struct cache_mapping *map)
 {
        return map_get_printable(map, config_get_op_log_filename_format());
 }
+
+void
+map_parent(struct cache_mapping *child, struct cache_mapping *parent)
+{
+       parent->url = path_parent(child->url);
+       parent->path = path_parent(child->path);
+}
+
+struct cache_mapping *
+map_child(struct cache_mapping *parent, char const *name)
+{
+       struct cache_mapping *child;
+
+       child = pmalloc(sizeof(struct cache_mapping));
+       child->url = join_paths(parent->url, name);
+       child->path = join_paths(parent->path, name);
+
+       return child;
+}
+
+void
+map_cleanup(struct cache_mapping *map)
+{
+       free(map->url);
+       free(map->path);
+}
index 2eb8568da8f33717371b5e05e14f95714be5f7e1..e678fa5b91cd1b9754414c6049747b011139a5a9 100644 (file)
@@ -3,26 +3,18 @@
 
 // XXX document this better
 struct cache_mapping {
-       /*
-        * The one that always starts with "rsync://" or "https://".
-        * Normalized, ASCII-only, NULL-terminated.
-        */
-       char const *url;
-
-       /*
-        * Official cache location of the file.
-        * Normalized, ASCII-only, NULL-terminated.
-        */
-       char const *path;
-
-       /*
-        * Temporary cache location of the file.
-        * It'll stay here until committed.
-        */
-       char const *tmppath;
+       /* Normalized, ASCII-only, NULL-terminated. */
+       char *url;
+       /* Normalized, ASCII-only, NULL-terminated. */
+       char *path;
 };
 
 char const *map_val_get_printable(struct cache_mapping *);
 char const *map_op_get_printable(struct cache_mapping *);
 
+void map_parent(struct cache_mapping *, struct cache_mapping *);
+struct cache_mapping *map_child(struct cache_mapping *, char const *);
+
+void map_cleanup(struct cache_mapping *);
+
 #endif /* SRC_TYPES_MAP_H_ */
index 2246f33872a38782e14a4ef08afb432e941a0942..672bc104e5dc6a5b7149c24479ea7965bebb0340 100644 (file)
@@ -216,7 +216,34 @@ pb_cleanup(struct path_builder *pb)
        free(pb->string);
 }
 
-/* Cannot return NULL. */
+/* Note, fatal is hardcoded as 1. */
+char *
+path_parent(char const *child)
+{
+       struct path_builder pb;
+       pb.string = pstrdup(child);
+       pb.len = pb.capacity = strlen(pb.string);
+       pb_pop(&pb, true);
+       return pb.string;
+}
+
+char *
+path_childn(char const *p1, char const *p2, size_t p2len)
+{
+       struct path_builder pb;
+
+       pb_init(&pb);
+       pb_append(&pb, p1); // XXX
+       pb_appendn(&pb, p2, p2len); // XXX
+
+       return pb.string;
+}
+
+/*
+ * Cannot return NULL.
+ *
+ * XXX I'm starting to use this more. Probably clean the slashes.
+ */
 char *
 join_paths(char const *path1, char const *path2)
 {
index 6aac775fdf3f45cf34de647a02b7fd83777c7d3c..b8a8c14c84a1c67a43edb1917b7670b57d588e34 100644 (file)
@@ -38,6 +38,8 @@ void pb_reverse(struct path_builder *);
 
 void pb_cleanup(struct path_builder *);
 
+char *path_parent(char const *);
+char *path_childn(char const *, char const *, size_t);
 char *join_paths(char const *, char const *);
 
 #endif /* SRC_TYPES_PATH_H_ */
index 11d321fe128e06003fe3ff104bfeca7034082bb0..3e03b68c8f8837b6da25fad735816b726367a165 100644 (file)
  * times we get unsigned chars.
  * Casting a negative char into a unsigned char is undefined behavior.
  */
-static int
-validate_url_character(int character)
-{
-       /*
-        * RFCs 1738 and 3986 define a very specific range of allowed
-        * characters, but I don't think we're that concerned about URL
-        * correctness. Validating the URL properly is more involved than simply
-        * checking legal characters, anyway.
-        *
-        * What I really need this validation for is ensure that we won't get
-        * any trouble later, when we attempt to map the URL to a path.
-        *
-        * Sample trouble: Getting UTF-8 characters. Why are they trouble?
-        * Because we don't have any guarantees that the system's file name
-        * encoding is UTF-8. URIs are not supposed to contain UTF-8 in the
-        * first place, so we have no reason to deal with encoding conversion.
-        *
-        * To be perfectly fair, we have no guarantees that the system's file
-        * name encoding is ASCII-compatible either, but I need to hang onto
-        * SOMETHING.
-        *
-        * (Asking users to use UTF-8 is fine, but asking users to use something
-        * ASCII-compatible is a little better.)
-        *
-        * So just make sure that the character is printable ASCII.
-        *
-        * TODO (next iteration) Consider exhaustive URL validation.
-        */
-       return (0x20 <= character && character <= 0x7E)
-           ? 0
-           : pr_val_err("URL has non-printable character code '%d'.", character);
-}
+//static int
+//validate_url_character(int character)
+//{
+//     /*
+//      * RFCs 1738 and 3986 define a very specific range of allowed
+//      * characters, but I don't think we're that concerned about URL
+//      * correctness. Validating the URL properly is more involved than simply
+//      * checking legal characters, anyway.
+//      *
+//      * What I really need this validation for is ensure that we won't get
+//      * any trouble later, when we attempt to map the URL to a path.
+//      *
+//      * Sample trouble: Getting UTF-8 characters. Why are they trouble?
+//      * Because we don't have any guarantees that the system's file name
+//      * encoding is UTF-8. URIs are not supposed to contain UTF-8 in the
+//      * first place, so we have no reason to deal with encoding conversion.
+//      *
+//      * To be perfectly fair, we have no guarantees that the system's file
+//      * name encoding is ASCII-compatible either, but I need to hang onto
+//      * SOMETHING.
+//      *
+//      * (Asking users to use UTF-8 is fine, but asking users to use something
+//      * ASCII-compatible is a little better.)
+//      *
+//      * So just make sure that the character is printable ASCII.
+//      *
+//      * TODO (next iteration) Consider exhaustive URL validation.
+//      */
+//     return (0x20 <= character && character <= 0x7E)
+//         ? 0
+//         : pr_val_err("URL has non-printable character code '%d'.", character);
+//}
 
 static char *
 path_rewind(char const *root, char *cursor)