Needs to survive its task so the TA will be able to reference it.
}
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;
}
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:
*
#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)
{
}
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 */
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
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);
}
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;
}
#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);
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)
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)
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