]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Move TAL to the heap
authorAlberto Leiva Popper <ydahhrk@gmail.com>
Mon, 29 Sep 2025 23:25:18 +0000 (17:25 -0600)
committerAlberto Leiva Popper <ydahhrk@gmail.com>
Mon, 29 Sep 2025 23:25:18 +0000 (17:25 -0600)
Needs to survive its task so the TA will be able to reference it.

src/object/certificate.c
src/object/tal.c
src/object/tal.h
test/object/tal_test.c

index 393a9d33efd994c2b75bbff213ac46d596dc85e9..00747cfd0184f80d7875a591586ad032ed1a27c6 100644 (file)
@@ -216,22 +216,24 @@ validate_subject(X509 *cert)
 }
 
 static X509_PUBKEY *
-decode_spki(struct tal *tal)
+decode_spki(struct tal const *tal)
 {
        X509_PUBKEY *spki;
        unsigned char const *origin, *cursor;
-       size_t len;
 
-       fnstack_push(tal_get_file_name(tal));
-       tal_get_spki(tal, &origin, &len);
+       if (tal == NULL)
+               pr_panic("TAL is NULL.");
+
+       fnstack_push(tal->path);
+       origin = tal->spki;
        cursor = origin;
-       spki = d2i_X509_PUBKEY(NULL, &cursor, len);
+       spki = d2i_X509_PUBKEY(NULL, &cursor, tal->spki_len);
 
        if (spki == NULL) {
                pr_crypto_err("The TAL's public key cannot be decoded.");
                goto fail;
        }
-       if (cursor != origin + len) {
+       if (cursor != origin + tal->spki_len) {
                X509_PUBKEY_free(spki);
                pr_crypto_err("The TAL's public key contains trailing garbage.");
                goto fail;
@@ -245,14 +247,11 @@ fail:     fnstack_pop();
 }
 
 static int
-validate_spki(struct tal *tal, X509_PUBKEY *cert_spki)
+validate_spki(struct tal const *tal, X509_PUBKEY *cert_spki)
 {
        X509_PUBKEY *tal_spki;
        int error;
 
-       if (tal == NULL)
-               pr_panic("TAL is NULL.");
-
        /*
         * We have a problem at this point:
         *
index 0275758b0b32c414faad25ee9f5eb5c1f77394e5..fb1b7989f7db5f7fc9e6e7c04e105d8152848d14 100644 (file)
 #include "thread_var.h"
 #include "types/path.h"
 
-struct tal {
-       char const *file_name;
-       struct uris urls;
-       unsigned char *spki; /* Decoded; not base64. */
-       size_t spki_len;
-};
-
 static char *
 find_newline(char *str)
 {
@@ -42,7 +35,7 @@ is_blank(char const *str)
 }
 
 static int
-read_content(char *fc /* File Content */, struct tal *tal)
+parse_tal(struct tal *tal, char *fc /* File Content */)
 {
        char *nl; /* New Line */
        bool cr; /* Carriage return */
@@ -97,46 +90,39 @@ premature:
        return pr_err("The TAL seems to end prematurely at line '%s'.", fc);
 }
 
-/* @file_path is expected to outlive @tal. */
-static int
-tal_init(struct tal *tal, char const *file_path)
+static struct tal *
+tal_create(char const *path)
 {
+       struct tal *tal;
        struct file_contents file;
-       int error;
 
-       error = file_load(file_path, &file, false);
-       if (error)
-               return error;
-
-       tal->file_name = path_filename(file_path);
+       if (file_load(path, &file, false) != 0)
+               return NULL;
 
+       tal = pzalloc(sizeof(struct tal));
+       tal->path = pstrdup(path);
        uris_init(&tal->urls);
-       error = read_content((char *)file.buf, tal);
-       if (error)
+       atomic_init(&tal->refcount, 1);
+
+       if (parse_tal(tal, (char *)file.buf) != 0) {
                uris_cleanup(&tal->urls, uri_cleanup);
+               free(tal->path);
+               free(tal);
+               tal = NULL;
+       }
 
        file_free(&file);
-       return error;
+       return tal;
 }
 
 static void
 tal_cleanup(struct tal *tal)
 {
-       free(tal->spki);
-       uris_cleanup(&tal->urls, uri_cleanup);
-}
-
-char const *
-tal_get_file_name(struct tal *tal)
-{
-       return (tal != NULL) ? tal->file_name : NULL;
-}
-
-void
-tal_get_spki(struct tal *tal, unsigned char const **buffer, size_t *len)
-{
-       *buffer = tal->spki;
-       *len = tal->spki_len;
+       if (atomic_fetch_sub(&tal->refcount, 1) == 1) {
+               free(tal->spki);
+               uris_cleanup(&tal->urls, uri_cleanup);
+               free(tal);
+       }
 }
 
 static int
@@ -160,6 +146,7 @@ validate_ta(struct tal *tal, struct cache_mapping const *ta_map)
        ta = pzalloc(sizeof(struct rpki_certificate));
        map_copy(&ta->map, ta_map);
        ta->tal = tal;
+       atomic_fetch_add(&tal->refcount, 1);
        atomic_init(&ta->refcount, 1);
 
        vv = cer_traverse(ta);
@@ -209,37 +196,38 @@ try_urls(struct tal *tal, bool (*url_is_protocol)(struct uri const *),
 }
 
 static validation_verdict
-traverse_tal(char const *tal_path)
+traverse_tal(char const *path)
 {
-       struct tal tal;
+       struct tal *tal;
        validation_verdict vv;
 
-       fnstack_push(tal_path);
+       fnstack_push(path);
 
-       if (tal_init(&tal, tal_path) != 0) {
+       tal = tal_create(path);
+       if (!tal) {
                vv = VV_FAIL;
                goto end1;
        }
 
        /* Online attempts */
-       vv = try_urls(&tal, uri_is_https, cache_refresh_by_url);
+       vv = try_urls(tal, uri_is_https, cache_refresh_by_url);
        if (vv != VV_FAIL)
                goto end2;
-       vv = try_urls(&tal, uri_is_rsync, cache_refresh_by_url);
+       vv = try_urls(tal, uri_is_rsync, cache_refresh_by_url);
        if (vv != VV_FAIL)
                goto end2;
        /* Offline fallback attempts */
-       vv = try_urls(&tal, uri_is_https, cache_get_fallback);
+       vv = try_urls(tal, uri_is_https, cache_get_fallback);
        if (vv != VV_FAIL)
                goto end2;
-       vv = try_urls(&tal, uri_is_rsync, cache_get_fallback);
+       vv = try_urls(tal, uri_is_rsync, cache_get_fallback);
        if (vv != VV_FAIL)
                goto end2;
 
        pr_err("None of the TAL URIs yielded a successful traversal.");
        vv = VV_FAIL;
 
-end2:  tal_cleanup(&tal);
+end2:  tal_cleanup(tal);
 end1:  fnstack_pop();
        return vv;
 }
index e436b8ddad0904b9506e8062ba72e0f639bed2a0..d2b7a457f6f7b0d97ad56f6d1d62f5e2355b9021 100644 (file)
@@ -1,14 +1,20 @@
 #ifndef SRC_OBJECT_TAL_H_
 #define SRC_OBJECT_TAL_H_
 
+#include <stdatomic.h>
 #include <stddef.h>
+#include "types/uri.h"
 
 /* This is RFC 8630. */
 
-struct tal;
+struct tal {
+       char *path;
+       struct uris urls;
+       unsigned char *spki; /* Decoded; not base64. */
+       size_t spki_len;
 
-char const *tal_get_file_name(struct tal *);
-void tal_get_spki(struct tal *, unsigned char const **, size_t *);
+       atomic_uint refcount;
+};
 
 int perform_standalone_validation(void);
 
index 36a156c6769be4826fb484ddea5a17fd90fc0f3a..0a0fbd2b3b373062bdcd7ca2164c0cb47e9e5971 100644 (file)
@@ -54,15 +54,15 @@ check_spki(struct tal *tal)
 static void
 test_1url(char const *file)
 {
-       struct tal tal;
+       struct tal *tal = tal_create(file);
 
-       ck_assert_int_eq(0, tal_init(&tal, file));
+       ck_assert_ptr_ne(NULL, tal);
 
-       ck_assert_uint_eq(1, tal.urls.len);
-       ck_assert_uri("rsync://example.com/rpki/ta.cer", &tal.urls.array[0]);
-       check_spki(&tal);
+       ck_assert_uint_eq(1, tal->urls.len);
+       ck_assert_uri("rsync://example.com/rpki/ta.cer", &tal->urls.array[0]);
+       check_spki(tal);
 
-       tal_cleanup(&tal);
+       tal_cleanup(tal);
 }
 
 START_TEST(test_tal_load_1url)
@@ -75,19 +75,19 @@ END_TEST
 static void
 test_4urls(char const *file)
 {
-       struct tal tal;
+       struct tal *tal = tal_create(file);
 
-       ck_assert_int_eq(0, tal_init(&tal, file));
+       ck_assert_ptr_ne(NULL, tal);
 
-       ck_assert_uint_eq(4, tal.urls.len);
-       ck_assert_uri("rsync://example.com/rpki/ta.cer", &tal.urls.array[0]);
-       ck_assert_uri("https://example.com/rpki/ta.cer", &tal.urls.array[1]);
-       ck_assert_uri("rsync://www.example.com/potato/ta.cer", &tal.urls.array[2]);
-       ck_assert_uri("https://wx3.example.com/tomato/ta.cer", &tal.urls.array[3]);
+       ck_assert_uint_eq(4, tal->urls.len);
+       ck_assert_uri("rsync://example.com/rpki/ta.cer", &tal->urls.array[0]);
+       ck_assert_uri("https://example.com/rpki/ta.cer", &tal->urls.array[1]);
+       ck_assert_uri("rsync://www.example.com/potato/ta.cer", &tal->urls.array[2]);
+       ck_assert_uri("https://wx3.example.com/tomato/ta.cer", &tal->urls.array[3]);
 
-       check_spki(&tal);
+       check_spki(tal);
 
-       tal_cleanup(&tal);
+       tal_cleanup(tal);
 }
 
 START_TEST(test_tal_load_4urls)
@@ -102,12 +102,10 @@ END_TEST
 
 START_TEST(test_tal_load_error)
 {
-       struct tal tal;
-
-       ck_assert_int_eq(EINVAL, tal_init(&tal, "resources/tal/4urls-lf-comment-space-1.tal"));
-       ck_assert_int_eq(EINVAL, tal_init(&tal, "resources/tal/4urls-lf-comment-space-2.tal"));
-       ck_assert_int_eq(EINVAL, tal_init(&tal, "resources/tal/4urls-lf-comment-space-3.tal"));
-       ck_assert_int_eq(EINVAL, tal_init(&tal, "resources/tal/4urls-lf-comment-space-4.tal"));
+       ck_assert_ptr_eq(NULL, tal_create("resources/tal/4urls-lf-comment-space-1.tal"));
+       ck_assert_ptr_eq(NULL, tal_create("resources/tal/4urls-lf-comment-space-2.tal"));
+       ck_assert_ptr_eq(NULL, tal_create("resources/tal/4urls-lf-comment-space-3.tal"));
+       ck_assert_ptr_eq(NULL, tal_create("resources/tal/4urls-lf-comment-space-4.tal"));
 }
 END_TEST