From a414468d00d0a3be4b6bd8ae902a325336622f6a Mon Sep 17 00:00:00 2001 From: Alberto Leiva Popper Date: Mon, 29 Sep 2025 17:25:18 -0600 Subject: [PATCH] Move TAL to the heap Needs to survive its task so the TA will be able to reference it. --- src/object/certificate.c | 19 +++++----- src/object/tal.c | 76 +++++++++++++++++----------------------- src/object/tal.h | 12 +++++-- test/object/tal_test.c | 40 ++++++++++----------- 4 files changed, 69 insertions(+), 78 deletions(-) diff --git a/src/object/certificate.c b/src/object/certificate.c index 393a9d33..00747cfd 100644 --- a/src/object/certificate.c +++ b/src/object/certificate.c @@ -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: * diff --git a/src/object/tal.c b/src/object/tal.c index 0275758b..fb1b7989 100644 --- a/src/object/tal.c +++ b/src/object/tal.c @@ -12,13 +12,6 @@ #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; } diff --git a/src/object/tal.h b/src/object/tal.h index e436b8dd..d2b7a457 100644 --- a/src/object/tal.h +++ b/src/object/tal.h @@ -1,14 +1,20 @@ #ifndef SRC_OBJECT_TAL_H_ #define SRC_OBJECT_TAL_H_ +#include #include +#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); diff --git a/test/object/tal_test.c b/test/object/tal_test.c index 36a156c6..0a0fbd2b 100644 --- a/test/object/tal_test.c +++ b/test/object/tal_test.c @@ -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 -- 2.47.3