From 74f8607ea6e8b5f8a41738f6e653391a47aecaa5 Mon Sep 17 00:00:00 2001 From: Alberto Leiva Popper Date: Thu, 1 Aug 2024 18:05:44 -0600 Subject: [PATCH] Thursday --- src/cache.c | 56 ++--- src/cache.h | 10 +- src/cachent.c | 14 +- src/cachent.h | 2 +- src/cert_stack.c | 11 +- src/cert_stack.h | 2 +- src/certificate_refs.c | 23 +- src/certificate_refs.h | 2 +- src/common.c | 32 +-- src/common.h | 7 +- src/object/certificate.c | 36 ++-- src/object/ghostbusters.c | 4 +- src/object/manifest.c | 229 ++++++++++---------- src/object/manifest.h | 3 +- src/object/roa.c | 4 +- src/object/roa.h | 1 - src/object/signed_object.c | 4 +- src/object/signed_object.h | 2 +- src/object/tal.c | 34 ++- src/rpp.c | 89 ++++---- src/rpp.h | 12 +- src/rrdp.c | 2 +- src/rtr/db/vrps.c | 14 +- src/slurm/db_slurm.c | 6 +- src/thread_var.h | 1 + src/types/map.c | 385 +--------------------------------- src/types/map.h | 59 ++---- src/types/str.h | 3 +- src/types/url.c | 68 +++++- test/Makefile.am | 6 +- test/base64_test.c | 1 + test/cache_test.c | 408 ++++++++++++++++++------------------ test/cache_util.c | 30 +-- test/cache_util.h | 15 +- test/cachent_test.c | 124 +++++------ test/mock.c | 4 + test/object/manifest_test.c | 98 +++++++++ test/rrdp_test.c | 2 - test/rrdp_update_test.c | 18 +- test/tal_test.c | 11 +- test/types/map_test.c | 234 --------------------- test/types/url_test.c | 17 +- 42 files changed, 759 insertions(+), 1324 deletions(-) create mode 100644 test/object/manifest_test.c delete mode 100644 test/types/map_test.c diff --git a/src/cache.c b/src/cache.c index d955b53c..6713860f 100644 --- a/src/cache.c +++ b/src/cache.c @@ -10,6 +10,7 @@ #include #include "alloc.h" +#include "cachent.h" #include "cachetmp.h" #include "common.h" #include "config.h" @@ -513,7 +514,7 @@ dl_rsync(struct cache_node *rpp) } module->flags |= CNF_RSYNC | CNF_CACHED | CNF_FRESH; - module->mtim = time(NULL); // XXX catch -1 + module->mtim = time_nonfatal(); module->tmppath = tmppath; for (node = rpp; node != module; node = node->parent) { @@ -541,7 +542,7 @@ dl_http(struct cache_node *node) if (error) return error; - mtim = time(NULL); // XXX + mtim = time_nonfatal(); error = http_download(node->url, tmppath, node->mtim, &changed); if (error) { @@ -559,9 +560,10 @@ dl_http(struct cache_node *node) /* @uri is either a caRepository or a rpkiNotify */ static int try_uri(char const *uri, struct cache_node *root, - dl_cb download, maps_dl_cb validate, void *arg) + dl_cb download, validate_cb validate, void *arg) { struct cache_node *rpp; + struct cache_mapping map; int error; if (!uri) @@ -585,19 +587,23 @@ try_uri(char const *uri, struct cache_node *root, } } - error = validate(rpp, arg); + map.url = rpp->url; + map.path = rpp->path; + map.tmppath = rpp->tmppath; + error = validate(&map, arg); if (error) { pr_val_debug("RPP validation failed."); return error; } pr_val_debug("RPP validated successfully."); + rpp->flags |= CNF_VALID; return 0; } static int try_uris(struct strlist *uris, struct cache_node *root, - char const *prefix, dl_cb dl, maps_dl_cb cb, void *arg) + char const *prefix, dl_cb dl, validate_cb cb, void *arg) { char **str; int error; @@ -613,7 +619,7 @@ try_uris(struct strlist *uris, struct cache_node *root, } int -cache_download_uri(struct strlist *uris, maps_dl_cb cb, void *arg) +cache_download_uri(struct strlist *uris, validate_cb cb, void *arg) { int error; @@ -649,7 +655,7 @@ cache_download_uri(struct strlist *uris, maps_dl_cb cb, void *arg) * that's already cached, and callbacks it. */ int -cache_download_alt(struct sia_uris *sias, maps_dl_cb cb, void *arg) +cache_download_alt(struct sia_uris *sias, validate_cb cb, void *arg) { int error; @@ -695,10 +701,6 @@ prune_rsync(void) } } -/* - * XXX this needs to be hit only by files now - * XXX result is redundant - */ static bool commit_rpp_delta(struct cache_node *node) { @@ -748,38 +750,6 @@ branch: node->flags = 0; return true; } -//static bool -//is_node_fresh(struct cache_node *node, time_t epoch) -//{ -// /* TODO This is a startup; probably complicate this. */ -// return difftime(epoch, node->attempt.ts) < 0; -//} -// -//static void -//delete_node(struct rpki_cache *cache, struct cache_node *node) -//{ -// HASH_DEL(cache->ht, node); -// map_refput(node->map); -// rrdp_notif_free(node->notif); -// free(node); -//} -// -//static void -//delete_node_and_cage(struct rpki_cache *cache, struct cache_node *node) -//{ -// struct cache_mapping *cage; -// -// if (map_get_type(node->map) == MAP_NOTIF) { -// if (map_create_cage(&cage, node->map) == 0) { -// pr_op_debug("Deleting cage %s.", map_get_path(cage)); -// file_rm_rf(map_get_path(cage)); -// map_refput(cage); -// } -// } -// -// delete_node(cache, node); -//} - static int rmf(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { diff --git a/src/cache.h b/src/cache.h index 213fa8bb..8fcf64dc 100644 --- a/src/cache.h +++ b/src/cache.h @@ -1,7 +1,7 @@ #ifndef SRC_CACHE_LOCAL_CACHE_H_ #define SRC_CACHE_LOCAL_CACHE_H_ -#include "cachent.h" +#include "types/map.h" #include "types/str.h" void cache_setup(void); /* Init this module */ @@ -26,12 +26,10 @@ void sias_cleanup(struct sia_uris *); * - 0 on success ("Mapping handled successfully") * - > 0 on soft errors ("Try another mapping") * - < 0 on hard errors ("Abandon foreach") - * - * XXX rename */ -typedef int (*maps_dl_cb)(struct cache_node *rpp, void *arg); -int cache_download_uri(struct strlist *, maps_dl_cb, void *); -int cache_download_alt(struct sia_uris *, maps_dl_cb, void *); +typedef int (*validate_cb)(struct cache_mapping *, void *); +int cache_download_uri(struct strlist *, validate_cb, void *); +int cache_download_alt(struct sia_uris *, validate_cb, void *); void cache_print(void); /* Dump cache in stdout. Recursive; tests only */ diff --git a/src/cachent.c b/src/cachent.c index 44b252e4..af68790b 100644 --- a/src/cachent.c +++ b/src/cachent.c @@ -34,24 +34,23 @@ cachent_root_https(void) } /* Preorder. @cb returns whether the children should be traversed. */ -int +void cachent_traverse(struct cache_node *root, bool (*cb)(struct cache_node *)) { struct cache_node *iter_start; struct cache_node *parent, *child; struct cache_node *tmp; - int error; if (!root) - return 0; + return; if (!cb(root)) - return error; + return; parent = root; iter_start = parent->children; if (iter_start == NULL) - return error; + return; reloop: /* iter_start must not be NULL */ HASH_ITER(hh, iter_start, child, tmp) { @@ -65,7 +64,7 @@ reloop: /* iter_start must not be NULL */ parent = iter_start->parent; do { if (parent == NULL) - return error; + return; iter_start = parent->hh.next; parent = parent->parent; } while (iter_start == NULL); @@ -167,7 +166,8 @@ provide(struct cache_node *parent, char const *url, * anything that is not @ancestor or one of its descendants. (ie. dot-dotting is * allowed, but the end result must not land outside of @ancestor.) * - * XXX review callers; can now return NULL. + * XXX In the end, it seems this is only being used by root ancestors. + * Should probably separate the caging to a simple get. */ struct cache_node * cachent_provide(struct cache_node *ancestor, char const *url) diff --git a/src/cachent.h b/src/cachent.h index 97143c9d..397fd97f 100644 --- a/src/cachent.h +++ b/src/cachent.h @@ -77,7 +77,7 @@ struct cache_node { struct cache_node *cachent_root_rsync(void); struct cache_node *cachent_root_https(void); -int cachent_traverse(struct cache_node *, bool (*cb)(struct cache_node *)); +void cachent_traverse(struct cache_node *, bool (*cb)(struct cache_node *)); struct cache_node *cachent_find(struct cache_node *, char const *, struct cache_node **); diff --git a/src/cert_stack.c b/src/cert_stack.c index 2eb9e467..a9186b48 100644 --- a/src/cert_stack.c +++ b/src/cert_stack.c @@ -42,7 +42,7 @@ STATIC_ARRAY_LIST(serial_numbers, struct serial_number) * Cached certificate data. */ struct metadata_node { - struct cache_mapping *map; + struct cache_mapping map; struct resources *resources; /* * Serial numbers of the children. @@ -121,7 +121,6 @@ defer_destroy(struct defer_node *defer) case DNT_SEPARATOR: break; case DNT_CERT: - map_refput(defer->deferred.map); rpp_refput(defer->deferred.pp); break; } @@ -139,7 +138,6 @@ serial_cleanup(struct serial_number *serial) static void meta_destroy(struct metadata_node *meta) { - map_refput(meta->map); resources_destroy(meta->resources); serial_numbers_cleanup(&meta->serials, serial_cleanup); free(meta); @@ -185,7 +183,6 @@ deferstack_push(struct cert_stack *stack, struct deferred_cert *deferred) node->type = DNT_CERT; node->deferred = *deferred; - map_refget(deferred->map); rpp_refget(deferred->pp); SLIST_INSERT_HEAD(&stack->defers, node, next); } @@ -229,7 +226,6 @@ again: node = SLIST_FIRST(&stack->defers); } *result = node->deferred; - map_refget(node->deferred.map); rpp_refget(node->deferred.pp); SLIST_REMOVE_HEAD(&stack->defers, next); @@ -299,7 +295,7 @@ x509stack_push(struct cert_stack *stack, struct cache_mapping *map, X509 *x509, meta = pmalloc(sizeof(struct metadata_node)); - meta->map = map_refget(map); + meta->map = *map; serial_numbers_init(&meta->serials); error = init_resources(x509, policy, type, &meta->resources); @@ -325,7 +321,6 @@ destroy_separator: resources_destroy(meta->resources); cleanup_serial: serial_numbers_cleanup(&meta->serials, serial_cleanup); - map_refput(meta->map); free(meta); return error; } @@ -362,7 +357,7 @@ struct cache_mapping * x509stack_peek_map(struct cert_stack *stack) { struct metadata_node *meta = SLIST_FIRST(&stack->metas); - return (meta != NULL) ? meta->map : NULL; + return (meta != NULL) ? &meta->map : NULL; } struct resources * diff --git a/src/cert_stack.h b/src/cert_stack.h index b9c9e248..3d938148 100644 --- a/src/cert_stack.h +++ b/src/cert_stack.h @@ -31,7 +31,7 @@ struct cert_stack; struct deferred_cert { - struct cache_mapping *map; + struct cache_mapping map; struct rpp *pp; }; diff --git a/src/certificate_refs.c b/src/certificate_refs.c index c63cf8e5..b94f6d31 100644 --- a/src/certificate_refs.c +++ b/src/certificate_refs.c @@ -22,34 +22,33 @@ refs_cleanup(struct certificate_refs *refs) static int validate_cdp(struct certificate_refs *refs, struct rpp const *pp) { - struct cache_mapping *pp_crl; + char const *crl_url; if (refs->crldp == NULL) pr_crit("Certificate's CRL Distribution Point was not recorded."); - pp_crl = rpp_get_crl(pp); - if (pp_crl == NULL) + crl_url = rpp_get_crl(pp); + if (crl_url == NULL) pr_crit("Manifest's CRL was not recorded."); - if (strcmp(refs->crldp, map_get_url(pp_crl)) != 0) { + if (strcmp(refs->crldp, crl_url) != 0) { return pr_val_err("Certificate's CRL Distribution Point ('%s') does not match manifest's CRL ('%s').", - refs->crldp, map_get_url(pp_crl)); + refs->crldp, crl_url); } return 0; } static int -validate_signedObject(struct certificate_refs *refs, - struct cache_mapping *signedObject_map) +validate_signedObject(struct certificate_refs *refs, char const *url) { if (refs->signedObject == NULL) pr_crit("Certificate's signedObject was not recorded."); /* XXX the left one is no longer normalized */ - if (strcmp(refs->signedObject, map_get_url(signedObject_map)) != 0) { + if (strcmp(refs->signedObject, url) != 0) { return pr_val_err("Certificate's signedObject ('%s') does not match the URI of its own signed object (%s).", - refs->signedObject, map_get_url(signedObject_map)); + refs->signedObject, url); } return 0; @@ -84,11 +83,11 @@ refs_validate_ca(struct certificate_refs *refs, struct rpp const *pp) * * @refs: References you want validated. * @pp: Repository Publication Point, as described by the Manifest. - * @map: Mapping of the signed object that contains the EE certificate. + * @url: URL of the signed object that contains the EE certificate. */ int refs_validate_ee(struct certificate_refs *refs, struct rpp const *pp, - struct cache_mapping *map) + char const *url) { int error; @@ -96,5 +95,5 @@ refs_validate_ee(struct certificate_refs *refs, struct rpp const *pp, if (error) return error; - return validate_signedObject(refs, map); + return validate_signedObject(refs, url); } diff --git a/src/certificate_refs.h b/src/certificate_refs.h index 009f4f91..841ba94b 100644 --- a/src/certificate_refs.h +++ b/src/certificate_refs.h @@ -40,6 +40,6 @@ void refs_init(struct certificate_refs *); void refs_cleanup(struct certificate_refs *); int refs_validate_ca(struct certificate_refs *, struct rpp const *); int refs_validate_ee(struct certificate_refs *, struct rpp const *, - struct cache_mapping *); + char const *); #endif /* SRC_CERTIFICATE_REFS_H_ */ diff --git a/src/common.c b/src/common.c index 6aee1b82..ace62b54 100644 --- a/src/common.c +++ b/src/common.c @@ -383,20 +383,28 @@ release_str: return error; } -int -get_current_time(time_t *result) +time_t +time_nonfatal(void) { - time_t now; - int error; + time_t result; - now = time(NULL); - if (now == ((time_t) -1)) { - error = errno; - pr_val_err("Error getting the current time: %s", - strerror(errno)); - return error; + result = time(NULL); + if (result == ((time_t)-1)) { + pr_val_warn("time(NULL) returned -1: %s", strerror(errno)); + result = 0; } - *result = now; - return 0; + return result; +} + +time_t +time_fatal(void) +{ + time_t result; + + result = time(NULL); + if (result == ((time_t)-1)) + pr_crit("time(NULL) returned -1: %s", strerror(errno)); + + return result; } diff --git a/src/common.h b/src/common.h index 190b04c7..eff5ee24 100644 --- a/src/common.h +++ b/src/common.h @@ -10,10 +10,6 @@ #define ENOTSUPPORTED 3172 /* "I haven't implemented this yet." */ #define ENOTIMPLEMENTED 3173 -/* "URI was not RSYNC." */ -#define ENOTRSYNC 3174 -/* "URI was not HTTPS." */ -#define ENOTHTTPS 3175 /* * If you're wondering why I'm not using -abs(error), it's because abs(INT_MIN) @@ -52,6 +48,7 @@ bool valid_file_or_dir(char const *, bool); int mkdir_p(char const *, bool, mode_t); int delete_dir_recursive_bottom_up(char const *); -int get_current_time(time_t *); +time_t time_nonfatal(void); +time_t time_fatal(void); #endif /* SRC_RTR_COMMON_H_ */ diff --git a/src/object/certificate.c b/src/object/certificate.c index 06a21cbc..072032ed 100644 --- a/src/object/certificate.c +++ b/src/object/certificate.c @@ -793,7 +793,7 @@ certificate_load(struct cache_mapping *map, X509 **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) { + if (BIO_read_filename(bio, map->path) <= 0) { error = val_crypto_err("Error reading certificate"); goto end; } @@ -821,12 +821,6 @@ update_crl_time(STACK_OF(X509_CRL) *crls, X509_CRL *original_crl) { ASN1_TIME *tm; X509_CRL *clone; - time_t t; - int error; - - error = get_current_time(&t); - if (error) - return error; /* * Yes, this is an awful hack. The other options were: @@ -837,7 +831,7 @@ update_crl_time(STACK_OF(X509_CRL) *crls, X509_CRL *original_crl) * only the nextUpdate field wrong (maybe there are other invalid * things). */ - tm = ASN1_TIME_adj(NULL, t, 0, 60); + tm = ASN1_TIME_adj(NULL, time_fatal(), 0, 60); if (tm == NULL) return val_crypto_err("ASN1_TIME_adj() returned NULL."); @@ -850,8 +844,7 @@ update_crl_time(STACK_OF(X509_CRL) *crls, X509_CRL *original_crl) X509_CRL_set1_nextUpdate(clone, tm); ASN1_STRING_free(tm); - error = sk_X509_CRL_push(crls, clone); - if (error <= 0) { + if (sk_X509_CRL_push(crls, clone) <= 0) { X509_CRL_free(clone); return val_crypto_err("Error calling sk_X509_CRL_push()"); } @@ -1813,7 +1806,7 @@ 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 *cert; + X509 *x509; struct sia_uris sia_uris; enum rpki_policy policy; enum cert_type certype; @@ -1833,7 +1826,6 @@ certificate_traverse(struct rpp *rpp_parent, struct cache_mapping *cert_map) else pr_val_debug("Certificate '%s' {", map_val_get_printable(cert_map)); - fnstack_push_map(cert_map); error = rpp_crl(rpp_parent, &rpp_parent_crl); @@ -1841,14 +1833,14 @@ certificate_traverse(struct rpp *rpp_parent, struct cache_mapping *cert_map) goto revert_fnstack_and_debug; /* -- Validate the certificate (@cert) -- */ - error = certificate_load(cert_map, &cert); + error = certificate_load(cert_map, &x509); if (error) goto revert_fnstack_and_debug; - error = certificate_validate_chain(cert, rpp_parent_crl); + error = certificate_validate_chain(x509, rpp_parent_crl); if (error) goto revert_cert; - error = get_certificate_type(cert, rpp_parent == NULL, &certype); + error = get_certificate_type(x509, rpp_parent == NULL, &certype); if (error) goto revert_cert; @@ -1869,14 +1861,14 @@ certificate_traverse(struct rpp *rpp_parent, struct cache_mapping *cert_map) goto revert_cert; } - error = certificate_validate_rfc6487(cert, certype); + error = certificate_validate_rfc6487(x509, certype); if (error) goto revert_cert; sias_init(&sia_uris); error = (certype == CERTYPE_TA) - ? certificate_validate_extensions_ta(cert, &sia_uris, &policy) - : certificate_validate_extensions_ca(cert, &sia_uris, &policy, + ? certificate_validate_extensions_ta(x509, &sia_uris, &policy) + : certificate_validate_extensions_ca(x509, &sia_uris, &policy, rpp_parent); if (error) goto revert_uris; @@ -1885,11 +1877,11 @@ certificate_traverse(struct rpp *rpp_parent, struct cache_mapping *cert_map) if (error) goto revert_uris; - error = x509stack_push(validation_certstack(state), cert_map, cert, + error = x509stack_push(validation_certstack(state), cert_map, x509, policy, certype); if (error) goto revert_uris; - cert = NULL; /* Ownership stolen */ + x509 = NULL; /* Ownership stolen */ error = handle_manifest(sia_uris.rpkiManifest, &pp); if (error) { @@ -1904,8 +1896,8 @@ certificate_traverse(struct rpp *rpp_parent, struct cache_mapping *cert_map) revert_uris: sias_cleanup(&sia_uris); revert_cert: - if (cert != NULL) - X509_free(cert); + if (x509 != NULL) + X509_free(x509); revert_fnstack_and_debug: fnstack_pop(); pr_val_debug("}"); diff --git a/src/object/ghostbusters.c b/src/object/ghostbusters.c index ec8ec64c..bb47c8e8 100644 --- a/src/object/ghostbusters.c +++ b/src/object/ghostbusters.c @@ -29,7 +29,7 @@ ghostbusters_traverse(struct cache_mapping *map, struct rpp *pp) fnstack_push_map(map); /* Decode */ - error = signed_object_decode(&sobj, map); + error = signed_object_decode(&sobj, map->path); if (error) goto revert_log; @@ -46,7 +46,7 @@ ghostbusters_traverse(struct cache_mapping *map, struct rpp *pp) error = handle_vcard(&sobj); if (error) goto revert_args; - error = refs_validate_ee(&ee.refs, pp, map); + error = refs_validate_ee(&ee.refs, pp, map->url); revert_args: eecert_cleanup(&ee); diff --git a/src/object/manifest.c b/src/object/manifest.c index a47afe5f..0afaf618 100644 --- a/src/object/manifest.c +++ b/src/object/manifest.c @@ -78,10 +78,7 @@ validate_dates(GeneralizedTime_t *this, GeneralizedTime_t *next) TM_ARGS(nextUpdate)); } - now_tt = 0; - error = get_current_time(&now_tt); - if (error) - return error; + now_tt = time_fatal(); if (gmtime_r(&now_tt, &now) == NULL) { error = errno; return pr_val_err("gmtime_r(now) error %d: %s", error, @@ -211,74 +208,74 @@ validate_mft_file(IA5String_t *ia5) 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; -} +///** +// * 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 build_rpp(struct Manifest *mft, char const *mft_url, struct rpp **pp) { - char *path, *slash; - size_t path_len; + char *rpp_url, *slash; + size_t rpp_url_len; int i; struct FileAndHash *fah; - char *file; - size_t file_len; + char *file_url; + size_t file_url_len; int written; - struct cache_mapping *map; + char const *extension; int error; *pp = rpp_create(); @@ -286,8 +283,8 @@ build_rpp(struct Manifest *mft, char const *mft_url, struct rpp **pp) slash = strrchr(mft_url, '/'); if (!slash) ; // XXX - path_len = slash - mft_url; - path = pstrndup(mft_url, path_len); + rpp_url_len = slash - mft_url; + rpp_url = pstrndup(mft_url, rpp_url_len); for (i = 0; i < mft->fileList.list.count; i++) { fah = mft->fileList.list.array[i]; @@ -302,54 +299,50 @@ build_rpp(struct Manifest *mft, char const *mft_url, struct rpp **pp) if (error) ; // XXX - file_len = path_len + fah->file.size + 2; - file = pmalloc(file_len); - written = snprintf(file, file_len, "%s/%.*s", path, + 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_len) - ; // XXX - - map = create_map(file); /* Needs to swallow @file. */ - if (!map) + 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) { - map_refput(map); - goto fail; - } - if (error > 0) { - map_refput(map); - continue; - } - - if (map_has_extension(map, ".cer")) - rpp_add_cert(*pp, map); - else if (map_has_extension(map, ".roa")) - rpp_add_roa(*pp, map); - else if (map_has_extension(map, ".crl")) - error = rpp_add_crl(*pp, map); - else if (map_has_extension(map, ".gbr")) - rpp_add_ghostbusters(*pp, map); +// /* +// * 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 - map_refput(map); /* ignore it. */ - - if (error) { - map_refput(map); - goto fail; - } /* Otherwise ownership was transferred to @pp. */ + free(file_url); /* ignore it. */ } /* rfc6486#section-7 */ @@ -370,9 +363,8 @@ fail: * @pp. */ int -handle_manifest(char const *uri, struct rpp **pp) +handle_manifest(struct cache_mapping *map, struct rpp **pp) { - struct cache_mapping *map; static OID oid = OID_MANIFEST; struct oid_arcs arcs = OID2ARCS("manifest", oid); struct signed_object sobj; @@ -381,16 +373,12 @@ handle_manifest(char const *uri, struct rpp **pp) STACK_OF(X509_CRL) *crl; int error; - map = create_map(uri); - if (!map) - return -EINVAL; /* XXX msg */ - /* Prepare */ pr_val_debug("Manifest '%s' {", map_val_get_printable(map)); fnstack_push_map(map); /* Decode */ - error = signed_object_decode(&sobj, map); + error = signed_object_decode(&sobj, map->path); if (error) goto revert_log; error = decode_manifest(&sobj, &mft); @@ -398,7 +386,7 @@ handle_manifest(char const *uri, struct rpp **pp) goto revert_sobj; /* Initialize out parameter (@pp) */ - error = build_rpp(mft, uri, pp); + error = build_rpp(mft, map->url, pp); if (error) goto revert_manifest; @@ -415,7 +403,7 @@ handle_manifest(char const *uri, struct rpp **pp) error = validate_manifest(mft); if (error) goto revert_args; - error = refs_validate_ee(&ee.refs, *pp, map); + error = refs_validate_ee(&ee.refs, *pp, map->url); if (error) goto revert_args; @@ -434,6 +422,5 @@ revert_sobj: revert_log: pr_val_debug("}"); fnstack_pop(); - map_refput(map); return error; } diff --git a/src/object/manifest.h b/src/object/manifest.h index 24d7c17d..402813ad 100644 --- a/src/object/manifest.h +++ b/src/object/manifest.h @@ -2,7 +2,8 @@ #define SRC_OBJECT_MANIFEST_H_ #include "rpp.h" +#include "types/map.h" -int handle_manifest(char const *, struct rpp **); +int handle_manifest(struct cache_mapping *map, struct rpp **); #endif /* SRC_OBJECT_MANIFEST_H_ */ diff --git a/src/object/roa.c b/src/object/roa.c index 63b810d2..7d495a50 100644 --- a/src/object/roa.c +++ b/src/object/roa.c @@ -262,7 +262,7 @@ roa_traverse(struct cache_mapping *map, struct rpp *pp) fnstack_push_map(map); /* Decode */ - error = signed_object_decode(&sobj, map); + error = signed_object_decode(&sobj, map->path); if (error) goto revert_log; error = decode_roa(&sobj, &roa); @@ -282,7 +282,7 @@ roa_traverse(struct cache_mapping *map, struct rpp *pp) error = __handle_roa(roa, ee.res); if (error) goto revert_args; - error = refs_validate_ee(&ee.refs, pp, map); + error = refs_validate_ee(&ee.refs, pp, map->url); revert_args: eecert_cleanup(&ee); diff --git a/src/object/roa.h b/src/object/roa.h index 31093005..497f9c47 100644 --- a/src/object/roa.h +++ b/src/object/roa.h @@ -2,7 +2,6 @@ #define SRC_OBJECT_ROA_H_ #include "rpp.h" -#include "types/address.h" #include "types/map.h" int roa_traverse(struct cache_mapping *, struct rpp *); diff --git a/src/object/signed_object.c b/src/object/signed_object.c index cb80aa81..f6c11fef 100644 --- a/src/object/signed_object.c +++ b/src/object/signed_object.c @@ -4,11 +4,11 @@ #include "log.h" int -signed_object_decode(struct signed_object *sobj, struct cache_mapping *map) +signed_object_decode(struct signed_object *sobj, char const *path) { int error; - error = content_info_load(map_get_path(map), &sobj->cinfo); + error = content_info_load(path, &sobj->cinfo); if (error) return error; diff --git a/src/object/signed_object.h b/src/object/signed_object.h index e6c2aba9..d148e063 100644 --- a/src/object/signed_object.h +++ b/src/object/signed_object.h @@ -9,7 +9,7 @@ struct signed_object { struct SignedData *sdata; }; -int signed_object_decode(struct signed_object *, struct cache_mapping *); +int signed_object_decode(struct signed_object *, char const *); int signed_object_validate(struct signed_object *, struct oid_arcs const *, struct ee_cert *); void signed_object_cleanup(struct signed_object *); diff --git a/src/object/tal.c b/src/object/tal.c index 81e827c8..d5f3ee6a 100644 --- a/src/object/tal.c +++ b/src/object/tal.c @@ -21,8 +21,6 @@ #include "types/str.h" #include "validation_handler.h" -typedef int (*foreach_map_cb)(struct tal *, struct cache_mapping *, void *); - struct tal { char const *file_name; struct strlist urls; @@ -164,38 +162,39 @@ tal_get_spki(struct tal *tal, unsigned char const **buffer, size_t *len) } /** - * Performs the whole validation walkthrough on the @map mapping, which is - * assumed to have been extracted from TAL @tal. + * Performs the whole validation walkthrough that starts with Trust Anchor @ta, + * which is assumed to have been extracted from TAL @arg->tal. */ static int -handle_tal_map(struct tal *tal, struct cache_mapping *map, struct db_table *db) +handle_ta(struct cache_mapping *ta, void *arg) { + struct handle_tal_args *args = arg; struct validation_handler validation_handler; struct validation *state; struct cert_stack *certstack; struct deferred_cert deferred; int error; - pr_val_debug("TAL URI '%s' {", map_val_get_printable(map)); + 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; - validation_handler.arg = db; + validation_handler.arg = args->db; - error = validation_prepare(&state, tal, &validation_handler); + error = validation_prepare(&state, &args->tal, &validation_handler); if (error) return ENSURE_NEGATIVE(error); - if (!map_has_extension(map, ".cer")) { + if (!str_ends_with(ta->url, ".cer")) { pr_op_err("TAL URI does not point to a certificate. (Expected .cer, got '%s')", - map_op_get_printable(map)); + ta->url); error = EINVAL; goto end; } /* Handle root certificate. */ - error = certificate_traverse(NULL, map); + error = certificate_traverse(NULL, ta); if (error) { switch (validation_pubkey_state(state)) { case PKS_INVALID: @@ -233,9 +232,8 @@ handle_tal_map(struct tal *tal, struct cache_mapping *map, struct db_table *db) * Ignore result code; remaining certificates are unrelated, * so they should not be affected. */ - certificate_traverse(deferred.pp, deferred.map); + certificate_traverse(deferred.pp, &deferred.map); - map_refput(deferred.map); rpp_refput(deferred.pp); } while (true); @@ -244,13 +242,6 @@ end: validation_destroy(state); return error; } -static int -__handle_tal_map(struct cache_mapping *map, void *arg) -{ - struct handle_tal_args *args = arg; - return handle_tal_map(&args->tal, map, args->db); -} - static void * do_file_validation(void *arg) { @@ -268,8 +259,7 @@ do_file_validation(void *arg) goto end; args.db = db_table_create(); - thread->error = cache_download_uri(&args.tal.urls, - __handle_tal_map, &args); + 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); diff --git a/src/rpp.c b/src/rpp.c index e165bb0d..59a12287 100644 --- a/src/rpp.c +++ b/src/rpp.c @@ -8,20 +8,19 @@ #include "object/ghostbusters.h" #include "object/roa.h" #include "thread_var.h" -#include "types/arraylist.h" -#include "types/map.h" +#include "types/str.h" -/** A Repository Publication Point (RFC 6481), as described by some manifest. */ +/* A Repository Publication Point (RFC 6481), as described by some manifest. */ struct rpp { - struct map_list certs; /* Certificates */ + struct strlist certs; /* * 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 { /* Certificate Revocation List */ - struct cache_mapping *map; + struct { + char *url; /* * CRL in libcrypto-friendly form. * Initialized lazily; access via rpp_crl(). @@ -36,10 +35,8 @@ struct rpp { } crl; /* The Manifest is not needed for now. */ - - struct map_list roas; /* Route Origin Attestations */ - - struct map_list ghostbusters; + struct strlist roas; + struct strlist ghostbusters; /* * Note that the reference counting functions are not prepared for @@ -55,12 +52,12 @@ rpp_create(void) result = pmalloc(sizeof(struct rpp)); - maps_init(&result->certs); - result->crl.map = NULL; + strlist_init(&result->certs); + result->crl.url = NULL; result->crl.stack = NULL; result->crl.error = 0; - maps_init(&result->roas); - maps_init(&result->ghostbusters); + strlist_init(&result->roas); + strlist_init(&result->ghostbusters); result->references = 1; return result; @@ -77,54 +74,52 @@ rpp_refput(struct rpp *pp) { pp->references--; if (pp->references == 0) { - maps_cleanup(&pp->certs); - if (pp->crl.map != NULL) - map_refput(pp->crl.map); - if (pp->crl.stack != NULL) - sk_X509_CRL_pop_free(pp->crl.stack, X509_CRL_free); - maps_cleanup(&pp->roas); - maps_cleanup(&pp->ghostbusters); + strlist_cleanup(&pp->certs); + free(pp->crl.url); + sk_X509_CRL_pop_free(pp->crl.stack, X509_CRL_free); + strlist_cleanup(&pp->roas); + strlist_cleanup(&pp->ghostbusters); free(pp); } } -/** Steals ownership of @map. */ +/* Steals ownership of @url */ void -rpp_add_cert(struct rpp *pp, struct cache_mapping *map) +rpp_add_cert(struct rpp *pp, char *url) { - maps_add(&pp->certs, map); + strlist_add(&pp->certs, url); } -/** Steals ownership of @map. */ +/* Steals ownership of @url */ void -rpp_add_roa(struct rpp *pp, struct cache_mapping *map) +rpp_add_roa(struct rpp *pp, char *url) { - maps_add(&pp->roas, map); + strlist_add(&pp->roas, url); } -/** Steals ownership of @map. */ +/* Steals ownership of @url */ void -rpp_add_ghostbusters(struct rpp *pp, struct cache_mapping *map) +rpp_add_ghostbusters(struct rpp *pp, char *url) { - maps_add(&pp->ghostbusters, map); + strlist_add(&pp->ghostbusters, url); } -/** Steals ownership of @map. */ +/* Steals ownership of @url */ int -rpp_add_crl(struct rpp *pp, struct cache_mapping *map) +rpp_add_crl(struct rpp *pp, char *url) { /* rfc6481#section-2.2 */ - if (pp->crl.map) + if (pp->crl.url) return pr_val_err("Repository Publication Point has more than one CRL."); - pp->crl.map = map; + pp->crl.url = url; return 0; } -struct cache_mapping * +char const * rpp_get_crl(struct rpp const *pp) { - return pp->crl.map; + return pp->crl.url; } static int @@ -134,9 +129,9 @@ add_crl_to_stack(struct rpp *pp, STACK_OF(X509_CRL) *crls) int error; int idx; - fnstack_push_map(pp->crl.map); + fnstack_push(pp->crl.url); - error = crl_load(pp->crl.map, &crl); + error = crl_load(pp->crl.url, &crl); if (error) goto end; @@ -152,7 +147,7 @@ end: return error; } -/** +/* * 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 @@ -169,7 +164,7 @@ rpp_crl(struct rpp *pp, STACK_OF(X509_CRL) **result) *result = NULL; return 0; } - if (pp->crl.map == NULL) { + if (pp->crl.url == NULL) { /* rpp_crl() assumes the rpp has been populated already. */ pr_crit("RPP lacks a CRL."); } @@ -226,13 +221,11 @@ __cert_traverse(struct rpp *pp) return 0; } -/** - * Traverses through all of @pp's known files, validating them. - */ +/* Traverses through all of @pp's known files, validating them. */ void rpp_traverse(struct rpp *pp) { - struct cache_mapping **map; + char **url; /* * A subtree should not invalidate the rest of the tree, so error codes @@ -249,13 +242,13 @@ rpp_traverse(struct rpp *pp) __cert_traverse(pp); /* Validate ROAs, apply validation_handler on them. */ - ARRAYLIST_FOREACH(&pp->roas, map) - roa_traverse(*map, pp); + ARRAYLIST_FOREACH(&pp->roas, url) + roa_traverse(*url, pp); /* * We don't do much with the ghostbusters right now. * Just validate them. */ - ARRAYLIST_FOREACH(&pp->ghostbusters, map) - ghostbusters_traverse(*map, pp); + ARRAYLIST_FOREACH(&pp->ghostbusters, url) + ghostbusters_traverse(*url, pp); } diff --git a/src/rpp.h b/src/rpp.h index 5f78a2b5..8999b4dc 100644 --- a/src/rpp.h +++ b/src/rpp.h @@ -4,20 +4,18 @@ #include #include -#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_add_cert(struct rpp *, struct cache_mapping *); -int rpp_add_crl(struct rpp *, struct cache_mapping *); -void rpp_add_roa(struct rpp *, struct cache_mapping *); -void rpp_add_ghostbusters(struct rpp *, struct cache_mapping *); +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 *); -struct cache_mapping *rpp_get_crl(struct rpp const *); +char const *rpp_get_crl(struct rpp const *); int rpp_crl(struct rpp *, STACK_OF(X509_CRL) **); void rpp_traverse(struct rpp *); diff --git a/src/rrdp.c b/src/rrdp.c index 94f239d3..6107df51 100644 --- a/src/rrdp.c +++ b/src/rrdp.c @@ -1097,7 +1097,7 @@ dl_notif(struct cache_node *notif, struct update_notification *new) if (notif->dlerr) return false; - mtim = time(NULL); // XXX + mtim = time_nonfatal(); changed = false; notif->dlerr = http_download(notif->url, tmppath, notif->mtim, &changed); notif->flags |= CNF_FRESH; diff --git a/src/rtr/db/vrps.c b/src/rtr/db/vrps.c index 3ba4a73d..1b261817 100644 --- a/src/rtr/db/vrps.c +++ b/src/rtr/db/vrps.c @@ -82,7 +82,6 @@ static pthread_rwlock_t state_lock; int vrps_init(void) { - time_t now; int error; state.base = NULL; @@ -96,11 +95,7 @@ vrps_init(void) state.serial = 0; /* Get the bits that'll fit in session_id */ - now = 0; - error = get_current_time(&now); - if (error) - goto revert_deltas; - state.v0_session_id = now & 0xFFFF; + state.v0_session_id = time_fatal() & 0xFFFF; /* Minus 1 to prevent same ID */ state.v1_session_id = (state.v0_session_id != 0) @@ -113,14 +108,11 @@ vrps_init(void) if (error) { pr_op_err("state pthread_rwlock_init() errored: %s", strerror(error)); - goto revert_deltas; + darray_destroy(state.deltas); + return error; } return 0; - -revert_deltas: - darray_destroy(state.deltas); - return error; } void diff --git a/src/slurm/db_slurm.c b/src/slurm/db_slurm.c index faf7b2b8..5a34cfcc 100644 --- a/src/slurm/db_slurm.c +++ b/src/slurm/db_slurm.c @@ -101,11 +101,7 @@ db_slurm_create(struct slurm_csum_list *csums, struct db_slurm **result) db = pmalloc(sizeof(struct db_slurm)); - error = get_current_time(&db->loaded_date); - if (error) { - free(db); - return error; - } + db->loaded_date = time_nonfatal(); /* Not ready yet (nor required yet) for multithreading */ al_filter_prefix_init(&db->lists.filter_pfx_al); diff --git a/src/thread_var.h b/src/thread_var.h index 0d5d389c..8b91768f 100644 --- a/src/thread_var.h +++ b/src/thread_var.h @@ -2,6 +2,7 @@ #define SRC_THREAD_VAR_H_ #include "state.h" +#include "types/map.h" int thvar_init(void); /* This function does not need cleanup. */ diff --git a/src/types/map.c b/src/types/map.c index 87ab958c..f2e620f1 100644 --- a/src/types/map.c +++ b/src/types/map.c @@ -1,354 +1,8 @@ #include "types/map.h" -#include - -#include "alloc.h" -#include "cachetmp.h" -#include "common.h" +#include #include "config.h" -#include "config/filename_format.h" #include "log.h" -#include "rrdp.h" -#include "state.h" -#include "thread_var.h" -#include "types/path.h" -#include "types/str.h" -#include "types/url.h" - -/** - * Aside from the reference counter, instances are meant to be immutable. - * - * TODO (fine) This structure is so intertwined with the cache module, - * nowadays it feels like it should be moved there. - */ -struct cache_mapping { - /** - * The one that always starts with "rsync://" or "https://". - * Normalized, ASCII-only, NULL-terminated. - */ - char *url; - - /** - * Cache location where we downloaded the file. - * Normalized, ASCII-only, NULL-terminated. - * Sometimes NULL, depending on @type. - */ - char *path; - - enum map_type type; - - unsigned int references; /* Reference counter */ -}; - -/* - * @character is an integer because we sometimes receive signed chars, and other - * 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 normalize_url(struct path_builder *, char const *, char const *, int); - -/** - * Initializes @map->url by building a normalized version of @str. - */ -static int -init_url(struct cache_mapping *map, char const *str) -{ - char const *s; - char const *pfx; - int error; - struct path_builder pb; - - if (str == NULL){ - map->url = NULL; - return 0; - } - - for (s = str; s[0] != '\0'; s++) { - error = validate_url_character(s[0]); - if (error) - return error; - } - - pfx = NULL; - error = 0; - - switch (map->type) { - case MAP_RSYNC: - pfx = "rsync://"; - error = ENOTRSYNC; - break; - case MAP_HTTP: - case MAP_NOTIF: - pfx = "https://"; - error = ENOTHTTPS; - break; - } - - if (pfx == NULL) - pr_crit("Unknown mapping type: %u", map->type); - - __pb_init(&pb, RPKI_SCHEMA_LEN - 1); - error = normalize_url(&pb, str, pfx, error); - if (error) { - pb_cleanup(&pb); - return error; - } - - map->url = strncpy(pb.string, str, RPKI_SCHEMA_LEN); - return 0; -} - -struct path_parser { - char const *token; - char const *slash; - size_t len; -}; - -/* Return true if there's a new token, false if we're done. */ -static bool -path_next(struct path_parser *parser) -{ - if (parser->slash == NULL) - return false; - - parser->token = parser->slash + 1; - parser->slash = strchr(parser->token, '/'); - parser->len = (parser->slash != NULL) - ? (parser->slash - parser->token) - : strlen(parser->token); - - return parser->token[0] != 0; -} - -static bool -path_is_dot(struct path_parser *parser) -{ - return parser->len == 1 && parser->token[0] == '.'; -} - -static bool -path_is_dotdots(struct path_parser *parser) -{ - return parser->len == 2 - && parser->token[0] == '.' - && parser->token[1] == '.'; -} - -static int -normalize_url(struct path_builder *pb, char const *url, char const *pfx, - int errnot) -{ - struct path_parser parser; - size_t dot_dot_limit; - int error; - - /* Schema */ - if (!str_starts_with(url, pfx)) { - pr_val_err("URL '%s' does not begin with '%s'.", url, pfx); - return errnot; - } - - /* Domain */ - parser.slash = url + 7; - if (!path_next(&parser)) - return pr_val_err("URL '%s' seems to lack a domain.", url); - if (path_is_dot(&parser)) { - /* Dumping files to the cache root is unsafe. */ - return pr_val_err("URL '%s' employs the root domain. This is not really cacheable, so I'm going to distrust it.", - url); - } - if (path_is_dotdots(&parser)) { - return pr_val_err("URL '%s' seems to be dot-dotting past its own schema.", - url); - } - error = pb_appendn(pb, parser.token, parser.len); - if (error) - return error; - - /* Other components */ - dot_dot_limit = pb->len; - while (path_next(&parser)) { - if (path_is_dotdots(&parser)) { - error = pb_pop(pb, false); - if (error) - return error; - if (pb->len < dot_dot_limit) { - return pr_val_err("URL '%s' seems to be dot-dotting past its own domain.", - url); - } - } else if (!path_is_dot(&parser)) { - error = pb_appendn(pb, parser.token, parser.len); - if (error) - return error; - } - } - - return 0; -} - -/* - * Maps "rsync://a.b.c/d/e.cer" into "/rsync/a.b.c/d/e.cer". - */ -static int -map_simple(struct cache_mapping *map, char const *subdir) -{ - struct path_builder pb; - int error; - - error = pb_init_cache(&pb, subdir); - if (error) - return error; - - error = pb_append(&pb, &map->url[RPKI_SCHEMA_LEN]); - if (error) { - pb_cleanup(&pb); - return error; - } - - map->path = pb.string; - return 0; -} - -static int -init_path(struct cache_mapping *map) -{ - switch (map->type) { - case MAP_RSYNC: - return map_simple(map, "rsync"); - case MAP_HTTP: - return map_simple(map, "https"); - case MAP_NOTIF: - return cache_tmpfile(&map->path); - } - - pr_crit("Unknown URL type: %u", map->type); - return -EINVAL; /* Unreachable */ -} - -int -map_create(struct cache_mapping **result, enum map_type type, char const *url) -{ - struct cache_mapping *map; - int error; - - map = pmalloc(sizeof(struct cache_mapping)); - map->type = type; - map->references = 1; - - error = init_url(map, url); - if (error) { - free(map); - return error; - } - - error = init_path(map); - if (error) { - free(map->url); - free(map); - return error; - } - - *result = map; - return 0; -} - -/* Cache-only; url and type are meaningless. */ -struct cache_mapping * -map_create_cache(char const *path) -{ - struct cache_mapping *map; - - map = pzalloc(sizeof(struct cache_mapping)); - map->path = pstrdup(path); - map->references = 1; - - return map; -} - -struct cache_mapping * -map_refget(struct cache_mapping *map) -{ - map->references++; - return map; -} - -void -map_refput(struct cache_mapping *map) -{ - if (map == NULL) - return; - - map->references--; - if (map->references == 0) { - free(map->url); - free(map->path); - free(map); - } -} - -char const * -map_get_url(struct cache_mapping *map) -{ - return map->url; -} - -char const * -map_get_path(struct cache_mapping *map) -{ - return map->path; -} - -bool -map_equals(struct cache_mapping *m1, struct cache_mapping *m2) -{ - return strcmp(m1->url, m2->url) == 0; -} - -/* @ext must include the period. */ -bool -map_has_extension(struct cache_mapping *map, char const *ext) -{ - return str_ends_with(map->url, ext); -} - -enum map_type -map_get_type(struct cache_mapping *map) -{ - return map->type; -} static char const * get_filename(char const *file_path) @@ -376,44 +30,11 @@ map_get_printable(struct cache_mapping *map, enum filename_format format) char const * map_val_get_printable(struct cache_mapping *map) { - enum filename_format format; - - format = config_get_val_log_filename_format(); - return map_get_printable(map, format); + return map_get_printable(map, config_get_val_log_filename_format()); } char const * map_op_get_printable(struct cache_mapping *map) { - enum filename_format format; - - format = config_get_op_log_filename_format(); - return map_get_printable(map, format); -} - -DEFINE_ARRAY_LIST_FUNCTIONS(map_list, struct cache_mapping *, static) - -void -maps_init(struct map_list *maps) -{ - map_list_init(maps); -} - -static void -__map_refput(struct cache_mapping **map) -{ - map_refput(*map); -} - -void -maps_cleanup(struct map_list *maps) -{ - map_list_cleanup(maps, __map_refput); -} - -/* Swallows @map. */ -void -maps_add(struct map_list *maps, struct cache_mapping *map) -{ - map_list_add(maps, &map); + return map_get_printable(map, config_get_op_log_filename_format()); } diff --git a/src/types/map.h b/src/types/map.h index 4edb1bc2..2eb8568d 100644 --- a/src/types/map.h +++ b/src/types/map.h @@ -1,61 +1,28 @@ #ifndef SRC_TYPES_MAP_H_ #define SRC_TYPES_MAP_H_ -#include -#include "asn1/asn1c/IA5String.h" -#include "types/arraylist.h" - -/* - * "Long" time = seven days. - * Currently hardcoded, but queued for tweakability. - */ -enum map_type { +// XXX document this better +struct cache_mapping { /* - * (rsync) Repository Publication Point. RFC 6481. - * The directory is cached until it's untraversed for a "long" time. + * The one that always starts with "rsync://" or "https://". + * Normalized, ASCII-only, NULL-terminated. */ - MAP_RSYNC = (1 << 0), + char const *url; - MAP_HTTP = (1 << 1), + /* + * Official cache location of the file. + * Normalized, ASCII-only, NULL-terminated. + */ + char const *path; /* - * An RRDP notification file; downloaded via HTTP. - * The file itself is not cached, but we preserve a handful of metadata - * that is needed in subsequent iterations. - * The metadata is cached until it's untraversed for a "long" time. + * Temporary cache location of the file. + * It'll stay here until committed. */ - MAP_NOTIF = (MAP_HTTP | (1 << 2)), + char const *tmppath; }; -struct cache_mapping; - -struct cache_mapping *create_map(char const *); - -struct cache_mapping *map_refget(struct cache_mapping *); -void map_refput(struct cache_mapping *); - -/* - * Note that, if you intend to print some mapping, you're likely supposed to use - * map_*_get_printable() instead. - */ -char const *map_get_url(struct cache_mapping *); -char const *map_get_path(struct cache_mapping *); - -bool map_has_extension(struct cache_mapping *, char const *); - -enum map_type map_get_type(struct cache_mapping *); - char const *map_val_get_printable(struct cache_mapping *); char const *map_op_get_printable(struct cache_mapping *); -/* Plural */ - -/* XXX still used? */ -DEFINE_ARRAY_LIST_STRUCT(map_list, struct cache_mapping *); - -void maps_init(struct map_list *); -void maps_cleanup(struct map_list *); - -void maps_add(struct map_list *, struct cache_mapping *); - #endif /* SRC_TYPES_MAP_H_ */ diff --git a/src/types/str.h b/src/types/str.h index 9798e784..333596d5 100644 --- a/src/types/str.h +++ b/src/types/str.h @@ -42,7 +42,8 @@ bool token_equals(struct string_tokenizer *, struct string_tokenizer *); char *token_read(struct string_tokenizer *); size_t token_count(struct string_tokenizer *); -/* XXX delete? */ +/* Plural */ + DEFINE_ARRAY_LIST_STRUCT(strlist, char *); void strlist_init(struct strlist *); diff --git a/src/types/url.c b/src/types/url.c index 5227b335..11d321fe 100644 --- a/src/types/url.c +++ b/src/types/url.c @@ -3,6 +3,52 @@ #include "alloc.h" #include "types/path.h" +/* + * XXX use this: + * + * for (s = str; s[0] != '\0'; s++) { + error = validate_url_character(s[0]); + if (error) + return error; + } + * + * @character is an integer because we sometimes receive signed chars, and other + * 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 char * path_rewind(char const *root, char *cursor) { @@ -12,6 +58,25 @@ path_rewind(char const *root, char *cursor) return NULL; } +static bool +has_bad_prefix(char const *url) +{ + // XXX what happens if code expects one but url is the other + if (strncmp(url, "rsync://", RPKI_SCHEMA_LEN) && + strncmp(url, "https://", RPKI_SCHEMA_LEN)) + return true; + + /* Disallow the root domain */ + url += RPKI_SCHEMA_LEN; + if (url[0] == '/') + return true; + if (url[0] == '.' && url[1] == '/') + return true; + + // XXX read the standard and reject more bad URLs + return false; +} + /* * Collapses '//' (except from the schema), '.' and '..'. * @@ -23,8 +88,7 @@ url_normalize(char const *url) char *normal, *dst; struct tokenizer tkn; - if (strncmp(url, "rsync://", RPKI_SCHEMA_LEN) && - strncmp(url, "https://", RPKI_SCHEMA_LEN)) + if (has_bad_prefix(url)) return NULL; normal = pstrdup(url); diff --git a/test/Makefile.am b/test/Makefile.am index f6a03bf7..4adfa9e7 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -29,7 +29,7 @@ check_PROGRAMS += db_table.test check_PROGRAMS += deltas_array.test check_PROGRAMS += hash.test check_PROGRAMS += json_util.test -check_PROGRAMS += map.test +check_PROGRAMS += mft.test check_PROGRAMS += path.test check_PROGRAMS += pdu_handler.test check_PROGRAMS += pdu_stream.test @@ -71,8 +71,8 @@ hash_test_LDADD = ${MY_LDADD} json_util_test_SOURCES = json_util_test.c json_util_test_LDADD = ${MY_LDADD} -map_test_SOURCES = types/map_test.c -map_test_LDADD = ${MY_LDADD} +mft_test_SOURCES = object/manifest_test.c +mft_test_LDADD = ${MY_LDADD} path_test_SOURCES = types/path_test.c path_test_LDADD = ${MY_LDADD} diff --git a/test/base64_test.c b/test/base64_test.c index b6461646..5055046b 100644 --- a/test/base64_test.c +++ b/test/base64_test.c @@ -4,6 +4,7 @@ #include "base64.c" #include "common.h" #include "mock.c" +#include "types/array.h" static void ck_uchar_array(unsigned char *expected, size_t expected_len, diff --git a/test/cache_test.c b/test/cache_test.c index dcedef53..21fdfda9 100644 --- a/test/cache_test.c +++ b/test/cache_test.c @@ -56,10 +56,8 @@ setup_test(void) } static int -okay(struct cache_node *node, void *arg) +okay(struct cache_mapping *map, void *arg) { - // XXX ensure the rsync and RRDP codes do this - node->flags |= CNF_VALID; return 0; } @@ -181,13 +179,13 @@ ck_cache(struct cache_node *rsync, struct cache_node *https) static void ck_cache_rsync(struct cache_node *rsync) { - ck_cache(rsync, hunode(HE2UP, NULL)); + ck_cache(rsync, hnode(HE2UP, NULL)); } static void ck_cache_https(struct cache_node *https) { - ck_cache(runode(RE2UP, NULL), https); + ck_cache(rnode(RE2UP, NULL), https); } static time_t @@ -197,9 +195,7 @@ get_days_ago(int days) struct tm tm; int error; - tt_now = time(NULL); - if (tt_now == (time_t) -1) - pr_crit("time(NULL) returned (time_t) -1."); + tt_now = time_fatal(); if (localtime_r(&tt_now, &tm) == NULL) { error = errno; pr_crit("localtime_r(tt, &tm) returned error: %s", @@ -280,16 +276,16 @@ START_TEST(test_cache_download_rsync) printf("==== Startup ====\n"); run_dl_rsync("rsync://a.b.c/d", 0, 1); ck_cache_rsync( - runode(RE2UP, - runode(RO2UP("a.b.c"), - ruftnode(RO2UP("a.b.c/d"), FULL, "tmp/tmp/0", NULL), NULL), NULL)); + rnode(RE2UP, + rnode(RO2UP("a.b.c"), + rftnode(RO2UP("a.b.c/d"), FULL, "tmp/tmp/0", NULL), NULL), NULL)); printf("==== Redownload same file, nothing should happen ====\n"); run_dl_rsync("rsync://a.b.c/d", 0, 0); ck_cache_rsync( - runode(RE2UP, - runode(RO2UP("a.b.c"), - ruftnode(RO2UP("a.b.c/d"), FULL, "tmp/tmp/0", NULL), NULL), NULL)); + rnode(RE2UP, + rnode(RO2UP("a.b.c"), + rftnode(RO2UP("a.b.c/d"), FULL, "tmp/tmp/0", NULL), NULL), NULL)); /* * rsyncs are recursive, which means if we've been recently asked to @@ -298,10 +294,10 @@ START_TEST(test_cache_download_rsync) printf("==== Don't redownload child ====\n"); run_dl_rsync("rsync://a.b.c/d/e", 0, 0); ck_cache_rsync( - runode(RE2UP, - runode(RO2UP("a.b.c"), - ruftnode(RO2UP("a.b.c/d"), FULL, "tmp/tmp/0", - rufnode(RO2UP("a.b.c/d/e"), VALIDATED, NULL), NULL), NULL), NULL)); + rnode(RE2UP, + rnode(RO2UP("a.b.c"), + rftnode(RO2UP("a.b.c/d"), FULL, "tmp/tmp/0", + rfnode(RO2UP("a.b.c/d/e"), VALIDATED, NULL), NULL), NULL), NULL)); /* * rsyncs get truncated, because it results in much faster @@ -312,28 +308,28 @@ START_TEST(test_cache_download_rsync) printf("==== rsync truncated ====\n"); run_dl_rsync("rsync://x.y.z/m/n/o", 0, 1); ck_cache_rsync( - runode(RE2UP, - runode(RO2UP("a.b.c"), - ruftnode(RO2UP("a.b.c/d"), FULL, "tmp/tmp/0", - rufnode(RO2UP("a.b.c/d/e"), VALIDATED, NULL), NULL), NULL), - runode(RO2UP("x.y.z"), - ruftnode(RO2UP("x.y.z/m"), DOWNLOADED, "tmp/tmp/1", - rufnode(RO2UP("x.y.z/m/n"), BRANCH, - rufnode(RO2UP("x.y.z/m/n/o"), VALIDATED, NULL), NULL), NULL), NULL), NULL)); + rnode(RE2UP, + rnode(RO2UP("a.b.c"), + rftnode(RO2UP("a.b.c/d"), FULL, "tmp/tmp/0", + rfnode(RO2UP("a.b.c/d/e"), VALIDATED, NULL), NULL), NULL), + rnode(RO2UP("x.y.z"), + rftnode(RO2UP("x.y.z/m"), DOWNLOADED, "tmp/tmp/1", + rfnode(RO2UP("x.y.z/m/n"), BRANCH, + rfnode(RO2UP("x.y.z/m/n/o"), VALIDATED, NULL), NULL), NULL), NULL), NULL)); printf("==== Sibling ====\n"); run_dl_rsync("rsync://a.b.c/e/f", 0, 1); ck_cache_rsync( - runode(RE2UP, - runode(RO2UP("a.b.c"), - ruftnode(RO2UP("a.b.c/d"), FULL, "tmp/tmp/0", - rufnode(RO2UP("a.b.c/d/e"), VALIDATED, NULL), NULL), - ruftnode(RO2UP("a.b.c/e"), DOWNLOADED, "tmp/tmp/2", - rufnode(RO2UP("a.b.c/e/f"), VALIDATED, NULL), NULL), NULL), - runode(RO2UP("x.y.z"), - ruftnode(RO2UP("x.y.z/m"), DOWNLOADED, "tmp/tmp/1", - rufnode(RO2UP("x.y.z/m/n"), BRANCH, - rufnode(RO2UP("x.y.z/m/n/o"), VALIDATED, NULL), NULL), NULL), NULL), NULL)); + rnode(RE2UP, + rnode(RO2UP("a.b.c"), + rftnode(RO2UP("a.b.c/d"), FULL, "tmp/tmp/0", + rfnode(RO2UP("a.b.c/d/e"), VALIDATED, NULL), NULL), + rftnode(RO2UP("a.b.c/e"), DOWNLOADED, "tmp/tmp/2", + rfnode(RO2UP("a.b.c/e/f"), VALIDATED, NULL), NULL), NULL), + rnode(RO2UP("x.y.z"), + rftnode(RO2UP("x.y.z/m"), DOWNLOADED, "tmp/tmp/1", + rfnode(RO2UP("x.y.z/m/n"), BRANCH, + rfnode(RO2UP("x.y.z/m/n/o"), VALIDATED, NULL), NULL), NULL), NULL), NULL)); cleanup_test(); } @@ -349,27 +345,27 @@ START_TEST(test_cache_download_rsync_error) dl_error = -EINVAL; run_dl_rsync("rsync://a.b.c/e", -EINVAL, 1); ck_cache_rsync( - runode(RE2UP, - runode(RO2UP("a.b.c"), - ruftnode(RO2UP("a.b.c/d"), FULL, "tmp/tmp/0", NULL), - rufnode(RO2UP("a.b.c/e"), FAILED, NULL), NULL), NULL)); + rnode(RE2UP, + rnode(RO2UP("a.b.c"), + rftnode(RO2UP("a.b.c/d"), FULL, "tmp/tmp/0", NULL), + rfnode(RO2UP("a.b.c/e"), FAILED, NULL), NULL), NULL)); printf("==== Regardless of error, not reattempted because same iteration ====\n"); dl_error = EINVAL; run_dl_rsync("rsync://a.b.c/e", -EINVAL, 0); ck_cache_rsync( - runode(RE2UP, - runode(RO2UP("a.b.c"), - ruftnode(RO2UP("a.b.c/d"), FULL, "tmp/tmp/0", NULL), - rufnode(RO2UP("a.b.c/e"), FAILED, NULL), NULL), NULL)); + rnode(RE2UP, + rnode(RO2UP("a.b.c"), + rftnode(RO2UP("a.b.c/d"), FULL, "tmp/tmp/0", NULL), + rfnode(RO2UP("a.b.c/e"), FAILED, NULL), NULL), NULL)); dl_error = 0; run_dl_rsync("rsync://a.b.c/e", -EINVAL, 0); ck_cache_rsync( - runode(RE2UP, - runode(RO2UP("a.b.c"), - ruftnode(RO2UP("a.b.c/d"), FULL, "tmp/tmp/0", NULL), - rufnode(RO2UP("a.b.c/e"), FAILED, NULL), NULL), NULL)); + rnode(RE2UP, + rnode(RO2UP("a.b.c"), + rftnode(RO2UP("a.b.c/d"), FULL, "tmp/tmp/0", NULL), + rfnode(RO2UP("a.b.c/e"), FAILED, NULL), NULL), NULL)); cleanup_test(); } @@ -385,10 +381,10 @@ START_TEST(test_cache_cleanup_rsync) run_dl_rsync("rsync://a.b.c/e", 0, 1); run_cleanup(); ck_cache_rsync( - runode(RE2UP, - runode(RO2UP("a.b.c"), - rufnode(RO2UP("a.b.c/d"), FULL, NULL), - rufnode(RO2UP("a.b.c/e"), FULL, NULL), NULL), NULL)); + rnode(RE2UP, + rnode(RO2UP("a.b.c"), + rfnode(RO2UP("a.b.c/d"), FULL, NULL), + rfnode(RO2UP("a.b.c/e"), FULL, NULL), NULL), NULL)); printf("==== One iteration with no changes, for paranoia ====\n"); new_iteration(true); @@ -396,10 +392,10 @@ START_TEST(test_cache_cleanup_rsync) run_dl_rsync("rsync://a.b.c/e", 0, 1); run_cleanup(); ck_cache_rsync( - runode(RE2UP, - runode(RO2UP("a.b.c"), - rufnode(RO2UP("a.b.c/d"), FULL, NULL), - rufnode(RO2UP("a.b.c/e"), FULL, NULL), NULL), NULL)); + rnode(RE2UP, + rnode(RO2UP("a.b.c"), + rfnode(RO2UP("a.b.c/d"), FULL, NULL), + rfnode(RO2UP("a.b.c/e"), FULL, NULL), NULL), NULL)); printf("==== Add one sibling ====\n"); new_iteration(true); @@ -408,62 +404,62 @@ START_TEST(test_cache_cleanup_rsync) run_dl_rsync("rsync://a.b.c/f", 0, 1); run_cleanup(); ck_cache_rsync( - runode(RE2UP, - runode(RO2UP("a.b.c"), - rufnode(RO2UP("a.b.c/d"), FULL, NULL), - rufnode(RO2UP("a.b.c/e"), FULL, NULL), - rufnode(RO2UP("a.b.c/f"), FULL, NULL), NULL), NULL)); + rnode(RE2UP, + rnode(RO2UP("a.b.c"), + rfnode(RO2UP("a.b.c/d"), FULL, NULL), + rfnode(RO2UP("a.b.c/e"), FULL, NULL), + rfnode(RO2UP("a.b.c/f"), FULL, NULL), NULL), NULL)); printf("==== Nodes don't get updated, but they're still too young ====\n"); new_iteration(false); run_cleanup(); ck_cache_rsync( - runode(RE2UP, - runode(RO2UP("a.b.c"), - rufnode(RO2UP("a.b.c/d"), STALE, NULL), - rufnode(RO2UP("a.b.c/e"), STALE, NULL), - rufnode(RO2UP("a.b.c/f"), STALE, NULL), NULL), NULL)); + rnode(RE2UP, + rnode(RO2UP("a.b.c"), + rfnode(RO2UP("a.b.c/d"), STALE, NULL), + rfnode(RO2UP("a.b.c/e"), STALE, NULL), + rfnode(RO2UP("a.b.c/f"), STALE, NULL), NULL), NULL)); printf("==== Remove some branches ====\n"); new_iteration(true); run_dl_rsync("rsync://a.b.c/d", 0, 1); run_cleanup(); ck_cache_rsync( - runode(RE2UP, - runode(RO2UP("a.b.c"), - rufnode(RO2UP("a.b.c/d"), FULL, NULL), NULL), NULL)); + rnode(RE2UP, + rnode(RO2UP("a.b.c"), + rfnode(RO2UP("a.b.c/d"), FULL, NULL), NULL), NULL)); printf("==== Remove old branch and add sibling at the same time ====\n"); new_iteration(true); run_dl_rsync("rsync://a.b.c/e", 0, 1); run_cleanup(); ck_cache_rsync( - runode(RE2UP, - runode(RO2UP("a.b.c"), - rufnode(RO2UP("a.b.c/e"), FULL, NULL), NULL), NULL)); + rnode(RE2UP, + rnode(RO2UP("a.b.c"), + rfnode(RO2UP("a.b.c/e"), FULL, NULL), NULL), NULL)); printf("==== Try child ====\n"); new_iteration(true); run_dl_rsync("rsync://a.b.c/e/f/g", 0, 1); run_cleanup(); ck_cache_rsync( - runode(RE2UP, - runode(RO2UP("a.b.c"), - rufnode(RO2UP("a.b.c/e"), FULL, NULL), NULL), NULL)); + rnode(RE2UP, + rnode(RO2UP("a.b.c"), + rfnode(RO2UP("a.b.c/e"), FULL, NULL), NULL), NULL)); printf("==== Parent again ====\n"); new_iteration(true); run_dl_rsync("rsync://a.b.c/e", 0, 1); run_cleanup(); ck_cache_rsync( - runode(RE2UP, - runode(RO2UP("a.b.c"), - rufnode(RO2UP("a.b.c/e"), FULL, NULL), NULL), NULL)); + rnode(RE2UP, + rnode(RO2UP("a.b.c"), + rfnode(RO2UP("a.b.c/e"), FULL, NULL), NULL), NULL)); printf("==== Empty the tree ====\n"); new_iteration(true); run_cleanup(); - ck_cache_rsync(runode(RE2UP, NULL)); + ck_cache_rsync(rnode(RE2UP, NULL)); printf("==== Node exists, but file doesn't ====\n"); @@ -471,22 +467,22 @@ START_TEST(test_cache_cleanup_rsync) run_dl_rsync("rsync://a.b.c/e", 0, 1); run_dl_rsync("rsync://a.b.c/f", 0, 1); ck_cache_rsync( - runode(RE2UP, - runode(RO2UP("a.b.c"), - ruftnode(RO2UP("a.b.c/e"), FULL, "tmp/tmp/B", NULL), - ruftnode(RO2UP("a.b.c/f"), FULL, "tmp/tmp/C", NULL), NULL), NULL)); + rnode(RE2UP, + rnode(RO2UP("a.b.c"), + rftnode(RO2UP("a.b.c/e"), FULL, "tmp/tmp/B", NULL), + rftnode(RO2UP("a.b.c/f"), FULL, "tmp/tmp/C", NULL), NULL), NULL)); run_cleanup(); ck_cache_rsync( - runode(RE2UP, - runode(RO2UP("a.b.c"), - rufnode(RO2UP("a.b.c/e"), FULL, NULL), - rufnode(RO2UP("a.b.c/f"), FULL, NULL), NULL), NULL)); + rnode(RE2UP, + rnode(RO2UP("a.b.c"), + rfnode(RO2UP("a.b.c/e"), FULL, NULL), + rfnode(RO2UP("a.b.c/f"), FULL, NULL), NULL), NULL)); ck_assert_int_eq(0, file_rm_rf("tmp/rsync/a.b.c/f")); run_cleanup(); ck_cache_rsync( - runode(RE2UP, - runode(RO2UP("a.b.c"), - rufnode(RO2UP("a.b.c/e"), FULL, NULL), NULL), NULL)); + rnode(RE2UP, + rnode(RO2UP("a.b.c"), + rfnode(RO2UP("a.b.c/e"), FULL, NULL), NULL), NULL)); cleanup_test(); } @@ -502,17 +498,17 @@ START_TEST(test_cache_cleanup_rsync_error) dl_error = -EINVAL; run_dl_rsync("rsync://a.b.c/e", -EINVAL, 1); ck_cache_rsync( - runode(RE2UP, - runode(RO2UP("a.b.c"), - ruftnode(RO2UP("a.b.c/d"), FULL, "tmp/tmp/0", NULL), - rufnode(RO2UP("a.b.c/e"), FAILED, NULL), NULL), NULL)); + rnode(RE2UP, + rnode(RO2UP("a.b.c"), + rftnode(RO2UP("a.b.c/d"), FULL, "tmp/tmp/0", NULL), + rfnode(RO2UP("a.b.c/e"), FAILED, NULL), NULL), NULL)); printf("==== Node deleted because file doesn't exist ====\n"); run_cleanup(); ck_cache_rsync( - runode(RE2UP, - runode(RO2UP("a.b.c"), - rufnode(RO2UP("a.b.c/d"), FULL, NULL), NULL), NULL)); + rnode(RE2UP, + rnode(RO2UP("a.b.c"), + rfnode(RO2UP("a.b.c/d"), FULL, NULL), NULL), NULL)); printf("==== Node and file preserved because young ====\n"); /* (Deletion does not depend on success or failure.) */ @@ -520,14 +516,14 @@ START_TEST(test_cache_cleanup_rsync_error) dl_error = -EINVAL; run_dl_rsync("rsync://a.b.c/d", -EINVAL, 1); ck_cache_rsync( - runode(RE2UP, - runode(RO2UP("a.b.c"), - rufnode(RO2UP("a.b.c/d"), DOWNLOADED, NULL), NULL), NULL)); + rnode(RE2UP, + rnode(RO2UP("a.b.c"), + rfnode(RO2UP("a.b.c/d"), DOWNLOADED, NULL), NULL), NULL)); printf("==== Error node deleted because old ====\n"); new_iteration(true); run_cleanup(); - ck_cache_rsync(runode(RE2UP, NULL)); + ck_cache_rsync(rnode(RE2UP, NULL)); cleanup_test(); } @@ -547,30 +543,30 @@ START_TEST(test_cache_download_https) printf("==== Download *file* e ====\n"); run_dl_https("https://a.b.c/d/e", 0, 1); ck_cache_https( - hunode(HE2UP, - hunode(HO2UP("a.b.c"), - hunode(HO2UP("a.b.c/d"), - huftnode(HO2UP("a.b.c/d/e"), HFULL, "tmp/tmp/0", NULL), NULL), NULL), NULL)); + hnode(HE2UP, + hnode(HO2UP("a.b.c"), + hnode(HO2UP("a.b.c/d"), + hftnode(HO2UP("a.b.c/d/e"), HFULL, "tmp/tmp/0", NULL), NULL), NULL), NULL)); printf("==== Download something else 1 ====\n"); run_dl_https("https://a.b.c/e", 0, 1); ck_cache_https( - hunode(HE2UP, - hunode(HO2UP("a.b.c"), - hunode(HO2UP("a.b.c/d"), - huftnode(HO2UP("a.b.c/d/e"), HFULL, "tmp/tmp/0", NULL), NULL), - huftnode(HO2UP("a.b.c/e"), HFULL, "tmp/tmp/1", NULL), NULL), NULL)); + hnode(HE2UP, + hnode(HO2UP("a.b.c"), + hnode(HO2UP("a.b.c/d"), + hftnode(HO2UP("a.b.c/d/e"), HFULL, "tmp/tmp/0", NULL), NULL), + hftnode(HO2UP("a.b.c/e"), HFULL, "tmp/tmp/1", NULL), NULL), NULL)); printf("==== Download something else 2 ====\n"); run_dl_https("https://x.y.z/e", 0, 1); ck_cache_https( - hunode(HE2UP, - hunode(HO2UP("a.b.c"), - hunode(HO2UP("a.b.c/d"), - huftnode(HO2UP("a.b.c/d/e"), HFULL, "tmp/tmp/0", NULL), NULL), - huftnode(HO2UP("a.b.c/e"), HFULL, "tmp/tmp/1", NULL), NULL), - hunode(HO2UP("x.y.z"), - huftnode(HO2UP("x.y.z/e"), HFULL, "tmp/tmp/2", NULL), NULL), NULL)); + hnode(HE2UP, + hnode(HO2UP("a.b.c"), + hnode(HO2UP("a.b.c/d"), + hftnode(HO2UP("a.b.c/d/e"), HFULL, "tmp/tmp/0", NULL), NULL), + hftnode(HO2UP("a.b.c/e"), HFULL, "tmp/tmp/1", NULL), NULL), + hnode(HO2UP("x.y.z"), + hftnode(HO2UP("x.y.z/e"), HFULL, "tmp/tmp/2", NULL), NULL), NULL)); cleanup_test(); } @@ -586,10 +582,10 @@ START_TEST(test_cache_download_https_error) dl_error = -EINVAL; run_dl_https("https://a.b.c/e", -EINVAL, 1); ck_cache_https( - hunode(HE2UP, - hunode(HO2UP("a.b.c"), - huftnode(HO2UP("a.b.c/d"), HFULL, "tmp/tmp/0", NULL), - huftnode(HO2UP("a.b.c/e"), HFAILED, NULL, NULL), NULL), NULL)); + hnode(HE2UP, + hnode(HO2UP("a.b.c"), + hftnode(HO2UP("a.b.c/d"), HFULL, "tmp/tmp/0", NULL), + hftnode(HO2UP("a.b.c/e"), HFAILED, NULL, NULL), NULL), NULL)); printf("==== Regardless of error, not reattempted because same iteration ====\n"); dl_error = -EINVAL; @@ -597,10 +593,10 @@ START_TEST(test_cache_download_https_error) dl_error = 0; run_dl_https("https://a.b.c/e", -EINVAL, 0); ck_cache_https( - hunode(HE2UP, - hunode(HO2UP("a.b.c"), - huftnode(HO2UP("a.b.c/d"), HFULL, "tmp/tmp/0", NULL), - huftnode(HO2UP("a.b.c/e"), HFAILED, NULL, NULL), NULL), NULL)); + hnode(HE2UP, + hnode(HO2UP("a.b.c"), + hftnode(HO2UP("a.b.c/d"), HFULL, "tmp/tmp/0", NULL), + hftnode(HO2UP("a.b.c/e"), HFAILED, NULL, NULL), NULL), NULL)); cleanup_test(); } @@ -618,39 +614,39 @@ START_TEST(test_cache_cleanup_https) run_dl_https("https://a.b.c/e", 0, 1); run_cleanup(); ck_cache_https( - hunode(HE2UP, - hunode(HO2UP("a.b.c"), - hufnode(HO2UP("a.b.c/d"), HFULL, NULL), - hufnode(HO2UP("a.b.c/e"), HFULL, NULL), NULL), NULL)); + hnode(HE2UP, + hnode(HO2UP("a.b.c"), + hfnode(HO2UP("a.b.c/d"), HFULL, NULL), + hfnode(HO2UP("a.b.c/e"), HFULL, NULL), NULL), NULL)); printf("==== Remove one branch ====\n"); new_iteration(true); run_dl_https("https://a.b.c/d", 0, 1); run_cleanup(); ck_cache_https( - hunode(HE2UP, - hunode(HO2UP("a.b.c"), - hufnode(HO2UP("a.b.c/d"), HFULL, NULL), NULL), NULL)); + hnode(HE2UP, + hnode(HO2UP("a.b.c"), + hfnode(HO2UP("a.b.c/d"), HFULL, NULL), NULL), NULL)); printf("==== Change the one branch ====\n"); new_iteration(true); run_dl_https("https://a.b.c/e", 0, 1); run_cleanup(); ck_cache_https( - hunode(HE2UP, - hunode(HO2UP("a.b.c"), - hufnode(HO2UP("a.b.c/e"), HFULL, NULL), NULL), NULL)); + hnode(HE2UP, + hnode(HO2UP("a.b.c"), + hfnode(HO2UP("a.b.c/e"), HFULL, NULL), NULL), NULL)); printf("==== Add a child to the same branch, do not update the old one ====\n"); new_iteration(true); run_dl_https("https://a.b.c/e/f/g", 0, 1); run_cleanup(); ck_cache_https( - hunode(HE2UP, - hunode(HO2UP("a.b.c"), - hunode(HO2UP("a.b.c/e"), - hunode(HO2UP("a.b.c/e/f"), - hufnode(HO2UP("a.b.c/e/f/g"), HFULL, NULL), NULL), NULL), NULL), NULL)); + hnode(HE2UP, + hnode(HO2UP("a.b.c"), + hnode(HO2UP("a.b.c/e"), + hnode(HO2UP("a.b.c/e/f"), + hfnode(HO2UP("a.b.c/e/f/g"), HFULL, NULL), NULL), NULL), NULL), NULL)); printf("==== Download parent, do not update child ====\n"); /* (Children need to die, because parent is now a file) */ @@ -658,87 +654,87 @@ START_TEST(test_cache_cleanup_https) run_dl_https("https://a.b.c/e/f", 0, 1); run_cleanup(); ck_cache_https( - hunode(HE2UP, - hunode(HO2UP("a.b.c"), - hunode(HO2UP("a.b.c/e"), - hufnode(HO2UP("a.b.c/e/f"), HFULL, NULL), NULL), NULL), NULL)); + hnode(HE2UP, + hnode(HO2UP("a.b.c"), + hnode(HO2UP("a.b.c/e"), + hfnode(HO2UP("a.b.c/e/f"), HFULL, NULL), NULL), NULL), NULL)); printf("==== Do it again ====\n"); new_iteration(true); run_dl_https("https://a.b.c/e", 0, 1); run_cleanup(); ck_cache_https( - hunode(HE2UP, - hunode(HO2UP("a.b.c"), - hufnode(HO2UP("a.b.c/e"), HFULL, NULL), NULL), NULL)); + hnode(HE2UP, + hnode(HO2UP("a.b.c"), + hfnode(HO2UP("a.b.c/e"), HFULL, NULL), NULL), NULL)); printf("==== Empty the tree ====\n"); new_iteration(true); run_cleanup(); - ck_cache_https(hunode(HE2UP, NULL)); + ck_cache_https(hnode(HE2UP, NULL)); printf("==== Node exists, but file doesn't ====\n"); new_iteration(true); run_dl_https("https://a.b.c/e", 0, 1); run_dl_https("https://a.b.c/f/g/h", 0, 1); ck_cache_https( - hunode(HE2UP, - hunode(HO2UP("a.b.c"), - huftnode(HO2UP("a.b.c/e"), HFULL, "tmp/tmp/7", NULL), - hunode(HO2UP("a.b.c/f"), - hunode(HO2UP("a.b.c/f/g"), - huftnode(HO2UP("a.b.c/f/g/h"), HFULL, "tmp/tmp/8", NULL), NULL), NULL), NULL), NULL)); + hnode(HE2UP, + hnode(HO2UP("a.b.c"), + hftnode(HO2UP("a.b.c/e"), HFULL, "tmp/tmp/7", NULL), + hnode(HO2UP("a.b.c/f"), + hnode(HO2UP("a.b.c/f/g"), + hftnode(HO2UP("a.b.c/f/g/h"), HFULL, "tmp/tmp/8", NULL), NULL), NULL), NULL), NULL)); run_cleanup(); /* Move from tmp/tmp to tmp/https */ ck_cache_https( - hunode(HE2UP, - hunode(HO2UP("a.b.c"), - hufnode(HO2UP("a.b.c/e"), HFULL, NULL), - hunode(HO2UP("a.b.c/f"), - hunode(HO2UP("a.b.c/f/g"), - hufnode(HO2UP("a.b.c/f/g/h"), HFULL, NULL), NULL), NULL), NULL), NULL)); + hnode(HE2UP, + hnode(HO2UP("a.b.c"), + hfnode(HO2UP("a.b.c/e"), HFULL, NULL), + hnode(HO2UP("a.b.c/f"), + hnode(HO2UP("a.b.c/f/g"), + hfnode(HO2UP("a.b.c/f/g/h"), HFULL, NULL), NULL), NULL), NULL), NULL)); ck_assert_int_eq(0, file_rm_rf("tmp/https/a.b.c/f/g/h")); run_cleanup(); /* Actual test */ ck_cache_https( - hunode(HE2UP, - hunode(HO2UP("a.b.c"), - hufnode(HO2UP("a.b.c/e"), HFULL, NULL), NULL), NULL)); + hnode(HE2UP, + hnode(HO2UP("a.b.c"), + hfnode(HO2UP("a.b.c/e"), HFULL, NULL), NULL), NULL)); printf("==== Temporal version disappears before we get a commit ====\n"); new_iteration(true); run_dl_https("https://a.b.c/e", 0, 1); ck_cache_https( - hunode(HE2UP, - hunode(HO2UP("a.b.c"), - huftnode(HO2UP("a.b.c/e"), HFULL, "tmp/tmp/9", NULL), NULL), NULL)); + hnode(HE2UP, + hnode(HO2UP("a.b.c"), + hftnode(HO2UP("a.b.c/e"), HFULL, "tmp/tmp/9", NULL), NULL), NULL)); ck_assert_int_eq(0, file_rm_rf("tmp/tmp/9")); run_cleanup(); - ck_cache_https(hunode(HE2UP, NULL)); + ck_cache_https(hnode(HE2UP, NULL)); printf("==== Temporal version disappears after we get a commit ====\n"); new_iteration(true); run_dl_https("https://a.b.c/e", 0, 1); ck_cache_https( - hunode(HE2UP, - hunode(HO2UP("a.b.c"), - huftnode(HO2UP("a.b.c/e"), HFULL, "tmp/tmp/A", NULL), NULL), NULL)); + hnode(HE2UP, + hnode(HO2UP("a.b.c"), + hftnode(HO2UP("a.b.c/e"), HFULL, "tmp/tmp/A", NULL), NULL), NULL)); run_cleanup(); /* Commit */ ck_cache_https( - hunode(HE2UP, - hunode(HO2UP("a.b.c"), - hufnode(HO2UP("a.b.c/e"), HFULL, NULL, NULL), NULL), NULL)); + hnode(HE2UP, + hnode(HO2UP("a.b.c"), + hfnode(HO2UP("a.b.c/e"), HFULL, NULL, NULL), NULL), NULL)); new_iteration(false); run_dl_https("https://a.b.c/e", 0, 1); ck_cache_https( - hunode(HE2UP, - hunode(HO2UP("a.b.c"), - huftnode(HO2UP("a.b.c/e"), HFULL, "tmp/tmp/B", NULL), NULL), NULL)); + hnode(HE2UP, + hnode(HO2UP("a.b.c"), + hftnode(HO2UP("a.b.c/e"), HFULL, "tmp/tmp/B", NULL), NULL), NULL)); ck_assert_int_eq(0, file_rm_rf("tmp/tmp/B")); run_cleanup(); ck_cache_https( - hunode(HE2UP, - hunode(HO2UP("a.b.c"), - hufnode(HO2UP("a.b.c/e"), HFULL, NULL), NULL), NULL)); + hnode(HE2UP, + hnode(HO2UP("a.b.c"), + hfnode(HO2UP("a.b.c/e"), HFULL, NULL), NULL), NULL)); cleanup_test(); } @@ -755,39 +751,39 @@ START_TEST(test_cache_cleanup_https_error) run_dl_https("https://a.b.c/e", -EINVAL, 1); PR_DEBUG; ck_cache_https( - hunode(HE2UP, - hunode(HO2UP("a.b.c"), - huftnode(HO2UP("a.b.c/d"), HFULL, "tmp/tmp/0", NULL), - hufnode(HO2UP("a.b.c/e"), HFAILED, NULL), NULL), NULL)); + hnode(HE2UP, + hnode(HO2UP("a.b.c"), + hftnode(HO2UP("a.b.c/d"), HFULL, "tmp/tmp/0", NULL), + hfnode(HO2UP("a.b.c/e"), HFAILED, NULL), NULL), NULL)); printf("==== Deleted because file ENOENT ====\n"); run_cleanup(); ck_cache_https( - hunode(HE2UP, - hunode(HO2UP("a.b.c"), - hufnode(HO2UP("a.b.c/d"), HFULL, NULL), NULL), NULL)); + hnode(HE2UP, + hnode(HO2UP("a.b.c"), + hfnode(HO2UP("a.b.c/d"), HFULL, NULL), NULL), NULL)); printf("==== Fail d ====\n"); new_iteration(false); dl_error = -EINVAL; run_dl_https("https://a.b.c/d", -EINVAL, 1); ck_cache_https( - hunode(HE2UP, - hunode(HO2UP("a.b.c"), - hufnode(HO2UP("a.b.c/d"), CNF_CACHED | CNF_FRESH, NULL), NULL), NULL)); + hnode(HE2UP, + hnode(HO2UP("a.b.c"), + hfnode(HO2UP("a.b.c/d"), CNF_CACHED | CNF_FRESH, NULL), NULL), NULL)); printf("==== Not deleted, because not old ====\n"); new_iteration(false); run_cleanup(); ck_cache_https( - hunode(HE2UP, - hunode(HO2UP("a.b.c"), - hufnode(HO2UP("a.b.c/d"), CNF_CACHED, NULL), NULL), NULL)); + hnode(HE2UP, + hnode(HO2UP("a.b.c"), + hfnode(HO2UP("a.b.c/d"), CNF_CACHED, NULL), NULL), NULL)); printf("==== Become old ====\n"); new_iteration(true); run_cleanup(); - ck_cache_https(hunode(HE2UP, NULL)); + ck_cache_https(hnode(HE2UP, NULL)); cleanup_test(); } @@ -799,28 +795,28 @@ START_TEST(test_dots) run_dl_https("https://a.b.c/d", 0, 1); ck_cache_https( - hunode(HE2UP, - hunode(HO2UP("a.b.c"), - huftnode(HO2UP("a.b.c/d"), HFULL, "tmp/tmp/0", NULL), NULL), NULL)); + hnode(HE2UP, + hnode(HO2UP("a.b.c"), + hftnode(HO2UP("a.b.c/d"), HFULL, "tmp/tmp/0", NULL), NULL), NULL)); run_dl_https("https://a.b.c/d/.", 0, 0); ck_cache_https( - hunode(HE2UP, - hunode(HO2UP("a.b.c"), - huftnode(HO2UP("a.b.c/d"), HFULL, "tmp/tmp/0", NULL), NULL), NULL)); + hnode(HE2UP, + hnode(HO2UP("a.b.c"), + hftnode(HO2UP("a.b.c/d"), HFULL, "tmp/tmp/0", NULL), NULL), NULL)); run_dl_https("https://a.b.c/d/e/..", 0, 0); ck_cache_https( - hunode(HE2UP, - hunode(HO2UP("a.b.c"), - huftnode(HO2UP("a.b.c/d"), HFULL, "tmp/tmp/0", NULL), NULL), NULL)); + hnode(HE2UP, + hnode(HO2UP("a.b.c"), + hftnode(HO2UP("a.b.c/d"), HFULL, "tmp/tmp/0", NULL), NULL), NULL)); run_dl_https("https://a.b.c/./d/../e", 0, 1); ck_cache_https( - hunode(HE2UP, - hunode(HO2UP("a.b.c"), - huftnode(HO2UP("a.b.c/d"), HFULL, "tmp/tmp/0", NULL), - huftnode(HO2UP("a.b.c/e"), HFULL, "tmp/tmp/1", NULL), NULL), NULL)); + hnode(HE2UP, + hnode(HO2UP("a.b.c"), + hftnode(HO2UP("a.b.c/d"), HFULL, "tmp/tmp/0", NULL), + hftnode(HO2UP("a.b.c/e"), HFULL, "tmp/tmp/1", NULL), NULL), NULL)); cleanup_test(); } diff --git a/test/cache_util.c b/test/cache_util.c index 74475bf5..08a588db 100644 --- a/test/cache_util.c +++ b/test/cache_util.c @@ -42,8 +42,8 @@ ck_assert_cachent_eq(struct cache_node *expected, struct cache_node *actual) } } -struct cache_node * -vcreate_node(char const *url, char const *path, int flags, char const *tmppath, +static struct cache_node * +vnode(char const *url, char const *path, int flags, char const *tmppath, va_list children) { struct cache_node *result; @@ -69,76 +69,78 @@ vcreate_node(char const *url, char const *path, int flags, char const *tmppath, } struct cache_node * -ruftnode(char const *url, char const *path, int flags, char const *tmppath, ...) +rftnode(char const *url, char const *path, int flags, char const *tmppath, ...) { struct cache_node *result; va_list children; va_start(children, tmppath); - result = vcreate_node(url, path, flags, tmppath, children); + result = vnode(url, path, flags, tmppath, children); va_end(children); return result; } struct cache_node * -rufnode(char const *url, char const *path, int flags, ...) +rfnode(char const *url, char const *path, int flags, ...) { struct cache_node *result; va_list children; va_start(children, flags); - result = vcreate_node(url, path, flags, NULL, children); + result = vnode(url, path, flags, NULL, children); va_end(children); return result; } struct cache_node * -runode(char const *url, char const *path, ...) +rnode(char const *url, char const *path, ...) { struct cache_node *result; va_list children; va_start(children, path); - result = vcreate_node(url, path, 0, NULL, children); + result = vnode(url, path, 0, NULL, children); va_end(children); return result; } struct cache_node * -huftnode(char const *url, char const *path, int flags, char const *tmppath, ...) +hftnode(char const *url, char const *path, int flags, char const *tmppath, ...) { struct cache_node *result; va_list children; va_start(children, tmppath); - result = vcreate_node(url, path, flags, tmppath, children); + result = vnode(url, path, flags, tmppath, children); va_end(children); return result; } -struct cache_node *hufnode(char const *url, char const *path, int flags, ...) +struct cache_node * +hfnode(char const *url, char const *path, int flags, ...) { struct cache_node *result; va_list children; va_start(children, flags); - result = vcreate_node(url, path, flags, NULL, children); + result = vnode(url, path, flags, NULL, children); va_end(children); return result; } -struct cache_node *hunode(char const *url, char const *path, ...) +struct cache_node * +hnode(char const *url, char const *path, ...) { struct cache_node *result; va_list children; va_start(children, path); - result = vcreate_node(url, path, 0, NULL, children); + result = vnode(url, path, 0, NULL, children); va_end(children); return result; diff --git a/test/cache_util.h b/test/cache_util.h index 185895ad..f2461023 100644 --- a/test/cache_util.h +++ b/test/cache_util.h @@ -6,16 +6,13 @@ void ck_assert_cachent_eq(struct cache_node *, struct cache_node *); -struct cache_node *vcreate_node(char const *, char const *, int, char const *, va_list); +struct cache_node *rftnode(char const *, char const *, int, char const *, ...); +struct cache_node *rfnode(char const *, char const *, int, ...); +struct cache_node *rnode(char const *, char const *, ...); -// XXX Rename ? -struct cache_node *ruftnode(char const *, char const *, int, char const *, ...); -struct cache_node *rufnode(char const *, char const *, int, ...); -struct cache_node *runode(char const *, char const *, ...); - -struct cache_node *huftnode(char const *, char const *, int, char const *, ...); -struct cache_node *hufnode(char const *, char const *, int, ...); -struct cache_node *hunode(char const *, char const *, ...); +struct cache_node *hftnode(char const *, char const *, int, char const *, ...); +struct cache_node *hfnode(char const *, char const *, int, ...); +struct cache_node *hnode(char const *, char const *, ...); /* rsync offset to url + path */ #define RO2UP(offset) "rsync://" offset, "tmp/rsync/" offset diff --git a/test/cachent_test.c b/test/cachent_test.c index 8ffe46ad..1f821d33 100644 --- a/test/cachent_test.c +++ b/test/cachent_test.c @@ -20,14 +20,14 @@ START_TEST(test_delete) { struct cache_node *root, *a, *b; - a = runode(RO2UP("a"), NULL); + a = rnode(RO2UP("a"), NULL); dn = 0; cachent_delete(a); ck_assert_uint_eq(1, dn); ck_assert_str_eq("a", deleted[0]); - a = runode(RO2UP("a"), NULL); - root = runode(RE2UP, a, NULL); + a = rnode(RO2UP("a"), NULL); + root = rnode(RE2UP, a, NULL); dn = 0; cachent_delete(a); ck_assert_ptr_eq(NULL, root->children); @@ -39,23 +39,23 @@ START_TEST(test_delete) ck_assert_uint_eq(1, dn); ck_assert_str_eq("rsync", deleted[0]); - b = runode(RO2UP("a/b"), - runode(RO2UP("a/b/c"), NULL), - runode(RO2UP("a/b/d"), NULL), - runode(RO2UP("a/b/e"), NULL), - runode(RO2UP("a/b/f"), NULL), NULL); - a = runode(RO2UP("a"), + b = rnode(RO2UP("a/b"), + rnode(RO2UP("a/b/c"), NULL), + rnode(RO2UP("a/b/d"), NULL), + rnode(RO2UP("a/b/e"), NULL), + rnode(RO2UP("a/b/f"), NULL), NULL); + a = rnode(RO2UP("a"), b, - runode(RO2UP("a/g"), - runode(RO2UP("a/g/h"), - runode(RO2UP("a/g/h/i"), NULL), NULL), - runode(RO2UP("a/g/j"), - runode(RO2UP("a/g/j/k"), NULL), NULL), - runode(RO2UP("a/g/l"), - runode(RO2UP("a/g/l/m"), NULL), NULL), - runode(RO2UP("a/g/n"), - runode(RO2UP("a/g/n/o"), NULL), NULL), NULL), NULL); - root = runode(RE2UP, a, NULL); + rnode(RO2UP("a/g"), + rnode(RO2UP("a/g/h"), + rnode(RO2UP("a/g/h/i"), NULL), NULL), + rnode(RO2UP("a/g/j"), + rnode(RO2UP("a/g/j/k"), NULL), NULL), + rnode(RO2UP("a/g/l"), + rnode(RO2UP("a/g/l/m"), NULL), NULL), + rnode(RO2UP("a/g/n"), + rnode(RO2UP("a/g/n/o"), NULL), NULL), NULL), NULL); + root = rnode(RE2UP, a, NULL); dn = 0; cachent_delete(b); @@ -111,7 +111,7 @@ ck_traverse(struct cache_node *root, ...) expected[p] = NULL; e = 0; - ck_assert_int_eq(0, cachent_traverse(root, ck_traverse_cb)); + cachent_traverse(root, ck_traverse_cb); ck_assert_uint_eq(p, e); cachent_delete(root); @@ -124,36 +124,36 @@ START_TEST(test_traverse) root = NULL; ck_traverse(root, NULL); - root = runode(RO2UP("a"), NULL); + root = rnode(RO2UP("a"), NULL); ck_traverse(root, "tmp/rsync/a", NULL); - root = runode(RO2UP("a"), - runode(RO2UP("a/b"), NULL), NULL); + root = rnode(RO2UP("a"), + rnode(RO2UP("a/b"), NULL), NULL); ck_traverse(root, "tmp/rsync/a", "tmp/rsync/a/b", NULL); - root = runode(RO2UP("a"), - runode(RO2UP("a/b"), - runode(RO2UP("a/b/c"), NULL), NULL), NULL); + root = rnode(RO2UP("a"), + rnode(RO2UP("a/b"), + rnode(RO2UP("a/b/c"), NULL), NULL), NULL); ck_traverse(root, "tmp/rsync/a", "tmp/rsync/a/b", "tmp/rsync/a/b/c", NULL); - root = runode(RO2UP("a"), - runode(RO2UP("a/b"), - runode(RO2UP("a/b/c"), NULL), - runode(RO2UP("a/b/d"), NULL), NULL), NULL); + root = rnode(RO2UP("a"), + rnode(RO2UP("a/b"), + rnode(RO2UP("a/b/c"), NULL), + rnode(RO2UP("a/b/d"), NULL), NULL), NULL); ck_traverse(root, "tmp/rsync/a", "tmp/rsync/a/b", "tmp/rsync/a/b/c", "tmp/rsync/a/b/d", NULL); - root = runode(RO2UP("a"), - runode(RO2UP("a/b"), - runode(RO2UP("a/b/c"), NULL), - runode(RO2UP("a/b/d"), NULL), NULL), - runode(RO2UP("a/e"), NULL), NULL); + root = rnode(RO2UP("a"), + rnode(RO2UP("a/b"), + rnode(RO2UP("a/b/c"), NULL), + rnode(RO2UP("a/b/d"), NULL), NULL), + rnode(RO2UP("a/e"), NULL), NULL); ck_traverse(root, "tmp/rsync/a", "tmp/rsync/a/b", @@ -161,11 +161,11 @@ START_TEST(test_traverse) "tmp/rsync/a/b/d", "tmp/rsync/a/e", NULL); - root = runode(RO2UP("a"), - runode(RO2UP("a/b"), NULL), - runode(RO2UP("a/c"), - runode(RO2UP("a/c/d"), NULL), - runode(RO2UP("a/c/e"), NULL), NULL), NULL); + root = rnode(RO2UP("a"), + rnode(RO2UP("a/b"), NULL), + rnode(RO2UP("a/c"), + rnode(RO2UP("a/c/d"), NULL), + rnode(RO2UP("a/c/e"), NULL), NULL), NULL); ck_traverse(root, "tmp/rsync/a", "tmp/rsync/a/b", @@ -173,13 +173,13 @@ START_TEST(test_traverse) "tmp/rsync/a/c/d", "tmp/rsync/a/c/e", NULL); - root = runode(RO2UP("a"), - runode(RO2UP("a/b"), - runode(RO2UP("a/b/c"), NULL), - runode(RO2UP("a/b/d"), NULL), NULL), - runode(RO2UP("a/e"), - runode(RO2UP("a/e/f"), NULL), - runode(RO2UP("a/e/g"), NULL), NULL), NULL); + root = rnode(RO2UP("a"), + rnode(RO2UP("a/b"), + rnode(RO2UP("a/b/c"), NULL), + rnode(RO2UP("a/b/d"), NULL), NULL), + rnode(RO2UP("a/e"), + rnode(RO2UP("a/e/f"), NULL), + rnode(RO2UP("a/e/g"), NULL), NULL), NULL); ck_traverse(root, "tmp/rsync/a", "tmp/rsync/a/b", @@ -189,21 +189,21 @@ START_TEST(test_traverse) "tmp/rsync/a/e/f", "tmp/rsync/a/e/g", NULL); - root = runode(RO2UP("a"), - runode(RO2UP("a/b"), - runode(RO2UP("a/b/c"), NULL), - runode(RO2UP("a/b/d"), NULL), - runode(RO2UP("a/b/e"), NULL), - runode(RO2UP("a/b/f"), NULL), NULL), - runode(RO2UP("a/g"), - runode(RO2UP("a/g/h"), - runode(RO2UP("a/g/h/i"), NULL), NULL), - runode(RO2UP("a/g/j"), - runode(RO2UP("a/g/j/k"), NULL), NULL), - runode(RO2UP("a/g/l"), - runode(RO2UP("a/g/l/m"), NULL), NULL), - runode(RO2UP("a/g/n"), - runode(RO2UP("a/g/n/o"), NULL), NULL), NULL), NULL); + root = rnode(RO2UP("a"), + rnode(RO2UP("a/b"), + rnode(RO2UP("a/b/c"), NULL), + rnode(RO2UP("a/b/d"), NULL), + rnode(RO2UP("a/b/e"), NULL), + rnode(RO2UP("a/b/f"), NULL), NULL), + rnode(RO2UP("a/g"), + rnode(RO2UP("a/g/h"), + rnode(RO2UP("a/g/h/i"), NULL), NULL), + rnode(RO2UP("a/g/j"), + rnode(RO2UP("a/g/j/k"), NULL), NULL), + rnode(RO2UP("a/g/l"), + rnode(RO2UP("a/g/l/m"), NULL), NULL), + rnode(RO2UP("a/g/n"), + rnode(RO2UP("a/g/n/o"), NULL), NULL), NULL), NULL); ck_traverse(root, "tmp/rsync/a", "tmp/rsync/a/b", diff --git a/test/mock.c b/test/mock.c index 7df1a8e4..b420710c 100644 --- a/test/mock.c +++ b/test/mock.c @@ -124,3 +124,7 @@ MOCK_NULL(config_get_output_roa, char const *, void) 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_push, char const *file) +MOCK_VOID(fnstack_push_map, struct cache_mapping *map) +MOCK_VOID(fnstack_pop, void) diff --git a/test/object/manifest_test.c b/test/object/manifest_test.c new file mode 100644 index 00000000..823efdcd --- /dev/null +++ b/test/object/manifest_test.c @@ -0,0 +1,98 @@ +#include +#include + +#include "alloc.c" +#include "cachent.c" +#include "common.c" +#include "mock.c" +#include "object/manifest.c" +#include "types/map.c" +#include "types/path.c" +#include "types/url.c" + +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) + +#define BUFFER_LEN 128 +static uint8_t buffer[BUFFER_LEN]; + +static int +__test_validate(char const *src, size_t len) +{ + IA5String_t dst; + unsigned int i; + + memcpy(buffer, src, len); + for (i = len; i < BUFFER_LEN - 1; i++) + buffer[i] = '_'; + buffer[BUFFER_LEN - 1] = 0; + + dst.buf = buffer; + dst.size = len; + + return validate_mft_file(&dst); +} + +#define test_validate(str) __test_validate(str, sizeof(str) - 1) + +START_TEST(check_validate_current_directory) +{ + ck_assert_int_eq(-EINVAL, test_validate("")); + ck_assert_int_eq(-EINVAL, test_validate(".")); + ck_assert_int_eq(-EINVAL, test_validate("..")); + + ck_assert_int_eq(-EINVAL, test_validate("filename")); + ck_assert_int_eq(-EINVAL, test_validate("filename.")); + ck_assert_int_eq(-EINVAL, test_validate("filename.a")); + ck_assert_int_eq(-EINVAL, test_validate("filename.ab")); + ck_assert_int_eq(0, test_validate("filename.abc")); + ck_assert_int_eq(-EINVAL, test_validate("file.abcd")); + + ck_assert_int_eq(0, test_validate("file-name.ABC")); + ck_assert_int_eq(0, test_validate("file_name.123")); + ck_assert_int_eq(0, test_validate("file0name.aB2")); + ck_assert_int_eq(0, test_validate("file9name.---")); + ck_assert_int_eq(0, test_validate("FileName.A3_")); + ck_assert_int_eq(-EINVAL, test_validate("file.name.abc")); + ck_assert_int_eq(-EINVAL, test_validate("file/name.abc")); + ck_assert_int_eq(-EINVAL, test_validate("file\0name.abc")); + ck_assert_int_eq(-EINVAL, test_validate("filename.abc\0filename.abc")); + ck_assert_int_eq(-EINVAL, test_validate("filenameabc\0filename.abc")); + ck_assert_int_eq(0, test_validate("-.---")); + + ck_assert_int_eq(0, test_validate("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890-_.-_-")); + ck_assert_int_eq(0, test_validate("vixxBTS_TVXQ-2pmGOT7.cer")); +} +END_TEST + +static Suite * +mft_suite(void) +{ + Suite *suite; + TCase *core; + + core = tcase_create("core"); + tcase_add_test(core, check_validate_current_directory); + + suite = suite_create("mft"); + suite_add_tcase(suite, core); + return suite; +} + +int +main(int argc, char **argv) +{ + Suite *suite; + SRunner *runner; + int tests_failed; + + suite = mft_suite(); + + runner = srunner_create(suite); + srunner_run_all(runner, CK_NORMAL); + tests_failed = srunner_ntests_failed(runner); + srunner_free(runner); + + return (tests_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/test/rrdp_test.c b/test/rrdp_test.c index 20c379ef..4041892c 100644 --- a/test/rrdp_test.c +++ b/test/rrdp_test.c @@ -18,8 +18,6 @@ /* Mocks */ -MOCK_VOID(fnstack_push, char const *file) -MOCK_VOID(fnstack_pop, void) MOCK_VOID(__delete_node_cb, struct cache_node const *node) MOCK_ABORT_INT(http_download, char const *url, char const *path, curl_off_t ims, bool *changed) diff --git a/test/rrdp_update_test.c b/test/rrdp_update_test.c index 303fc904..17cb8239 100644 --- a/test/rrdp_update_test.c +++ b/test/rrdp_update_test.c @@ -18,8 +18,6 @@ /* Mocks */ -MOCK_VOID(fnstack_push, char const *file) -MOCK_VOID(fnstack_pop, void) MOCK_VOID(__delete_node_cb, struct cache_node const *node) /* Utils */ @@ -97,10 +95,10 @@ START_TEST(startup) ck_assert_uint_eq(2, https_counter); ck_file("tmp/tmp/0/a/b/c.cer"); ck_assert_cachent_eq( - ruftnode("rsync://", NOTIF_PATH, 0, "tmp/tmp/0", - ruftnode("rsync://a", NOTIF_PATH "/a", 0, "tmp/tmp/0/a", - ruftnode("rsync://a/b", NOTIF_PATH "/a/b", 0, "tmp/tmp/0/a/b", - ruftnode("rsync://a/b/c.cer", NOTIF_PATH "/a/b/c.cer", 0, "tmp/tmp/0/a/b/c.cer", NULL), + rftnode("rsync://", NOTIF_PATH, 0, "tmp/tmp/0", + rftnode("rsync://a", NOTIF_PATH "/a", 0, "tmp/tmp/0/a", + rftnode("rsync://a/b", NOTIF_PATH "/a/b", 0, "tmp/tmp/0/a/b", + rftnode("rsync://a/b/c.cer", NOTIF_PATH "/a/b/c.cer", 0, "tmp/tmp/0/a/b/c.cer", NULL), NULL), NULL), NULL), @@ -113,10 +111,10 @@ START_TEST(startup) ck_assert_uint_eq(1, https_counter); ck_file("tmp/tmp/0/a/b/c.cer"); ck_assert_cachent_eq( - ruftnode("rsync://", NOTIF_PATH, 0, "tmp/tmp/0", - ruftnode("rsync://a", NOTIF_PATH "/a", 0, "tmp/tmp/0/a", - ruftnode("rsync://a/b", NOTIF_PATH "/a/b", 0, "tmp/tmp/0/a/b", - ruftnode("rsync://a/b/c.cer", NOTIF_PATH "/a/b/c.cer", 0, "tmp/tmp/0/a/b/c.cer", NULL), + rftnode("rsync://", NOTIF_PATH, 0, "tmp/tmp/0", + rftnode("rsync://a", NOTIF_PATH "/a", 0, "tmp/tmp/0/a", + rftnode("rsync://a/b", NOTIF_PATH "/a/b", 0, "tmp/tmp/0/a/b", + rftnode("rsync://a/b/c.cer", NOTIF_PATH "/a/b/c.cer", 0, "tmp/tmp/0/a/b/c.cer", NULL), NULL), NULL), NULL), diff --git a/test/tal_test.c b/test/tal_test.c index aacfe6d7..a64ac582 100644 --- a/test/tal_test.c +++ b/test/tal_test.c @@ -16,13 +16,8 @@ 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, struct rpki_cache *cache, - struct cache_mapping *map, bool *changed, - struct cachefile_notification ***notif) MOCK_ABORT_INT(cache_download_alt, struct sia_uris *sias, - maps_dl_cb cb, void *arg) -MOCK_ABORT_PTR(cache_recover, cache_mapping, struct rpki_cache *cache, - struct map_list *maps) + 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, @@ -32,9 +27,6 @@ MOCK_VOID(db_table_destroy, struct db_table *table) MOCK_ABORT_INT(db_table_join, struct db_table *dst, struct db_table *src) MOCK_ABORT_INT(deferstack_pop, struct cert_stack *stack, struct deferred_cert *result) -MOCK_ABORT_VOID(fnstack_cleanup, void) -MOCK_ABORT_VOID(fnstack_init, void) -MOCK_ABORT_VOID(fnstack_push, char const *f) MOCK_ABORT_INT(handle_roa_v4, uint32_t as, struct ipv4_prefix const *prefix, uint8_t max_length, void *arg) MOCK_ABORT_INT(handle_roa_v6, uint32_t as, struct ipv6_prefix const *prefix, @@ -42,7 +34,6 @@ MOCK_ABORT_INT(handle_roa_v6, uint32_t as, struct ipv6_prefix const *prefix, MOCK_ABORT_INT(handle_router_key, unsigned char const *ski, struct asn_range const *asns, unsigned char const *spk, void *arg) MOCK_ABORT_VOID(rpp_refput, struct rpp *pp) -MOCK_ABORT_INT(rrdp_update, struct cache_node *notif) MOCK(state_retrieve, struct validation *, NULL, void) MOCK_ABORT_PTR(validation_certstack, cert_stack, struct validation *state) MOCK_ABORT_VOID(validation_destroy, struct validation *state) diff --git a/test/types/map_test.c b/test/types/map_test.c deleted file mode 100644 index cd901ce6..00000000 --- a/test/types/map_test.c +++ /dev/null @@ -1,234 +0,0 @@ -#include -#include -#include - -#include "alloc.c" -#include "common.c" -#include "mock.c" -#include "types/map.c" -#include "types/path.c" - -/* Mocks */ - -static struct cache_mapping *notif; - -MOCK(state_retrieve, struct validation *, NULL, void) -MOCK(validation_tal, struct tal *, NULL, struct validation *state) -MOCK(tal_get_file_name, char const *, NULL, struct tal *tal) - -int -cache_tmpfile(char **filename) -{ - static unsigned int used = 1; - - if (used > 2) { - ck_abort_msg("cache_tmpfile() called a third time!"); - return -EINVAL; - } - - *filename = pstrdup("tmp/tmp/0"); - used = true; - return 0; -} - -/* Tests */ - -#define MAP_CREATE_HTTP(map, str) map_create(&map, MAP_HTTP, str) -#define MAP_CREATE(map, type, str) map_create(&map, type, str) - -START_TEST(test_constructor) -{ - struct cache_mapping *map; - - ck_assert_int_eq(ENOTHTTPS, MAP_CREATE_HTTP(map, "")); - ck_assert_int_eq(ENOTHTTPS, MAP_CREATE_HTTP(map, "h")); - ck_assert_int_eq(ENOTHTTPS, MAP_CREATE_HTTP(map, "http")); - ck_assert_int_eq(ENOTHTTPS, MAP_CREATE_HTTP(map, "https")); - ck_assert_int_eq(ENOTHTTPS, MAP_CREATE_HTTP(map, "https:")); - ck_assert_int_eq(ENOTHTTPS, MAP_CREATE_HTTP(map, "https:/")); - ck_assert_int_eq(-EINVAL, MAP_CREATE_HTTP(map, "https://")); - - ck_assert_int_eq(0, MAP_CREATE_HTTP(map, "https://a.b.c")); - ck_assert_str_eq("https://a.b.c", map_get_url(map)); - ck_assert_str_eq("tmp/https/a.b.c", map_get_path(map)); - map_refput(map); - - ck_assert_int_eq(0, MAP_CREATE_HTTP(map, "https://a.b.c/")); - ck_assert_str_eq("https://a.b.c", map_get_url(map)); - ck_assert_str_eq("tmp/https/a.b.c", map_get_path(map)); - map_refput(map); - - ck_assert_int_eq(0, MAP_CREATE_HTTP(map, "https://a.b.c/d")); - ck_assert_str_eq("https://a.b.c/d", map_get_url(map)); - ck_assert_str_eq("tmp/https/a.b.c/d", map_get_path(map)); - map_refput(map); - - ck_assert_int_eq(0, MAP_CREATE_HTTP(map, "https://a.b.c/d/e")); - ck_assert_str_eq("https://a.b.c/d/e", map_get_url(map)); - ck_assert_str_eq("tmp/https/a.b.c/d/e", map_get_path(map)); - map_refput(map); - - ck_assert_int_eq(0, MAP_CREATE_HTTP(map, "https://a.b.c/d/..")); - ck_assert_str_eq("https://a.b.c", map_get_url(map)); - ck_assert_str_eq("tmp/https/a.b.c", map_get_path(map)); - map_refput(map); - - ck_assert_int_eq(0, MAP_CREATE_HTTP(map, "https://a.b.c/.")); - ck_assert_str_eq("https://a.b.c", map_get_url(map)); - ck_assert_str_eq("tmp/https/a.b.c", map_get_path(map)); - map_refput(map); - - ck_assert_int_eq(0, MAP_CREATE_HTTP(map, "https://a.b.c/././d/././e/./.")); - ck_assert_str_eq("https://a.b.c/d/e", map_get_url(map)); - ck_assert_str_eq("tmp/https/a.b.c/d/e", map_get_path(map)); - map_refput(map); - - ck_assert_int_eq(0, MAP_CREATE_HTTP(map, "https://a.b.c/a/b/.././..")); - ck_assert_str_eq("https://a.b.c", map_get_url(map)); - ck_assert_str_eq("tmp/https/a.b.c", map_get_path(map)); - map_refput(map); - - ck_assert_int_eq(-EINVAL, MAP_CREATE_HTTP(map, "https://a.b.c/..")); - ck_assert_int_eq(-EINVAL, MAP_CREATE_HTTP(map, "https://a.b.c/../..")); - ck_assert_int_eq(-EINVAL, MAP_CREATE_HTTP(map, "https://a.b.c/d/../..")); - ck_assert_int_eq(-EINVAL, MAP_CREATE_HTTP(map, "https://a.b.c/d/../../..")); - ck_assert_int_eq(-EINVAL, MAP_CREATE_HTTP(map, "https://.")); - ck_assert_int_eq(-EINVAL, MAP_CREATE_HTTP(map, "https://./.")); - ck_assert_int_eq(-EINVAL, MAP_CREATE_HTTP(map, "https://..")); - ck_assert_int_eq(-EINVAL, MAP_CREATE_HTTP(map, "https://../..")); - ck_assert_int_eq(-EINVAL, MAP_CREATE_HTTP(map, "https://../../..")); - - ck_assert_int_eq(ENOTHTTPS, MAP_CREATE_HTTP(map, "rsync://a.b.c/d")); - ck_assert_int_eq(ENOTHTTPS, MAP_CREATE_HTTP(map, "http://a.b.c/d")); - ck_assert_int_eq(ENOTRSYNC, MAP_CREATE(map, MAP_RSYNC, "https://a.b.c/d")); - - ck_assert_int_eq(0, MAP_CREATE(map, MAP_RSYNC, "rsync://a.b.c/d")); - ck_assert_str_eq("rsync://a.b.c/d", map_get_url(map)); - ck_assert_str_eq("tmp/rsync/a.b.c/d", map_get_path(map)); - map_refput(map); - - ck_assert_int_eq(0, MAP_CREATE(map, MAP_RSYNC, "rsync://a.b.c/d.cer")); - ck_assert_str_eq("rsync://a.b.c/d.cer", map_get_url(map)); - ck_assert_str_eq("tmp/rsync/a.b.c/d.cer", map_get_path(map)); - map_refput(map); - - ck_assert_int_eq(0, MAP_CREATE(map, MAP_NOTIF, "https://a.b.c/notification.xml")); - ck_assert_str_eq("https://a.b.c/notification.xml", map_get_url(map)); - ck_assert_str_eq("tmp/tmp/0", map_get_path(map)); - map_refput(map); - - /* XXX - ck_assert_int_eq(0, MAP_CREATE(map, MAP_TMP, "https://a.b.c/snapshot.xml")); - ck_assert_str_eq("https://a.b.c/snapshot.xml", map_get_url(map)); - ck_assert_str_eq("tmp/tmp/0", map_get_path(map)); - map_refput(map); - */ -} -END_TEST - -/* -#define BUFFER_LEN 128 -static uint8_t buffer[BUFFER_LEN]; - -static int -__test_validate(char const *src, size_t len) -{ - IA5String_t dst; - unsigned int i; - - memcpy(buffer, src, len); - for (i = len; i < BUFFER_LEN - 1; i++) - buffer[i] = '_'; - buffer[BUFFER_LEN - 1] = 0; - - dst.buf = buffer; - dst.size = len; - - return validate_mft_file(&dst); -} - -#define test_validate(str) __test_validate(str, sizeof(str) - 1) -*/ - -START_TEST(check_validate_current_directory) -{ - /* XXX wtf is this doing in the map test? - ck_assert_int_eq(-EINVAL, test_validate("")); - ck_assert_int_eq(-EINVAL, test_validate(".")); - ck_assert_int_eq(-EINVAL, test_validate("..")); - - ck_assert_int_eq(-EINVAL, test_validate("filename")); - ck_assert_int_eq(-EINVAL, test_validate("filename.")); - ck_assert_int_eq(-EINVAL, test_validate("filename.a")); - ck_assert_int_eq(-EINVAL, test_validate("filename.ab")); - ck_assert_int_eq(0, test_validate("filename.abc")); - ck_assert_int_eq(-EINVAL, test_validate("file.abcd")); - - ck_assert_int_eq(0, test_validate("file-name.ABC")); - ck_assert_int_eq(0, test_validate("file_name.123")); - ck_assert_int_eq(0, test_validate("file0name.aB2")); - ck_assert_int_eq(0, test_validate("file9name.---")); - ck_assert_int_eq(0, test_validate("FileName.A3_")); - ck_assert_int_eq(-EINVAL, test_validate("file.name.abc")); - ck_assert_int_eq(-EINVAL, test_validate("file/name.abc")); - ck_assert_int_eq(-EINVAL, test_validate("file\0name.abc")); - ck_assert_int_eq(-EINVAL, test_validate("filename.abc\0filename.abc")); - ck_assert_int_eq(-EINVAL, test_validate("filenameabc\0filename.abc")); - ck_assert_int_eq(0, test_validate("-.---")); - - ck_assert_int_eq(0, test_validate("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890-_.-_-")); - ck_assert_int_eq(0, test_validate("vixxBTS_TVXQ-2pmGOT7.cer")); - */ -} -END_TEST - -START_TEST(check_caged) -{ - /* XXX - struct cache_mapping *map; - - ck_assert_int_eq(0, map_create(¬if, MAP_NOTIF, "https://a.b.c/d/e.xml")); - ck_assert_int_eq(0, map_create(&map, MAP_CAGED, notif, "rsync://x.y.z/v/w.cer")); - ck_assert_str_eq("tmp/rrdp/a.b.c/d/e.xml/x.y.z/v/w.cer", map_get_path(map)); - map_refput(map); - map_refput(notif); - - ck_assert_int_eq(0, map_create(¬if, MAP_NOTIF, "https://a.b.c")); - ck_assert_int_eq(0, map_create(&map, MAP_CAGED, notif, "rsync://w")); - ck_assert_str_eq("tmp/rrdp/a.b.c/w", map_get_path(map)); - map_refput(map); - map_refput(notif); - */ -} -END_TEST - -static Suite *address_load_suite(void) -{ - Suite *suite; - TCase *core; - - core = tcase_create("Core"); - tcase_add_test(core, test_constructor); - tcase_add_test(core, check_validate_current_directory); - tcase_add_test(core, check_caged); - - suite = suite_create("Encoding checking"); - suite_add_tcase(suite, core); - return suite; -} - -int main(void) -{ - Suite *suite; - SRunner *runner; - int tests_failed; - - suite = address_load_suite(); - - runner = srunner_create(suite); - srunner_run_all(runner, CK_NORMAL); - tests_failed = srunner_ntests_failed(runner); - srunner_free(runner); - - return (tests_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; -} diff --git a/test/types/url_test.c b/test/types/url_test.c index 8d20ab30..7decf000 100644 --- a/test/types/url_test.c +++ b/test/types/url_test.c @@ -17,21 +17,36 @@ START_TEST(test_normalize) TEST_NORMALIZE("rsync://a.b.c", "rsync://a.b.c"); TEST_NORMALIZE("rsync://a.b.c/", "rsync://a.b.c"); + TEST_NORMALIZE("rsync://a.b.c/d", "rsync://a.b.c/d"); TEST_NORMALIZE("rsync://a.b.c//////", "rsync://a.b.c"); TEST_NORMALIZE("rsync://a.b.c/d/e", "rsync://a.b.c/d/e"); TEST_NORMALIZE("rsync://a.b.c/d/e/.", "rsync://a.b.c/d/e"); TEST_NORMALIZE("rsync://a.b.c/d/e/.", "rsync://a.b.c/d/e"); - TEST_NORMALIZE("rsync://a.b.c/d/./e/.", "rsync://a.b.c/d/e"); + TEST_NORMALIZE("rsync://a.b.c/././d/././e/./.", "rsync://a.b.c/d/e"); + TEST_NORMALIZE("rsync://a.b.c/d/..", "rsync://a.b.c"); TEST_NORMALIZE("rsync://a.b.c/x/../x/y/z", "rsync://a.b.c/x/y/z"); TEST_NORMALIZE("rsync://a.b.c/d/../d/../d/e/", "rsync://a.b.c/d/e"); TEST_NORMALIZE("rsync://x//y/z/../../m/./n/o", "rsync://x/m/n/o"); + + ck_assert_ptr_eq(NULL, url_normalize("")); + ck_assert_ptr_eq(NULL, url_normalize("h")); + ck_assert_ptr_eq(NULL, url_normalize("http")); + ck_assert_ptr_eq(NULL, url_normalize("https")); + ck_assert_ptr_eq(NULL, url_normalize("https:")); + ck_assert_ptr_eq(NULL, url_normalize("https:/")); ck_assert_ptr_eq(NULL, url_normalize("rsync://")); ck_assert_ptr_eq(NULL, url_normalize("rsync://.")); + ck_assert_ptr_eq(NULL, url_normalize("https://./.")); + ck_assert_ptr_eq(NULL, url_normalize("https://./d")); ck_assert_ptr_eq(NULL, url_normalize("rsync://..")); + ck_assert_ptr_eq(NULL, url_normalize("rsync://../..")); + ck_assert_ptr_eq(NULL, url_normalize("rsync://../d")); ck_assert_ptr_eq(NULL, url_normalize("rsync://a.b.c/..")); + ck_assert_ptr_eq(NULL, url_normalize("rsync://a.b.c/../..")); ck_assert_ptr_eq(NULL, url_normalize("rsync://a.b.c/../x")); ck_assert_ptr_eq(NULL, url_normalize("rsync://a.b.c/../x/y/z")); ck_assert_ptr_eq(NULL, url_normalize("rsync://a.b.c/d/e/../../..")); + ck_assert_ptr_eq(NULL, url_normalize("http://a.b.c/d")); ck_assert_ptr_eq(NULL, url_normalize("abcde://a.b.c/d")); } END_TEST -- 2.47.2