From c0b3a335e4dec8bb2ae366a425b717f33b5e8993 Mon Sep 17 00:00:00 2001 From: Alberto Leiva Popper Date: Fri, 13 Sep 2024 17:59:18 -0600 Subject: [PATCH] Starting the home stretch, apparently Testing. Fixes bugs and TODOs. --- src/asn1/signed_data.c | 11 +- src/base64.c | 8 +- src/cache.c | 71 +++++++-- src/cache.h | 5 +- src/cachent.c | 3 + src/cachent.h | 1 - src/cert_stack.c | 164 +++++++------------- src/cert_stack.h | 25 --- src/common.c | 9 +- src/file.c | 6 +- src/main.c | 8 +- src/object/certificate.c | 55 ++----- src/object/crl.c | 15 +- src/object/crl.h | 3 +- src/object/ghostbusters.c | 2 - src/object/manifest.c | 7 +- src/object/roa.c | 97 +++--------- src/object/tal.c | 45 +++--- src/rpp.c | 6 +- src/rrdp.c | 51 +++--- src/rrdp.h | 1 + src/thread_var.c | 23 +-- src/types/map.c | 7 + src/types/map.h | 1 + test/Makefile.am | 2 +- test/cache_test.c | 1 + test/cachent_test.c | 2 + test/mock.c | 6 +- test/object/manifest_test.c | 1 + test/{ => object}/tal_test.c | 12 +- test/resources/tal/4urls-ignored-protos.tal | 14 ++ 31 files changed, 284 insertions(+), 378 deletions(-) rename test/{ => object}/tal_test.c (93%) create mode 100644 test/resources/tal/4urls-ignored-protos.tal diff --git a/src/asn1/signed_data.c b/src/asn1/signed_data.c index 7eb8f7d1..05f120b1 100644 --- a/src/asn1/signed_data.c +++ b/src/asn1/signed_data.c @@ -61,8 +61,6 @@ handle_sdata_certificate(ANY_t *cert_encoded, struct ee_cert *ee, * to a tree leaf. Loops aren't possible. */ - pr_val_debug("EE Certificate (embedded) {"); - /* * "If the call is successful *in is incremented to the byte following * the parsed data." @@ -103,14 +101,9 @@ handle_sdata_certificate(ANY_t *cert_encoded, struct ee_cert *ee, resources_set_policy(ee->res, policy); error = certificate_get_resources(cert, ee->res, CERTYPE_EE); - if (error) - goto end2; -end2: - X509_free(cert); -end1: - pr_val_debug("}"); - return error; +end2: X509_free(cert); +end1: return error; } /* rfc6488#section-2.1.6.4.1 */ diff --git a/src/base64.c b/src/base64.c index 25865bff..560a1a50 100644 --- a/src/base64.c +++ b/src/base64.c @@ -34,17 +34,21 @@ base64_decode(char *in, size_t in_len, unsigned char **out, size_t *out_len) status = EVP_DecodeUpdate(ctx, result, &outl, (unsigned char *)in, in_len); if (status == -1) - return false; + goto cancel; *out_len = outl; status = EVP_DecodeFinal(ctx, result + outl, &outl); if (status != 1) - return false; + goto cancel; + EVP_ENCODE_CTX_free(ctx); *out = result; *out_len += outl; return true; + +cancel: EVP_ENCODE_CTX_free(ctx); + return false; } /* diff --git a/src/cache.c b/src/cache.c index a8bbb2af..ef15fceb 100644 --- a/src/cache.c +++ b/src/cache.c @@ -165,7 +165,7 @@ init_cachedir_tag(void) free(filename); } -static void +static int init_tmp_dir(void) { char *dirname; @@ -173,19 +173,24 @@ init_tmp_dir(void) dirname = get_cache_filename(CACHE_TMPDIR, true); - error = mkdir(dirname, true); - if (error != EEXIST) - pr_crit("Cannot create %s: %s", dirname, strerror(error)); + if (mkdir(dirname, 0777) < 0) { + error = errno; + if (error != EEXIST) + return pr_op_err("Cannot create '%s': %s", + dirname, strerror(error)); + } free(dirname); + return 0; } -void +int cache_setup(void) { init_cache_metafile(); init_tmp_dir(); init_cachedir_tag(); + return 0; } void @@ -506,7 +511,7 @@ dl_rsync(struct cache_node *rpp) return error; } - module->flags |= CNF_RSYNC | CNF_CACHED | CNF_FRESH; + module->flags |= CNF_RSYNC | CNF_CACHED | CNF_FRESH | CNF_FREE_TMPPATH; module->mtim = time_nonfatal(); module->tmppath = tmppath; @@ -543,13 +548,48 @@ dl_http(struct cache_node *node) return error; } - node->flags |= CNF_CACHED | CNF_FRESH; + node->flags |= CNF_CACHED | CNF_FRESH | CNF_FREE_TMPPATH; if (changed) node->mtim = mtim; node->tmppath = tmppath; return 0; } +static char * +get_tmppath(struct cache_node *node) +{ + struct cache_node *ancestor; + struct path_builder pb; + size_t skiplen; + + if (node->tmppath != NULL) + return node->tmppath; + + ancestor = node; + do { + ancestor = ancestor->parent; + if (ancestor == NULL) + pr_crit("aaaaa"); // XXX This should never happen, but maybe don't crash anyway + } while (ancestor->tmppath == NULL); + + skiplen = strlen(ancestor->path); + if (strncmp(ancestor->path, node->path, skiplen) != 0) + return NULL; // XXX + + pb_init(&pb); + if (pb_append(&pb, ancestor->tmppath) != 0) + goto cancel; + if (pb_append(&pb, node->path + skiplen) != 0) + goto cancel; + + node->flags |= CNF_FREE_TMPPATH; + node->tmppath = pb.string; + return pb.string; + +cancel: pb_cleanup(&pb); + return NULL; +} + /* @uri is either a caRepository or a rpkiNotify */ static int try_uri(char const *uri, struct cache_node *root, @@ -581,7 +621,7 @@ try_uri(char const *uri, struct cache_node *root, } map.url = rpp->url; - map.path = (download != NULL) ? rpp->tmppath : rpp->path; + map.path = (download != NULL) ? get_tmppath(rpp) : rpp->path; error = validate(&map, arg); if (error) { pr_val_debug("RPP validation failed."); @@ -633,7 +673,7 @@ cache_download_uri(struct strlist *uris, validate_cb cb, void *arg) return try_uris(uris, cache.rsync, "rsync://", NULL, cb, arg); } -/** +/* * XXX outdated comment * * Assumes the URIs represent different ways to access the same content. @@ -734,7 +774,8 @@ commit_rpp_delta(struct cache_node *node) node->tmppath = NULL; return true; -branch: node->flags = 0; +branch: /* Clean up state flags */ + node->flags &= ~(CNF_CACHED | CNF_FRESH | CNF_TOUCHED | CNF_VALID); if (node->tmppath) { free(node->tmppath); node->tmppath = NULL; @@ -745,7 +786,7 @@ branch: node->flags = 0; static int rmf(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { - if (remove(fpath)) + if (remove(fpath) < 0) pr_op_warn("Can't remove %s: %s", fpath, strerror(errno)); else pr_op_debug("Removed %s.", fpath); @@ -898,7 +939,7 @@ abandoned: if (pm) cachent_delete(pm); unknown: - if (remove(path)) + if (remove(path) < 0) PR_DEBUG_MSG("remove(): %s", strerror(errno)); // XXX return 0; } @@ -932,6 +973,12 @@ remove_orphaned(struct cache_node *node) if (file_exists(node->path) == ENOENT) { pr_op_debug("Missing file; deleting node: %s", node->path); cachent_delete(node); + + if (node == cache.https) + cache.https = NULL; + else if (node == cache.rsync) + cache.rsync = NULL; + return false; } diff --git a/src/cache.h b/src/cache.h index 8fcf64dc..fdf46a02 100644 --- a/src/cache.h +++ b/src/cache.h @@ -4,12 +4,11 @@ #include "types/map.h" #include "types/str.h" -void cache_setup(void); /* Init this module */ +int cache_setup(void); /* Init this module */ void cache_teardown(void); /* Destroy this module */ void cache_prepare(void); /* Prepare cache for new validation cycle */ -void cache_commit(void); /* Finish successful validation cycle */ -/* XXX Huh. Looks like this could use a cache_rollback() */ +void cache_commit(void); /* Finish validation cycle */ struct sia_uris { char *caRepository; /* RPP cage */ diff --git a/src/cachent.c b/src/cachent.c index af68790b..3f51f822 100644 --- a/src/cachent.c +++ b/src/cachent.c @@ -111,6 +111,7 @@ cachent_find(struct cache_node *root, char const *path, struct cache_node **msm) return child; } +// XXX path_childn() dup static char * inherit_path(char const *parent, char const *name, size_t nlen) { @@ -217,6 +218,8 @@ __delete_node(struct cache_node *node) free(node->path); if (node->flags & CNF_FREE_TMPPATH) free(node->tmppath); + if (node->flags & CNF_NOTIFICATION) + rrdp_notif_cleanup(&node->rrdp); free(node); return valid; diff --git a/src/cachent.h b/src/cachent.h index c67362db..63a1c1a9 100644 --- a/src/cachent.h +++ b/src/cachent.h @@ -49,7 +49,6 @@ */ #define RSYNC_INHERIT (CNF_RSYNC | CNF_FRESH) -// XXX rename to cache_entity or cachent struct cache_node { char *url; /* rsync://a.b.c/d/e (normalized) */ char *path; /* path/to/cache/rsync/a.b.c/d/e */ diff --git a/src/cert_stack.c b/src/cert_stack.c index 06e5697d..f863ec09 100644 --- a/src/cert_stack.c +++ b/src/cert_stack.c @@ -15,13 +15,13 @@ enum defer_node_type { struct defer_node { enum defer_node_type type; - /** - * This field is only relevant if @type == PCT_CERT. + /* + * This field is only relevant if @type == DNT_CERT. * Do not dereference members otherwise. */ struct deferred_cert deferred; - /** Used by certstack. Points to the next stacked certificate. */ + /* Used by certstack. Points to the next stacked certificate. */ SLIST_ENTRY(defer_node) next; }; @@ -34,9 +34,7 @@ struct serial_number { STATIC_ARRAY_LIST(serial_numbers, struct serial_number) -/** - * Cached certificate data. - */ +/* Cached certificate data */ struct metadata_node { struct cache_mapping map; struct resources *resources; @@ -47,47 +45,31 @@ struct metadata_node { */ struct serial_numbers serials; - /** Used by certstack. Points to the next stacked certificate. */ + /* Used by certstack. Points to the next stacked certificate. */ SLIST_ENTRY(metadata_node) next; }; -SLIST_HEAD(metadata_stack, metadata_node); - -/** - * This is the foundation through which we pull off our iterative traversal, - * as opposed to a stack-threatening recursive one. - * - * It is a bunch of data that replaces the one that would normally be allocated - * in the function stack. - */ +/* Certificates that need to be remembered during a validation cycle. */ struct cert_stack { - /** - * Defer stack. Certificates we haven't iterated through yet. - * - * Every time a certificate validates successfully, its children are - * stored here so they can be traversed later. + /* + * Defer stack; certificates whose validation has been postponed. + * (Postponing certificates avoids us recursion and stack overflow.) */ struct defer_stack defers; - /** - * x509 stack. Parents of the certificate we're currently iterating - * through. + /* + * X509 stack. Ancestor certificates of the current certificate. * Formatted for immediate libcrypto consumption. */ STACK_OF(X509) *x509s; - /** - * Stacked additional data to each @x509 certificate. - * - * (These two stacks should always have the same size. The reason why I - * don't combine them is because libcrypto's validation function needs - * the X509 stack, and I'm not creating it over and over again.) + /* + * Metadata for each X509. Stuff that doesn't fit in libcrypto's struct. * - * (This is a SLIST and not a STACK_OF because the OpenSSL stack - * implementation is different than the LibreSSL one, and the latter is - * seemingly not intended to be used outside of its library.) + * (This is a SLIST and not a STACK_OF because the LibreSSL STACK_OF + * is seemingly private.) */ - struct metadata_stack metas; + SLIST_HEAD(, metadata_node) metas; }; int @@ -111,18 +93,19 @@ certstack_create(struct cert_stack **result) } static void -defer_destroy(struct defer_node *defer) +defer_pop(struct cert_stack *stack) { - switch (defer->type) { - case DNT_SEPARATOR: - break; - case DNT_CERT: - free(defer->deferred.map.url); - free(defer->deferred.map.path); + struct defer_node *defer; + + defer = SLIST_FIRST(&stack->defers); + if (defer == NULL) + pr_crit("Attempted to pop empty defer stack"); + + SLIST_REMOVE_HEAD(&stack->defers, next); + if (defer->type == DNT_CERT) { + map_cleanup(&defer->deferred.map); rpp_refput(defer->deferred.pp); - break; } - free(defer); } @@ -134,10 +117,16 @@ serial_cleanup(struct serial_number *serial) } static void -meta_destroy(struct metadata_node *meta) +meta_pop(struct cert_stack *stack) { - free(meta->map.url); - free(meta->map.path); + struct metadata_node *meta; + + meta = SLIST_FIRST(&stack->metas); + if (meta == NULL) + pr_crit("Attempted to pop empty metadata stack"); + + SLIST_REMOVE_HEAD(&stack->metas, next); + map_cleanup(&meta->map); resources_destroy(meta->resources); serial_numbers_cleanup(&meta->serials, serial_cleanup); free(meta); @@ -146,30 +135,19 @@ meta_destroy(struct metadata_node *meta) void certstack_destroy(struct cert_stack *stack) { - unsigned int stack_size; - struct metadata_node *meta; - struct defer_node *post; - - stack_size = 0; - while (!SLIST_EMPTY(&stack->defers)) { - post = SLIST_FIRST(&stack->defers); - SLIST_REMOVE_HEAD(&stack->defers, next); - defer_destroy(post); - stack_size++; - } - pr_val_debug("Deleted %u deferred certificates.", stack_size); + int n; + + for (n = 0; !SLIST_EMPTY(&stack->defers); n++) + defer_pop(stack); + pr_val_debug("Deleted %d deferred certificates.", n); - pr_val_debug("Deleting %d stacked x509s.", sk_X509_num(stack->x509s)); + n = sk_X509_num(stack->x509s); sk_X509_pop_free(stack->x509s, X509_free); + pr_val_debug("Deleted %d stacked x509s.", n); - stack_size = 0; - while (!SLIST_EMPTY(&stack->metas)) { - meta = SLIST_FIRST(&stack->metas); - SLIST_REMOVE_HEAD(&stack->metas, next); - meta_destroy(meta); - stack_size++; - } - pr_val_debug("Deleted %u metadatas.", stack_size); + for (n = 0; !SLIST_EMPTY(&stack->metas); n++) + meta_pop(stack); + pr_val_debug("Deleted %u metadatas.", n); free(stack); } @@ -183,7 +161,7 @@ deferstack_push(struct cert_stack *stack, struct cache_mapping *map, node = pmalloc(sizeof(struct defer_node)); node->type = DNT_CERT; - node->deferred.map = *map; // XXX + map_copy(&node->deferred.map, map); node->deferred.pp = pp; rpp_refget(pp); SLIST_INSERT_HEAD(&stack->defers, node, next); @@ -193,23 +171,16 @@ static void x509stack_pop(struct cert_stack *stack) { X509 *cert; - struct metadata_node *meta; cert = sk_X509_pop(stack->x509s); if (cert == NULL) pr_crit("Attempted to pop empty X509 stack"); X509_free(cert); - meta = SLIST_FIRST(&stack->metas); - if (meta == NULL) - pr_crit("Attempted to pop empty metadata stack"); - SLIST_REMOVE_HEAD(&stack->metas, next); - meta_destroy(meta); + meta_pop(stack); } -/** - * Contract: Returns either 0 or -ENOENT. No other outcomes. - */ +/* Contract: Returns either 0 or -ENOENT. No other outcomes. */ int deferstack_pop(struct cert_stack *stack, struct deferred_cert *result) { @@ -221,27 +192,17 @@ again: node = SLIST_FIRST(&stack->defers); if (node->type == DNT_SEPARATOR) { x509stack_pop(stack); - - SLIST_REMOVE_HEAD(&stack->defers, next); - defer_destroy(node); + defer_pop(stack); goto again; } *result = node->deferred; -// uri_refget(node->deferred.uri); // XXX - rpp_refget(node->deferred.pp); SLIST_REMOVE_HEAD(&stack->defers, next); - defer_destroy(node); + free(node); return 0; } -bool -deferstack_is_empty(struct cert_stack *stack) -{ - return SLIST_EMPTY(&stack->defers); -} - static int init_resources(X509 *x509, enum rpki_policy policy, enum cert_type type, struct resources **_result) @@ -286,7 +247,7 @@ create_separator(void) return result; } -/** Steals ownership of @x509 on success. */ +/* Steals ownership of @x509 on success. */ int x509stack_push(struct cert_stack *stack, struct cache_mapping *map, X509 *x509, enum rpki_policy policy, enum cert_type type) @@ -298,7 +259,7 @@ x509stack_push(struct cert_stack *stack, struct cache_mapping *map, X509 *x509, meta = pmalloc(sizeof(struct metadata_node)); - meta->map = *map; // XXX + map_copy(&meta->map, map); serial_numbers_init(&meta->serials); error = init_resources(x509, policy, type, &meta->resources); @@ -330,7 +291,7 @@ cleanup_serial: return error; } -/** +/* * This one is intended to revert a recent x509 push. * Reverts that particular push. * @@ -340,15 +301,8 @@ cleanup_serial: void x509stack_cancel(struct cert_stack *stack) { - struct defer_node *defer_separator; - x509stack_pop(stack); - - defer_separator = SLIST_FIRST(&stack->defers); - if (defer_separator == NULL) - pr_crit("Attempted to pop empty defer stack"); - SLIST_REMOVE_HEAD(&stack->defers, next); - defer_destroy(defer_separator); + defer_pop(stack); } X509 * @@ -357,14 +311,6 @@ x509stack_peek(struct cert_stack *stack) return sk_X509_value(stack->x509s, sk_X509_num(stack->x509s) - 1); } -/** Does not grab reference. */ -struct cache_mapping * -x509stack_peek_map(struct cert_stack *stack) -{ - struct metadata_node *meta = SLIST_FIRST(&stack->metas); - return (meta != NULL) ? &meta->map : NULL; -} - struct resources * x509stack_peek_resources(struct cert_stack *stack) { @@ -384,7 +330,7 @@ get_current_file_name(void) return pstrdup(file_name); } -/** +/* * Intended to validate serial number uniqueness. * "Stores" the serial number in the current relevant certificate metadata, * and complains if there's a collision. That's all. diff --git a/src/cert_stack.h b/src/cert_stack.h index 7368419b..5c818aef 100644 --- a/src/cert_stack.h +++ b/src/cert_stack.h @@ -6,26 +6,6 @@ #include "object/certificate.h" #include "types/name.h" -/* - * One certificate stack is allocated per validation cycle, and it is used - * through its entirety to hold the certificates relevant to the ongoing - * validation. - * - * Keep in mind: This module deals with two different (but correlated) stack - * data structures, and they both store "certificates" (albeit in different - * representations): - * - * - Defer stack: This one stores certificates whose validation has been - * postponed during the validation cycle. (They were found in some manifest - * list, and haven't been opened yet.) - * It prevents us from having to validate the RPKI tree in a recursive manner, - * which would be prone to stack overflow. - * - x509 stack: It is a chain of certificates, ready to be validated by - * libcrypto. - * For any given certificate being validated, this stack stores all of its - * parents. - */ - struct cert_stack; struct deferred_cert { @@ -38,18 +18,13 @@ void certstack_destroy(struct cert_stack *); 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 *); int x509stack_push(struct cert_stack *, struct cache_mapping *, X509 *, enum rpki_policy, enum cert_type); void x509stack_cancel(struct cert_stack *); X509 *x509stack_peek(struct cert_stack *); -struct cache_mapping *x509stack_peek_map(struct cert_stack *); struct resources *x509stack_peek_resources(struct cert_stack *); void x509stack_store_serial(struct cert_stack *, BIGNUM *); -typedef int (*subject_pk_check_cb)(bool *, char const *, void *); -int x509stack_store_subject(struct cert_stack *, struct rfc5280_name *, - subject_pk_check_cb, void *); STACK_OF(X509) *certstack_get_x509s(struct cert_stack *); int certstack_get_x509_num(struct cert_stack *); diff --git a/src/common.c b/src/common.c index ace62b54..c3c2db7d 100644 --- a/src/common.c +++ b/src/common.c @@ -260,10 +260,10 @@ ensure_dir(char const *path, mode_t mode) * path actually refers to a file. * So it looks like this stat() is unavoidable. */ - if (stat_dir(path) == ENOTDIR && remove(path)) + if (stat_dir(path) == ENOTDIR && remove(path) < 0) return errno; - if (mkdir(path, mode)) { + if (mkdir(path, mode) < 0) { error = errno; return (error == EEXIST) ? 0 : error; } @@ -298,7 +298,7 @@ mkdir_p(char const *_path, bool include_basename, mode_t mode) } if (result == ENOTDIR) - pr_op_err_st("stack tracing..."); + pr_op_err_st("stack tracing for '%s'...", path); for (i = 1; path[i] != '\0'; i++) { if (path[i] == '/') { @@ -334,8 +334,7 @@ delete_dir_recursive_bottom_up(char const *path) size_t config_len; int error; - errno = 0; - if (remove(path) != 0) { + if (remove(path) < 0) { error = errno; pr_val_err("Couldn't delete '%s': %s", path, strerror(error)); return error; diff --git a/src/file.c b/src/file.c index 174a751b..27e16d12 100644 --- a/src/file.c +++ b/src/file.c @@ -239,8 +239,7 @@ file_rm_f(char const *path) { int error; - errno = 0; - if (remove(path) != 0) { + if (remove(path) < 0) { error = errno; if (error != ENOENT) return error; @@ -253,8 +252,7 @@ static int rm(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { pr_op_debug("Deleting %s.", fpath); - errno = 0; - return (remove(fpath) != 0) ? errno : 0; + return (remove(fpath) < 0) ? errno : 0; } /* Same as `system("rm -rf ")`, but more portable and maaaaybe faster. */ diff --git a/src/main.c b/src/main.c index d5ab1b77..4d63ee81 100644 --- a/src/main.c +++ b/src/main.c @@ -1,5 +1,6 @@ #include +#include "cache.h" #include "config.h" #include "extension.h" #include "hash.h" @@ -75,7 +76,7 @@ fort_server(void) return error; } -/** +/* * Shells don't like it when we return values other than 0-255. * In fact, bash also has its own meanings for 126-255. * (See man 1 bash > EXIT STATUS) @@ -147,6 +148,9 @@ main(int argc, char **argv) error = vrps_init(); if (error) goto revert_relax_ng; + error = cache_setup(); + if (error) + goto revert_vrps; /* Meat */ @@ -164,6 +168,8 @@ main(int argc, char **argv) /* End */ + cache_teardown(); +revert_vrps: vrps_destroy(); revert_relax_ng: relax_ng_cleanup(); diff --git a/src/object/certificate.c b/src/object/certificate.c index caeb7337..9a09a8ef 100644 --- a/src/object/certificate.c +++ b/src/object/certificate.c @@ -211,7 +211,7 @@ validate_subject(X509 *cert) static X509_PUBKEY * decode_spki(struct tal *tal) { - X509_PUBKEY *spki = NULL; + X509_PUBKEY *spki; unsigned char const *origin, *cursor; size_t len; @@ -548,9 +548,7 @@ struct progress { size_t remaining; }; -/** - * Skip the "T" part of a TLV. - */ +/* Skip the "T" part of a TLV. */ static int skip_t(ANY_t *content, struct progress *p, unsigned int tag) { @@ -567,9 +565,7 @@ skip_t(ANY_t *content, struct progress *p, unsigned int tag) return 0; } -/** - * Skip the "TL" part of a TLV. - */ +/* Skip the "TL" part of a TLV. */ static int skip_tl(ANY_t *content, struct progress *p, unsigned int tag) { @@ -614,9 +610,7 @@ skip_tlv(ANY_t *content, struct progress *p, unsigned int tag) return 0; } -/** - * A structure that points to the LV part of a signedAttrs TLV. - */ +/* A structure that points to the LV part of a signedAttrs TLV. */ struct encoded_signedAttrs { const uint8_t *buffer; ber_tlv_len_t size; @@ -1150,11 +1144,9 @@ __certificate_get_resources(X509 *cert, struct resources *resources, if (!X509_EXTENSION_get_critical(ext)) return pr_val_err("The IP extension is not marked as critical."); - pr_val_debug("IP {"); - error = handle_ip_extension(ext, resources); - pr_val_debug("}"); ip_ext_found = true; + error = handle_ip_extension(ext, resources); if (error) return error; @@ -1164,12 +1156,10 @@ __certificate_get_resources(X509 *cert, struct resources *resources, if (!X509_EXTENSION_get_critical(ext)) return pr_val_err("The AS extension is not marked as critical."); - pr_val_debug("ASN {"); - error = handle_asn_extension(ext, resources, - allow_asn_inherit); - pr_val_debug("}"); asn_ext_found = true; + error = handle_asn_extension(ext, resources, + allow_asn_inherit); if (error) return error; @@ -1188,9 +1178,7 @@ __certificate_get_resources(X509 *cert, struct resources *resources, return 0; } -/** - * Copies the resources from @cert to @resources. - */ +/* Copies the resources from @cert to @resources. */ int certificate_get_resources(X509 *cert, struct resources *resources, enum cert_type type) @@ -1528,7 +1516,7 @@ ad2uri(char **uri, ACCESS_DESCRIPTION *ad) return 0; } -/** +/* * The RFC does not explain AD validation very well. This is personal * interpretation, influenced by Tim Bruijnzeels's response * (https://mailarchive.ietf.org/arch/msg/sidr/4ycmff9jEU4VU9gGK5RyhZ7JYsQ) @@ -1691,9 +1679,7 @@ handle_cp(void *ext, void *arg) return 0; } -/** - * Validates the certificate extensions, Trust Anchor style. - */ +/* Validates the certificate extensions, Trust Anchor style. */ static int certificate_validate_extensions_ta(X509 *cert, struct sia_uris *sia_uris, enum rpki_policy *policy) @@ -1717,7 +1703,7 @@ certificate_validate_extensions_ta(X509 *cert, struct sia_uris *sia_uris, return handle_extensions(handlers, X509_get0_extensions(cert)); } -/** +/* * Validates the certificate extensions, (intermediate) Certificate Authority * style. * @@ -1880,13 +1866,12 @@ end: free(mft.path); return error; } -/** Boilerplate code for CA certificate validation and recursive traversal. */ +/* Boilerplate code for CA certificate validation and recursive traversal. */ int certificate_traverse(struct rpp *rpp_parent, struct cache_mapping *cert_map) { struct validation *state; int total_parents; - STACK_OF(X509_CRL) *rpp_parent_crl; X509 *x509; struct sia_uris sia_uris; enum rpki_policy policy; @@ -1899,26 +1884,13 @@ certificate_traverse(struct rpp *rpp_parent, struct cache_mapping *cert_map) if (total_parents >= config_get_max_cert_depth()) return pr_val_err("Certificate chain maximum depth exceeded."); - /* Debug cert type */ - if (rpp_parent == NULL) - pr_val_debug("TA Certificate '%s' {", - map_val_get_printable(cert_map)); - else - pr_val_debug("Certificate '%s' {", - map_val_get_printable(cert_map)); fnstack_push_map(cert_map); - 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); if (error) goto revert_fnstack_and_debug; - error = certificate_validate_chain(x509, rpp_parent_crl); + error = certificate_validate_chain(x509, rpp_crl(rpp_parent)); if (error) goto revert_cert; @@ -1972,6 +1944,5 @@ revert_cert: X509_free(x509); revert_fnstack_and_debug: fnstack_pop(); - pr_val_debug("}"); return error; } diff --git a/src/object/crl.c b/src/object/crl.c index 39a0e717..3339aecf 100644 --- a/src/object/crl.c +++ b/src/object/crl.c @@ -7,6 +7,7 @@ #include "algorithm.h" #include "extension.h" #include "log.h" +#include "thread_var.h" #include "types/name.h" static int @@ -20,13 +21,13 @@ __crl_load(char const *path, X509_CRL **result) if (bio == NULL) return val_crypto_err("BIO_new(BIO_s_file()) returned NULL"); if (BIO_read_filename(bio, path) <= 0) { - error = val_crypto_err("Error reading CRL '%s'", path); + error = val_crypto_err("Error reading CRL"); goto end; } crl = d2i_X509_CRL_bio(bio, NULL); if (crl == NULL) { - error = val_crypto_err("Error parsing CRL '%s'", path); + error = val_crypto_err("Error parsing CRL"); goto end; } @@ -163,15 +164,14 @@ crl_validate(X509_CRL *crl) return validate_extensions(crl); } -/* XXX I suspect this should receive the map */ int -crl_load(char const *path, X509_CRL **result) +crl_load(struct cache_mapping *map, X509_CRL **result) { int error; - pr_val_debug("CRL '%s' {", path); + fnstack_push_map(map); - error = __crl_load(path, result); + error = __crl_load(map->path, result); if (error) goto end; @@ -179,7 +179,6 @@ crl_load(char const *path, X509_CRL **result) if (error) X509_CRL_free(*result); -end: - pr_val_debug("}"); +end: fnstack_pop(); return error; } diff --git a/src/object/crl.h b/src/object/crl.h index aecffed4..59006ba0 100644 --- a/src/object/crl.h +++ b/src/object/crl.h @@ -2,7 +2,8 @@ #define SRC_OBJECT_CRL_H_ #include +#include "types/map.h" -int crl_load(char const *, X509_CRL **); +int crl_load(struct cache_mapping *, X509_CRL **); #endif /* SRC_OBJECT_CRL_H_ */ diff --git a/src/object/ghostbusters.c b/src/object/ghostbusters.c index 833438d4..7f5bf217 100644 --- a/src/object/ghostbusters.c +++ b/src/object/ghostbusters.c @@ -26,7 +26,6 @@ ghostbusters_traverse(struct cache_mapping *map, struct rpp *pp) int error; /* Prepare */ - pr_val_debug("Ghostbusters '%s' {", map_val_get_printable(map)); fnstack_push_map(map); /* Decode */ @@ -56,7 +55,6 @@ revert_args: revert_sobj: signed_object_cleanup(&sobj); revert_log: - pr_val_debug("}"); fnstack_pop(); return error; } diff --git a/src/object/manifest.c b/src/object/manifest.c index 44abf09e..644ec256 100644 --- a/src/object/manifest.c +++ b/src/object/manifest.c @@ -276,11 +276,11 @@ build_rpp(struct cache_mapping *mft_map, struct Manifest *mft, error = check_file_and_hash(fah, map.path); if (error) - goto fail; + goto fail2; error = rpp_add_file(pp, &map); if (error) - goto fail; + goto fail2; } /* rfc6486#section-7 */ @@ -293,6 +293,7 @@ build_rpp(struct cache_mapping *mft_map, struct Manifest *mft, *result = pp; return 0; +fail2: map_cleanup(&map); fail: map_cleanup(&pp_map); rpp_refput(pp); return error; @@ -311,7 +312,6 @@ handle_manifest(struct cache_mapping *map, struct rpp **pp) int error; /* Prepare */ - pr_val_debug("Manifest '%s' {", map_val_get_printable(map)); fnstack_push_map(map); /* Decode */ @@ -359,7 +359,6 @@ revert_manifest: revert_sobj: signed_object_cleanup(&sobj); revert_log: - pr_val_debug("}"); fnstack_pop(); return error; } diff --git a/src/object/roa.c b/src/object/roa.c index 5074467d..c45f614e 100644 --- a/src/object/roa.c +++ b/src/object/roa.c @@ -29,7 +29,6 @@ ____handle_roa_v4(struct resources *parent, unsigned long asn, if (error) return error; - pr_val_debug("ROAIPAddress {"); pr_val_debug("address: %s/%u", v4addr2str(&prefix.addr), prefix.len); if (roa_addr->maxLength != NULL) { @@ -39,21 +38,18 @@ ____handle_roa_v4(struct resources *parent, unsigned long asn, pr_val_err("Error casting ROA's IPv4 maxLength: %s", strerror(errno)); } - error = pr_val_err("The ROA's IPv4 maxLength isn't a valid unsigned long"); - goto end_error; + return pr_val_err("The ROA's IPv4 maxLength isn't a valid unsigned long"); } pr_val_debug("maxLength: %lu", max_length); if (max_length > 32) { - error = pr_val_err("maxLength (%lu) is out of bounds (0-32).", + return pr_val_err("maxLength (%lu) is out of bounds (0-32).", max_length); - goto end_error; } if (prefix.len > max_length) { - error = pr_val_err("Prefix length (%u) > maxLength (%lu)", + return pr_val_err("Prefix length (%u) > maxLength (%lu)", prefix.len, max_length); - goto end_error; } } else { @@ -61,16 +57,11 @@ ____handle_roa_v4(struct resources *parent, unsigned long asn, } if (!resources_contains_ipv4(parent, &prefix)) { - error = pr_val_err("ROA is not allowed to advertise %s/%u.", + return pr_val_err("ROA is not allowed to advertise %s/%u.", v4addr2str(&prefix.addr), prefix.len); - goto end_error; } - pr_val_debug("}"); return vhandler_handle_roa_v4(asn, &prefix, max_length); -end_error: - pr_val_debug("}"); - return error; } static int @@ -85,7 +76,6 @@ ____handle_roa_v6(struct resources *parent, unsigned long asn, if (error) return error; - pr_val_debug("ROAIPAddress {"); pr_val_debug("address: %s/%u", v6addr2str(&prefix.addr), prefix.len); if (roa_addr->maxLength != NULL) { @@ -95,21 +85,18 @@ ____handle_roa_v6(struct resources *parent, unsigned long asn, pr_val_err("Error casting ROA's IPv6 maxLength: %s", strerror(errno)); } - error = pr_val_err("The ROA's IPv6 maxLength isn't a valid unsigned long"); - goto end_error; + return pr_val_err("The ROA's IPv6 maxLength isn't a valid unsigned long"); } pr_val_debug("maxLength: %lu", max_length); if (max_length > 128) { - error = pr_val_err("maxLength (%lu) is out of bounds (0-128).", + return pr_val_err("maxLength (%lu) is out of bounds (0-128).", max_length); - goto end_error; } if (prefix.len > max_length) { - error = pr_val_err("Prefix length (%u) > maxLength (%lu)", + return pr_val_err("Prefix length (%u) > maxLength (%lu)", prefix.len, max_length); - goto end_error; } } else { @@ -117,16 +104,11 @@ ____handle_roa_v6(struct resources *parent, unsigned long asn, } if (!resources_contains_ipv6(parent, &prefix)) { - error = pr_val_err("ROA is not allowed to advertise %s/%u.", + return pr_val_err("ROA is not allowed to advertise %s/%u.", v6addr2str(&prefix.addr), prefix.len); - goto end_error; } - pr_val_debug("}"); return vhandler_handle_roa_v6(asn, &prefix, max_length); -end_error: - pr_val_debug("}"); - return error; } static int @@ -153,7 +135,6 @@ __handle_roa(struct RouteOriginAttestation *roa, struct resources *parent) int a; int error; - pr_val_debug("eContent {"); if (roa->version != NULL) { error = asn_INTEGER2ulong(roa->version, &version); if (error) { @@ -161,14 +142,12 @@ __handle_roa(struct RouteOriginAttestation *roa, struct resources *parent) pr_val_err("Error casting ROA's version: %s", strerror(errno)); } - error = pr_val_err("The ROA's version isn't a valid long"); - goto end_error; + return pr_val_err("The ROA's version isn't a valid long"); } /* rfc6482#section-3.1 */ if (version != 0) { - error = pr_val_err("ROA's version (%lu) is nonzero.", + return pr_val_err("ROA's version (%lu) is nonzero.", version); - goto end_error; } } @@ -178,70 +157,46 @@ __handle_roa(struct RouteOriginAttestation *roa, struct resources *parent) pr_val_err("Error casting ROA's AS ID value: %s", strerror(errno)); } - error = pr_val_err("ROA's AS ID couldn't be parsed as unsigned long"); - goto end_error; + return pr_val_err("ROA's AS ID couldn't be parsed as unsigned long"); } - if (asn > UINT32_MAX) { - error = pr_val_err("AS value (%lu) is out of range.", asn); - goto end_error; - } - pr_val_debug("asId: %lu", asn); + if (asn > UINT32_MAX) + return pr_val_err("AS value (%lu) is out of range.", asn); /* rfc6482#section-3.3 */ - if (roa->ipAddrBlocks.list.array == NULL) { - error = pr_val_err("ipAddrBlocks array is NULL."); - goto end_error; - } + if (roa->ipAddrBlocks.list.array == NULL) + return pr_val_err("ipAddrBlocks array is NULL."); - pr_val_debug("ipAddrBlocks {"); for (b = 0; b < roa->ipAddrBlocks.list.count; b++) { block = roa->ipAddrBlocks.list.array[b]; - if (block == NULL) { - error = pr_val_err("Address block array element is NULL."); - goto ip_error; - } + if (block == NULL) + return pr_val_err("Address block array element is NULL."); if (block->addressFamily.size != 2) goto family_error; if (block->addressFamily.buf[0] != 0) goto family_error; - if (block->addressFamily.buf[1] != 1 - && block->addressFamily.buf[1] != 2) + if (block->addressFamily.buf[1] != 1 && + block->addressFamily.buf[1] != 2) goto family_error; - pr_val_debug("%s {", - block->addressFamily.buf[1] == 1 ? "v4" : "v6"); - if (block->addresses.list.array == NULL) { - error = pr_val_err("ROA's address list array is NULL."); - pr_val_debug("}"); - goto ip_error; - } + if (block->addresses.list.array == NULL) + return pr_val_err("ROA's address list array is NULL."); for (a = 0; a < block->addresses.list.count; a++) { error = ____handle_roa(parent, asn, block->addressFamily.buf[1], block->addresses.list.array[a]); - if (error) { - pr_val_debug("}"); - goto ip_error; - } + if (error) + return error; } - pr_val_debug("}"); } - /* Error 0 it's ok */ - error = 0; - goto ip_error; + return 0; family_error: - error = pr_val_err("ROA's IP family is not v4 or v6."); -ip_error: - pr_val_debug("}"); -end_error: - pr_val_debug("}"); - return error; + return pr_val_err("ROA's IP family is not v4 or v6."); } int @@ -256,7 +211,6 @@ roa_traverse(struct cache_mapping *map, struct rpp *pp) int error; /* Prepare */ - pr_val_debug("ROA '%s' {", map_val_get_printable(map)); fnstack_push_map(map); /* Decode */ @@ -292,6 +246,5 @@ revert_sobj: signed_object_cleanup(&sobj); revert_log: fnstack_pop(); - pr_val_debug("}"); return error; } diff --git a/src/object/tal.c b/src/object/tal.c index 4a4e07f0..02af11a0 100644 --- a/src/object/tal.c +++ b/src/object/tal.c @@ -83,8 +83,9 @@ read_content(char *fc /* File Content */, struct tal *tal) if (is_blank(fc)) break; - // XXX no longer validating schema - strlist_add(&tal->urls, pstrdup(fc)); + if (str_starts_with(fc, "https://") || + str_starts_with(fc, "rsync://")) + strlist_add(&tal->urls, pstrdup(fc)); fc = nl + cr + 1; if (*fc == '\0') @@ -105,9 +106,7 @@ premature: return pr_op_err("The TAL seems to end prematurely at line '%s'.", fc); } -/** - * @file_name is expected to outlive the result. - */ +/* @file_path is expected to outlive @tal. */ static int tal_init(struct tal *tal, char const *file_path) { @@ -152,7 +151,7 @@ tal_get_spki(struct tal *tal, unsigned char const **buffer, size_t *len) *len = tal->spki_len; } -/** +/* * Performs the whole validation walkthrough that starts with Trust Anchor @ta, * which is assumed to have been extracted from TAL @arg->tal. */ @@ -166,8 +165,6 @@ handle_ta(struct cache_mapping *ta, void *arg) struct deferred_cert deferred; int error; - pr_val_debug("TAL URI '%s' {", map_val_get_printable(ta)); - validation_handler.handle_roa_v4 = handle_roa_v4; validation_handler.handle_roa_v6 = handle_roa_v6; validation_handler.handle_router_key = handle_router_key; @@ -178,8 +175,7 @@ handle_ta(struct cache_mapping *ta, void *arg) return ENSURE_NEGATIVE(error); if (!str_ends_with(ta->url, ".cer")) { - pr_op_err("TAL URI does not point to a certificate. (Expected .cer, got '%s')", - ta->url); + pr_op_err("TAL URI lacks '.cer' extension: %s", ta->url); error = EINVAL; goto end; } @@ -208,8 +204,6 @@ handle_ta(struct cache_mapping *ta, void *arg) /* Handle every other certificate. */ certstack = validation_certstack(state); - if (certstack == NULL) - pr_crit("Validation state has no certificate stack"); do { error = deferstack_pop(certstack, &deferred); @@ -229,7 +223,6 @@ handle_ta(struct cache_mapping *ta, void *arg) } while (true); end: validation_destroy(state); - pr_val_debug("}"); return error; } @@ -252,8 +245,7 @@ do_file_validation(void *arg) args.db = db_table_create(); thread->error = cache_download_uri(&args.tal.urls, handle_ta, &args); if (thread->error) { - pr_op_err("None of the URIs of the TAL '%s' yielded a successful traversal.", - thread->tal_file); + pr_op_err("None of the TAL URIs yielded a successful traversal."); db_table_destroy(args.db); } else { thread->db = args.db; @@ -312,7 +304,7 @@ perform_standalone_validation(void) int error = 0; int tmperr; - cache_setup(); + cache_prepare(); /* TODO (fine) Maybe don't spawn threads if there's only one TAL */ if (foreach_file(config_get_tal(), ".tal", true, spawn_tal_thread, @@ -322,7 +314,12 @@ perform_standalone_validation(void) SLIST_REMOVE_HEAD(&threads, next); thread_destroy(thread); } - return NULL; + + /* + * Commit even on failure, as there's no reason to throw away + * something we recently downloaded if it's marked as valid. + */ + goto end; } /* Wait for all */ @@ -330,13 +327,14 @@ perform_standalone_validation(void) thread = SLIST_FIRST(&threads); tmperr = pthread_join(thread->pid, NULL); if (tmperr) - pr_crit("pthread_join() threw %d (%s) on the '%s' thread.", - tmperr, strerror(tmperr), thread->tal_file); + pr_crit("pthread_join() threw '%s' on the '%s' thread.", + strerror(tmperr), thread->tal_file); SLIST_REMOVE_HEAD(&threads, next); if (thread->error) { error = thread->error; - pr_op_warn("Validation from TAL '%s' yielded error %d (%s); discarding all validation results.", - thread->tal_file, error, strerror(abs(error))); + pr_op_warn("Validation from TAL '%s' yielded '%s'; " + "discarding all validation results.", + thread->tal_file, strerror(abs(error))); } if (!error) { @@ -351,13 +349,12 @@ perform_standalone_validation(void) thread_destroy(thread); } - cache_teardown(); - - /* If one thread has errors, we can't keep the resulting table. */ + /* If at least one thread had a fatal error, the table is unusable. */ if (error) { db_table_destroy(db); db = NULL; } +end: cache_commit(); return db; } diff --git a/src/rpp.c b/src/rpp.c index 72ab988c..c3e75f94 100644 --- a/src/rpp.c +++ b/src/rpp.c @@ -65,7 +65,7 @@ set_crl(struct rpp *pp, struct cache_mapping *map) if (pp->crl.stack != NULL) return pr_val_err("Repository Publication Point has more than one CRL."); - error = crl_load(map->path, &crl); + error = crl_load(map, &crl); if (error) return error; @@ -87,7 +87,7 @@ set_crl(struct rpp *pp, struct cache_mapping *map) int rpp_add_file(struct rpp *pp, struct cache_mapping *map) { - if (str_ends_with(map->url, ".crl") == 0) + if (str_ends_with(map->url, ".crl")) return set_crl(pp, map); filelist_add(&pp->files, map); @@ -107,7 +107,7 @@ rpp_get_crl_url(struct rpp const *pp) STACK_OF(X509_CRL) * rpp_crl(struct rpp *pp) { - return pp->crl.stack; + return (pp != NULL) ? pp->crl.stack : NULL; } /* Traverses through all of @pp's known files, validating them. */ diff --git a/src/rrdp.c b/src/rrdp.c index 2f172971..5723a151 100644 --- a/src/rrdp.c +++ b/src/rrdp.c @@ -101,8 +101,8 @@ session_cleanup(struct rrdp_session *meta) static void metadata_cleanup(struct file_metadata *meta) { - free(meta->hash); free(meta->uri); + free(meta->hash); } static void @@ -867,7 +867,7 @@ handle_snapshot(struct update_notification *new, struct cache_node *notif) if (error) goto end2; error = parse_snapshot(&new->session, tmppath, notif); - delete_file(tmppath); +// delete_file(tmppath); XXX end2: free(tmppath); end1: fnstack_pop(); @@ -938,7 +938,7 @@ handle_delta(struct update_notification *notif, if (error) goto end; error = parse_delta(notif, delta, tmppath, notif_node); - delete_file(tmppath); +// delete_file(tmppath); XXX free(tmppath); end: fnstack_pop(); @@ -1112,19 +1112,22 @@ dl_notif(struct cache_node *notif, struct update_notification *new) if (notif->dlerr) goto end; - if (remove(tmppath) == -1) { - notif->dlerr = errno; - pr_val_err("Can't remove notification's temporal file: %s", - strerror(notif->dlerr)); - goto end; - } - if (mkdir(tmppath, 0777) == -1) { - notif->dlerr = errno; - pr_val_err("Can't create notification's temporal directory: %s", - strerror(notif->dlerr)); - goto end; - } - +// if (remove(tmppath) < 0) { +// notif->dlerr = errno; +// pr_val_err("Can't remove notification's temporal file: %s", +// strerror(notif->dlerr)); +// update_notification_cleanup(new); +// goto end; +// } +// if (mkdir(tmppath, 0777) < 0) { +// notif->dlerr = errno; +// pr_val_err("Can't create notification's temporal directory: %s", +// strerror(notif->dlerr)); +// update_notification_cleanup(new); +// goto end; +// } + + notif->flags |= CNF_FREE_TMPPATH; notif->tmppath = tmppath; return true; @@ -1407,12 +1410,18 @@ revert_notif: } void -rrdp_notif_free(struct cachefile_notification *notif) +rrdp_notif_cleanup(struct cachefile_notification *notif) { - if (notif == NULL) - return; - session_cleanup(¬if->session); + cachent_delete(notif->subtree); clear_delta_hashes(notif); - free(notif); +} + +void +rrdp_notif_free(struct cachefile_notification *notif) +{ + if (notif != NULL) { + rrdp_notif_cleanup(notif); + free(notif); + } } diff --git a/src/rrdp.h b/src/rrdp.h index d88a5b0a..984811a2 100644 --- a/src/rrdp.h +++ b/src/rrdp.h @@ -46,6 +46,7 @@ int rrdp_update(struct cache_node *); json_t *rrdp_notif2json(struct cachefile_notification *); int rrdp_json2notif(json_t *, struct cachefile_notification **); +void rrdp_notif_cleanup(struct cachefile_notification *); void rrdp_notif_free(struct cachefile_notification *); #endif /* SRC_RRDP_H_ */ diff --git a/src/thread_var.c b/src/thread_var.c index b9a1b681..13d5ec5f 100644 --- a/src/thread_var.c +++ b/src/thread_var.c @@ -112,7 +112,7 @@ fnstack_cleanup(void) pr_op_err("pthread_setspecific() returned %d.", error); } -/** +/* * Call this function every time you're about to start processing a new file. * Any pr_op_err()s and friends will now include the new file name. * Use fnstack_pop() to revert back to the previously stacked file name. @@ -156,12 +156,7 @@ fnstack_push(char const *file) files->filenames[files->len++] = file; } -/** - * See fnstack_push(). - * - * This function cannot claim a reference for @map, so @map will have to outlive - * the push/pop. - */ +/* See fnstack_push(). @map needs to outlive the push/pop. */ void fnstack_push_map(struct cache_mapping *map) { @@ -201,7 +196,7 @@ addr2str(int af, void const *addr, char *(*buffer_cb)(struct validation *)) return inet_ntop(af, addr, buffer_cb(state), INET6_ADDRSTRLEN); } -/** +/* * Returns @addr, converted to a printable string. Intended for minimal clutter * address printing. * @@ -217,27 +212,21 @@ v4addr2str(struct in_addr const *addr) return addr2str(AF_INET, addr, validation_get_ip_buffer1); } -/** - * Same as v4addr2str(), except a different buffer is used. - */ +/* Same as v4addr2str(), except a different buffer is used. */ char const * v4addr2str2(struct in_addr const *addr) { return addr2str(AF_INET, addr, validation_get_ip_buffer2); } -/** - * See v4addr2str(). - */ +/* See v4addr2str(). */ char const * v6addr2str(struct in6_addr const *addr) { return addr2str(AF_INET6, addr, validation_get_ip_buffer1); } -/** - * See v4addr2str2(). - */ +/* See v4addr2str2(). */ char const * v6addr2str2(struct in6_addr const *addr) { diff --git a/src/types/map.c b/src/types/map.c index d23484e6..3f0ea814 100644 --- a/src/types/map.c +++ b/src/types/map.c @@ -59,6 +59,13 @@ map_child(struct cache_mapping *parent, char const *name) return child; } +void +map_copy(struct cache_mapping *dst, struct cache_mapping *src) +{ + dst->url = pstrdup(src->url); + dst->path = pstrdup(src->path); +} + void map_cleanup(struct cache_mapping *map) { diff --git a/src/types/map.h b/src/types/map.h index e678fa5b..c35b27ff 100644 --- a/src/types/map.h +++ b/src/types/map.h @@ -15,6 +15,7 @@ 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_copy(struct cache_mapping *, struct cache_mapping *); void map_cleanup(struct cache_mapping *); #endif /* SRC_TYPES_MAP_H_ */ diff --git a/test/Makefile.am b/test/Makefile.am index cf836420..54a04640 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -96,7 +96,7 @@ rsync_test_LDADD = ${MY_LDADD} serial_test_SOURCES = types/serial_test.c serial_test_LDADD = ${MY_LDADD} -tal_test_SOURCES = tal_test.c +tal_test_SOURCES = object/tal_test.c tal_test_LDADD = ${MY_LDADD} thread_pool_test_SOURCES = thread_pool_test.c diff --git a/test/cache_test.c b/test/cache_test.c index 21fdfda9..232f1375 100644 --- a/test/cache_test.c +++ b/test/cache_test.c @@ -40,6 +40,7 @@ rsync_download(char const *src, char const *dst, char const *cmpdir) MOCK_ABORT_INT(rrdp_update, struct cache_node *notif) __MOCK_ABORT(rrdp_notif2json, json_t *, NULL, struct cachefile_notification *notif) +MOCK_ABORT_VOID(rrdp_notif_cleanup, struct cachefile_notification *notif) MOCK_VOID(rrdp_notif_free, struct cachefile_notification *notif) MOCK_ABORT_INT(rrdp_json2notif, json_t *json, struct cachefile_notification **result) MOCK_VOID(__delete_node_cb, struct cache_node const *node) diff --git a/test/cachent_test.c b/test/cachent_test.c index 1f821d33..3d371660 100644 --- a/test/cachent_test.c +++ b/test/cachent_test.c @@ -10,6 +10,8 @@ static char deleted[16][6]; static unsigned int dn; +MOCK_ABORT_VOID(rrdp_notif_cleanup, struct cachefile_notification *notif) + static void __delete_node_cb(struct cache_node const *node) { diff --git a/test/mock.c b/test/mock.c index e3e87174..44c70736 100644 --- a/test/mock.c +++ b/test/mock.c @@ -7,9 +7,7 @@ #include "state.h" #include "thread_var.h" -/** - * Some core functions, as linked from unit tests. - */ +/* Some core functions, as linked from unit tests. */ MOCK_TRUE(log_val_enabled, unsigned int l) MOCK_TRUE(log_op_enabled, unsigned int l) @@ -123,6 +121,8 @@ MOCK_NULL(config_get_output_bgpsec, char const *, void) MOCK(config_get_op_log_filename_format, enum filename_format, FNF_NAME, void) MOCK(config_get_val_log_filename_format, enum filename_format, FNF_NAME, void) +MOCK_VOID(fnstack_init, void) MOCK_VOID(fnstack_push, char const *file) MOCK_VOID(fnstack_push_map, struct cache_mapping *map) MOCK_VOID(fnstack_pop, void) +MOCK_VOID(fnstack_cleanup, void) diff --git a/test/object/manifest_test.c b/test/object/manifest_test.c index 823efdcd..a73b86f8 100644 --- a/test/object/manifest_test.c +++ b/test/object/manifest_test.c @@ -10,6 +10,7 @@ #include "types/path.c" #include "types/url.c" +MOCK_ABORT_VOID(rrdp_notif_cleanup, struct cachefile_notification *notif) MOCK_ABORT_INT(signed_object_decode, struct signed_object *sobj, char const *path) MOCK_ABORT_VOID(signed_object_cleanup, struct signed_object *sobj) MOCK_VOID(__delete_node_cb, struct cache_node const *node) diff --git a/test/tal_test.c b/test/object/tal_test.c similarity index 93% rename from test/tal_test.c rename to test/object/tal_test.c index a64ac582..bf11db66 100644 --- a/test/tal_test.c +++ b/test/object/tal_test.c @@ -13,15 +13,8 @@ /* Mocks */ -MOCK_ABORT_VOID(cache_setup, void) -MOCK(cache_create, struct rpki_cache *, NULL, void) -MOCK_VOID(cache_destroy, struct rpki_cache *cache) -MOCK_ABORT_INT(cache_download_alt, struct sia_uris *sias, - validate_cb cb, void *arg) -MOCK_ABORT_INT(cache_tmpfile, char **filename) -MOCK_ABORT_VOID(cache_teardown, void) -MOCK_ABORT_INT(certificate_traverse, struct rpp *rpp_parent, - struct cache_mapping *cert_map) +MOCK_ABORT_VOID(cache_prepare, void) +MOCK_ABORT_VOID(cache_commit, void) MOCK_ABORT_PTR(db_table_create, db_table, void) MOCK_VOID(db_table_destroy, struct db_table *table) MOCK_ABORT_INT(db_table_join, struct db_table *dst, struct db_table *src) @@ -129,6 +122,7 @@ START_TEST(test_tal_load_4urls) test_4urls("resources/tal/4urls-crlf.tal"); test_4urls("resources/tal/4urls-lf-comment.tal"); test_4urls("resources/tal/4urls-lf-comment-utf8.tal"); + test_4urls("resources/tal/4urls-ignored-protos.tal"); } END_TEST diff --git a/test/resources/tal/4urls-ignored-protos.tal b/test/resources/tal/4urls-ignored-protos.tal new file mode 100644 index 00000000..eb7122bb --- /dev/null +++ b/test/resources/tal/4urls-ignored-protos.tal @@ -0,0 +1,14 @@ +rsync://example.com/rpki/ta.cer +https://example.com/rpki/ta.cer +ftp://example.com/rpki/ta.cer +rsync://www.example.com/potato/ta.cer +http://example.com/rpki/ta.cer +https://wx3.example.com/tomato/ta.cer + +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqZEzhYK0+PtDOPfub/KR +c3MeWx3neXx4/wbnJWGbNAtbYqXg3uU5J4HFzPgk/VIppgSKAhlO0H60DRP48by9 +gr5/yDHu2KXhOmnMg46sYsUIpfgtBS9+VtrqWziJfb+pkGtuOWeTnj6zBmBNZKK+ +5AlMCW1WPhrylIcB+XSZx8tk9GS/3SMQ+YfMVwwAyYjsex14Uzto4GjONALE5oh1 +M3+glRQduD6vzSwOD+WahMbc9vCOTED+2McLHRKgNaQf0YJ9a1jG9oJIvDkKXEqd +fqDRktwyoD74cV57bW3tBAexB7GglITbInyQAsmdngtfg2LUMrcROHHP86QPZINj +DQIDAQAB -- 2.47.3