From: Alberto Leiva Popper Date: Fri, 1 Mar 2024 21:25:54 +0000 (-0600) Subject: Add several values to uri_type X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e41ddbb51804f4df68191913f896b0e62f671ac9;p=thirdparty%2FFORT-validator.git Add several values to uri_type In the upcoming commits, the cache is going to need to start managing the notifications differently from the other downloadables, including snapshots and deltas. The logic used to differentiate the different objects from each other was getting convoluted, and had been naturally converging into the URI object since the 1.6.0 refactors, IIRC. So stop beating around the bush and commit to this design. Store the type in the URI object, and add several values to the uri_type enum. --- diff --git a/src/cache/local_cache.c b/src/cache/local_cache.c index 4550ecb6..3f431d67 100644 --- a/src/cache/local_cache.c +++ b/src/cache/local_cache.c @@ -49,11 +49,16 @@ struct rpki_cache { #define TMPDIR "tmp" #define TAL_METAFILE "tal.json" +#define TAGNAME_TYPE "type" #define TAGNAME_URL "url" #define TAGNAME_ATTEMPT_TS "attempt-timestamp" #define TAGNAME_ATTEMPT_ERR "attempt-result" #define TAGNAME_SUCCESS_TS "success-timestamp" -#define TAGNAME_IS_NOTIF "is-rrdp-notification" + +#define TYPEVALUE_TA_RSYNC "TA (rsync)" +#define TYPEVALUE_TA_HTTP "TA (HTTP)" +#define TYPEVALUE_RPP "RPP" +#define TYPEVALUE_NOTIF "RRDP Notification" static atomic_uint file_counter; @@ -243,34 +248,41 @@ static struct cache_node * json2node(struct rpki_cache *cache, json_t *json) { struct cache_node *node; - char const *url; - bool is_notif; + char const *type_str; enum uri_type type; + char const *url; int error; node = pzalloc(sizeof(struct cache_node)); - error = json_get_str(json, TAGNAME_URL, &url); + error = json_get_str(json, TAGNAME_TYPE, &type_str); if (error) { if (error > 0) - pr_op_err("Node is missing the '" TAGNAME_URL "' tag."); + pr_op_err("Node is missing the '" TAGNAME_TYPE "' tag."); goto fail; } - if (str_starts_with(url, "https://")) - type = UT_HTTPS; - else if (str_starts_with(url, "rsync://")) - type = UT_RSYNC; + if (strcmp(type_str, TYPEVALUE_TA_RSYNC) == 0) + type = UT_TA_RSYNC; + else if (strcmp(type_str, TYPEVALUE_TA_HTTP) == 0) + type = UT_TA_HTTP; + else if (strcmp(type_str, TYPEVALUE_RPP) == 0) + type = UT_RPP; + else if (strcmp(type_str, TYPEVALUE_NOTIF) == 0) + type = UT_NOTIF; else { - pr_op_err("Unknown protocol: %s", url); + pr_op_err("Unknown node type: %s", type_str); goto fail; } - error = json_get_bool(json, TAGNAME_IS_NOTIF, &is_notif); - if (error < 0) + error = json_get_str(json, TAGNAME_URL, &url); + if (error) { + if (error > 0) + pr_op_err("Node is missing the '" TAGNAME_URL "' tag."); goto fail; + } - error = uri_create(&node->url, cache->tal, type, is_notif, NULL, url); + error = uri_create(&node->url, cache->tal, type, NULL, url); if (error) { pr_op_err("Cannot parse '%s' into a URI.", url); goto fail; @@ -302,11 +314,10 @@ fail: } static struct cache_node* -find_node(struct rpki_cache *cache, struct rpki_uri *uri) +find_node(struct rpki_cache *cache, char const *luri) { - char const *key = uri_get_local(uri); struct cache_node *result; - HASH_FIND_STR(cache->ht, key, result); + HASH_FIND_STR(cache->ht, luri, result); return result; } @@ -380,18 +391,33 @@ static json_t * node2json(struct cache_node *node) { json_t *json; + char const *type; json = json_object(); - if (json == NULL) { - pr_op_err("json object allocation failure."); - return NULL; + if (json == NULL) + enomem_panic(); + + switch (uri_get_type(node->url)) { + case UT_TA_RSYNC: + type = TYPEVALUE_TA_RSYNC; + break; + case UT_TA_HTTP: + type = TYPEVALUE_TA_HTTP; + break; + case UT_RPP: + type = TYPEVALUE_RPP; + break; + case UT_NOTIF: + type = TYPEVALUE_NOTIF; + break; + default: + goto cancel; } + if (json_add_str(json, TAGNAME_TYPE, type)) + goto cancel; if (json_add_str(json, TAGNAME_URL, uri_get_global(node->url))) goto cancel; - if (uri_is_notif(node->url)) - if (json_add_bool(json, TAGNAME_IS_NOTIF, true)) - goto cancel; if (json_add_date(json, TAGNAME_ATTEMPT_TS, node->attempt.ts)) goto cancel; if (json_add_int(json, TAGNAME_ATTEMPT_ERR, node->attempt.result)) @@ -460,7 +486,7 @@ get_url(struct rpki_uri *uri, const char *tal, struct rpki_uri **url) unsigned int slashes; int error; - if (uri_get_type(uri) != UT_RSYNC) { + if (uri_get_type(uri) != UT_RPP) { uri_refget(uri); *url = uri; return 0; @@ -516,7 +542,7 @@ get_url(struct rpki_uri *uri, const char *tal, struct rpki_uri **url) if (*c == '/') { slashes++; if (slashes == 4) - return __uri_create(url, tal, UT_RSYNC, false, + return __uri_create(url, tal, UT_RPP, NULL, guri, c - guri + 1); } } @@ -524,7 +550,7 @@ get_url(struct rpki_uri *uri, const char *tal, struct rpki_uri **url) if (slashes == 3 && *(c - 1) != '/') { guri2 = pstrdup(guri); /* Remove const */ guri2[c - guri] = '/'; - error = __uri_create(url, tal, UT_RSYNC, false, NULL, guri2, + error = __uri_create(url, tal, UT_RPP, NULL, guri2, c - guri + 1); free(guri2); return error; @@ -566,10 +592,11 @@ cache_check(struct rpki_uri *url) } /** - * @changed only on HTTP. + * @ims and @changed only on HTTP. */ int -cache_download(struct rpki_cache *cache, struct rpki_uri *uri, bool *changed) +cache_download(struct rpki_cache *cache, struct rpki_uri *uri, + curl_off_t ims, bool *changed) { struct rpki_uri *url; struct cache_node *node; @@ -582,7 +609,7 @@ cache_download(struct rpki_cache *cache, struct rpki_uri *uri, bool *changed) if (error) return error; - node = find_node(cache, url); + node = find_node(cache, uri_get_local(url)); if (node != NULL) { uri_refput(url); if (was_recently_downloaded(cache, node)) @@ -595,18 +622,21 @@ cache_download(struct rpki_cache *cache, struct rpki_uri *uri, bool *changed) } switch (uri_get_type(url)) { - case UT_RSYNC: + case UT_TA_HTTP: + case UT_NOTIF: + case UT_TMP: + error = config_get_http_enabled() + ? http_download(url, ims, changed) + : cache_check(url); + break; + case UT_TA_RSYNC: + case UT_RPP: error = config_get_rsync_enabled() ? rsync_download(url) : cache_check(url); break; - case UT_HTTPS: - error = config_get_http_enabled() - ? http_download(url, changed) - : cache_check(url); - break; default: - pr_crit("Unexpected URI type: %d", uri_get_type(url)); + pr_crit("URI type not downloadable: %d", uri_get_type(url)); } node->attempt.ts = time(NULL); @@ -622,32 +652,43 @@ cache_download(struct rpki_cache *cache, struct rpki_uri *uri, bool *changed) } static int -download(struct rpki_cache *cache, struct rpki_uri *uri, bool use_rrdp, - uris_dl_cb cb, void *arg) +download(struct rpki_cache *cache, struct rpki_uri *uri, uris_dl_cb cb, void *arg) { + time_t ims = 0; int error; pr_val_debug("Trying URL %s...", uri_get_global(uri)); - error = (use_rrdp && (uri_get_type(uri) == UT_HTTPS)) - ? rrdp_update(uri) - : cache_download(cache, uri, NULL); - if (error) - return 1; + switch (uri_get_type(uri)) { + case UT_TA_HTTP: + error = file_get_mtim(uri_get_local(uri), &ims); + if (error) + break; + /* Fall through */ + case UT_TA_RSYNC: + case UT_RPP: + error = cache_download(cache, uri, ims, NULL); + break; + case UT_NOTIF: + error = rrdp_update(uri); + break; + default: + pr_crit("URI type is not a legal alt candidate: %u", uri_get_type(uri)); + } - return cb(uri, arg); + return error ? 1 : cb(uri, arg); } static int download_uris(struct rpki_cache *cache, struct uri_list *uris, - enum uri_type type, bool use_rrdp, uris_dl_cb cb, void *arg) + enum uri_type type, uris_dl_cb cb, void *arg) { struct rpki_uri **uri; int error; ARRAYLIST_FOREACH(uris, uri) { if (uri_get_type(*uri) == type) { - error = download(cache, *uri, use_rrdp, cb, arg); + error = download(cache, *uri, cb, arg); if (error <= 0) return error; } @@ -670,36 +711,36 @@ download_uris(struct rpki_cache *cache, struct uri_list *uris, */ int cache_download_alt(struct rpki_cache *cache, struct uri_list *uris, - bool use_rrdp, uris_dl_cb cb, void *arg) + enum uri_type http_type, enum uri_type rsync_type, uris_dl_cb cb, void *arg) { struct rpki_uri **cursor, *uri; int error; if (config_get_http_priority() > config_get_rsync_priority()) { - error = download_uris(cache, uris, UT_HTTPS, use_rrdp, cb, arg); + error = download_uris(cache, uris, http_type, cb, arg); if (error <= 0) return error; - error = download_uris(cache, uris, UT_RSYNC, use_rrdp, cb, arg); + error = download_uris(cache, uris, rsync_type, cb, arg); if (error <= 0) return error; } else if (config_get_http_priority() < config_get_rsync_priority()) { - error = download_uris(cache, uris, UT_RSYNC, use_rrdp, cb, arg); + error = download_uris(cache, uris, rsync_type, cb, arg); if (error <= 0) return error; - error = download_uris(cache, uris, UT_HTTPS, use_rrdp, cb, arg); + error = download_uris(cache, uris, http_type, cb, arg); if (error <= 0) return error; } else { ARRAYLIST_FOREACH(uris, cursor) { - error = download(cache, *cursor, use_rrdp, cb, arg); + error = download(cache, *cursor, cb, arg); if (error <= 0) return error; } } - uri = cache_recover(cache, uris, use_rrdp); + uri = cache_recover(cache, uris); return (uri != NULL) ? cb(uri, arg) : ESRCH; } @@ -743,7 +784,7 @@ struct uri_and_node { /* Separated because of unit tests. */ static void -__cache_recover(struct rpki_cache *cache, struct uri_list *uris, bool use_rrdp, +__cache_recover(struct rpki_cache *cache, struct uri_list *uris, struct uri_and_node *best) { struct rpki_uri **uri; @@ -755,7 +796,7 @@ __cache_recover(struct rpki_cache *cache, struct uri_list *uris, bool use_rrdp, if (get_url(cursor.uri, cache->tal, &url) != 0) continue; - cursor.node = find_node(cache, url); + cursor.node = find_node(cache, uri_get_local(url)); uri_refput(url); if (cursor.node == NULL) continue; @@ -766,10 +807,10 @@ __cache_recover(struct rpki_cache *cache, struct uri_list *uris, bool use_rrdp, } struct rpki_uri * -cache_recover(struct rpki_cache *cache, struct uri_list *uris, bool use_rrdp) +cache_recover(struct rpki_cache *cache, struct uri_list *uris) { struct uri_and_node best = { 0 }; - __cache_recover(cache, uris, use_rrdp, &best); + __cache_recover(cache, uris, &best); return best.uri; } @@ -806,7 +847,7 @@ delete_node_and_cage(struct rpki_cache *cache, struct cache_node *node) { struct rpki_uri *cage; - if (uri_is_notif(node->url)) { + if (uri_get_type(node->url) == UT_NOTIF) { if (uri_create_cage(&cage, cache->tal, node->url) == 0) { pr_op_debug("Deleting cage %s.", uri_get_local(cage)); file_rm_rf(uri_get_local(cage)); @@ -840,6 +881,22 @@ get_days_ago(int days) return last_week; } +static void +cleanup_tmp(struct rpki_cache *cache, struct cache_node *node) +{ + char const *path; + int error; + + if (uri_get_type(node->url) == UT_TMP) { + path = uri_get_local(node->url); + pr_op_debug("Deleting temporal file '%s'.", path); + error = file_rm_f(path); + if (error) + pr_op_err("Could not delete '%s': %s", path, strerror(error)); + delete_node(cache, node); + } +} + static void cleanup_node(struct rpki_cache *cache, struct cache_node *node, time_t last_week) @@ -910,8 +967,11 @@ delete_if_unknown(const char *fpath, const struct stat *sb, int typeflag, { if (!is_cached(fpath)) { pr_op_debug("Deleting untracked file or directory %s.", fpath); - remove(fpath); + errno = 0; + if (remove(fpath) != 0) + pr_op_err("Cannot delete '%s': %s", fpath, strerror(errno)); } + return 0; } @@ -938,7 +998,7 @@ delete_unknown_files(struct rpki_cache *cache) uri_refget(node->url); uris_add(&dnc, node->url); - if (!uri_is_notif(node->url)) + if (uri_get_type(node->url) != UT_NOTIF) continue; if (uri_create_cage(&cage, cache->tal, node->url) != 0) { @@ -971,6 +1031,10 @@ cache_cleanup(struct rpki_cache *cache) struct cache_node *node, *tmp; time_t last_week; + pr_op_debug("Cleaning up temporal files."); + HASH_ITER(hh, cache->ht, node, tmp) + cleanup_tmp(cache, node); + pr_op_debug("Cleaning up old abandoned cache files."); last_week = get_days_ago(7); HASH_ITER(hh, cache->ht, node, tmp) diff --git a/src/cache/local_cache.h b/src/cache/local_cache.h index 93eb11f1..19253512 100644 --- a/src/cache/local_cache.h +++ b/src/cache/local_cache.h @@ -1,6 +1,7 @@ #ifndef SRC_CACHE_LOCAL_CACHE_H_ #define SRC_CACHE_LOCAL_CACHE_H_ +#include #include "types/uri.h" struct rpki_cache; @@ -15,7 +16,7 @@ struct rpki_cache *cache_create(char const *); void cache_destroy(struct rpki_cache *); /* Downloads @uri into the cache */ -int cache_download(struct rpki_cache *, struct rpki_uri *uri, bool *); +int cache_download(struct rpki_cache *, struct rpki_uri *uri, curl_off_t, bool *); /* * The callback should return @@ -25,11 +26,11 @@ int cache_download(struct rpki_cache *, struct rpki_uri *uri, bool *); * - < 0 on hard errors ("Abandon foreach") */ typedef int (*uris_dl_cb)(struct rpki_uri *, void *); -int cache_download_alt(struct rpki_cache *, struct uri_list *, bool, - uris_dl_cb, void *); +int cache_download_alt(struct rpki_cache *, struct uri_list *, enum uri_type, + enum uri_type, uris_dl_cb, void *); /* Returns the most recent successfully cached URI of the list */ -struct rpki_uri *cache_recover(struct rpki_cache *, struct uri_list *, bool); +struct rpki_uri *cache_recover(struct rpki_cache *, struct uri_list *); /* Prints the cache in standard output. */ void cache_print(struct rpki_cache *); diff --git a/src/common.c b/src/common.c index a0e9ec01..b73297a2 100644 --- a/src/common.c +++ b/src/common.c @@ -238,9 +238,9 @@ dir_exists(char const *path) if (stat(path, &meta) != 0) { error = errno; if (error == ENOENT) - return false; + return 0; pr_op_err_st("stat() failed: %s", strerror(error)); - return error; + return -error; } if (!S_ISDIR(meta.st_mode)) { @@ -308,31 +308,13 @@ end: return result; } -static int -remove_file(char const *path) -{ - int error; - - errno = 0; - if (remove(path) != 0) { - error = errno; - /* - pr_val_err("Couldn't delete '%s': %s", path, - strerror(error)); - */ - return error; - } - - return 0; -} - /* - * Delete parent dirs of @path only if dirs are empty, @path must be a file - * location and will be deleted first. + * Delete @path. + * If path's parent is now empty, delete parent as well. + * If parent's parent is now empty, delete parent's parent. + * And so on. * - * The algorithm is a bit aggressive, but rmdir() won't delete - * something unless is empty, so in case the dir still has something in - * it the cycle is finished. + * FIXME this should be done by the cache cleaner instead. */ int delete_dir_recursive_bottom_up(char const *path) @@ -342,9 +324,12 @@ delete_dir_recursive_bottom_up(char const *path) size_t config_len; int error; - error = remove_file(path); - if (error) + errno = 0; + if (remove(path) != 0) { + error = errno; + pr_val_err("Couldn't delete '%s': %s", path, strerror(error)); return error; + } config_repo = pstrdup(config_get_local_repository()); diff --git a/src/file.c b/src/file.c index ad8bbda9..d3a64b14 100644 --- a/src/file.c +++ b/src/file.c @@ -154,10 +154,53 @@ file_valid(char const *file_name) return true; } +int +file_get_mtim(char const *file, time_t *ims) +{ + struct stat meta; + int error; + + if (stat(file, &meta) != 0) { + error = errno; + /* + * This happens to be most convenient for callers, + * because they all want to convert the ims to a curl_off_t ATM. + */ + *ims = 0; + return (error == ENOENT) ? 0 : error; + } + +#ifdef __APPLE__ + *ims = meta.st_mtime; /* Seriously, Apple? */ +#else + *ims = meta.st_mtim.tv_sec; +#endif + return 0; +} + +/* + * Like remove(), but don't care if the file is already deleted. + */ +int +file_rm_f(char const *path) +{ + int error; + + errno = 0; + if (remove(path) != 0) { + error = errno; + if (error != ENOENT) + return error; + } + + return 0; +} + static int rm(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { pr_op_debug("Deleting %s.", fpath); + errno = 0; return (remove(fpath) != 0) ? errno : 0; } diff --git a/src/file.h b/src/file.h index 67f95b06..f62b00b6 100644 --- a/src/file.h +++ b/src/file.h @@ -32,7 +32,9 @@ void file_free(struct file_contents *); int file_exists(char const *); bool file_valid(char const *); +int file_get_mtim(char const *, time_t *); +int file_rm_f(char const *); int file_rm_rf(char const *); /* diff --git a/src/http/http.c b/src/http/http.c index 53a681b7..0de473bb 100644 --- a/src/http/http.c +++ b/src/http/http.c @@ -1,7 +1,5 @@ #include "http/http.h" -#include - #include "alloc.h" #include "common.h" #include "config.h" @@ -33,26 +31,6 @@ http_cleanup(void) curl_global_cleanup(); } -static int -get_ims(char const *file, time_t *ims) -{ - struct stat meta; - int error; - - if (stat(file, &meta) != 0) { - error = errno; - *ims = 0; - return (error == ENOENT) ? 0 : error; - } - -#ifdef __APPLE__ - *ims = meta.st_mtime; /* Seriously, Apple? */ -#else - *ims = meta.st_mtim.tv_sec; -#endif - return 0; -} - static void setopt_str(CURL *curl, CURLoption opt, char const *value) { @@ -345,30 +323,42 @@ http_fetch(char const *src, char const *dst, curl_off_t ims, bool *changed) pr_val_debug("HTTP result code: %ld", http_code); error = 0; - *changed = true; + if (changed != NULL) + *changed = true; end: http_easy_cleanup(&handler); if (error) - remove(dst); + file_rm_f(dst); return error; } /* - * Assumes @dst's parent directory has already been created. + * Download @uri->global into @uri->local; HTTP assumed. + * + * If @changed returns true, the file was downloaded normally. + * If @changed returns false, the file has not been modified since @ims. + * + * @ims can be 0, which means "no epoch." + * @changed can be NULL, which means "I don't care." + * If @changed is not NULL, initialize it to false. */ -static int -do_retries(char const *src, char const *dst, curl_off_t ims, bool *changed) +int +http_download(struct rpki_uri *uri, curl_off_t ims, bool *changed) { unsigned int r; int error; - pr_val_debug("Downloading '%s'.", src); + pr_val_info("HTTP GET: %s -> %s", uri_get_global(uri), uri_get_local(uri)); - r = 0; - do { + error = mkdir_p(uri_get_local(uri), false); + if (error) + return error; + + for (r = 0; true; r++) { pr_val_debug("Download attempt #%u...", r + 1); - error = http_fetch(src, dst, ims, changed); + error = http_fetch(uri_get_global(uri), uri_get_local(uri), + ims, changed); switch (error) { case 0: pr_val_debug("Download successful."); @@ -394,63 +384,7 @@ do_retries(char const *src, char const *dst, curl_off_t ims, bool *changed) * down; use a thread pool. */ sleep(config_get_http_retry_interval()); - r++; - } while (true); -} - -/* - * Download @uri->global into @uri->local; HTTP assumed. - * - * If @changed returns true, the file was downloaded normally. - * If @changed returns false, the file already existed and is already its latest - * version. - * @changed can be NULL. - */ -int -http_download(struct rpki_uri *uri, bool *changed) -{ - char *tmp_file_name; - char const *final_file_name; - time_t ims; - bool __changed; - int error; - - if (changed == NULL) - changed = &__changed; - *changed = false; - - error = cache_tmpfile(&tmp_file_name); - if (error) - return error; - final_file_name = uri_get_local(uri); - error = get_ims(final_file_name, &ims); - if (error) - goto end; - - pr_val_info("HTTP GET: %s -> %s", uri_get_global(uri), final_file_name); - - error = do_retries(uri_get_global(uri), tmp_file_name, (curl_off_t)ims, - changed); - if (error || !(*changed)) - goto end; - - error = mkdir_p(final_file_name, false); - if (error) { - remove(tmp_file_name); - goto end; } - - error = rename(tmp_file_name, final_file_name); - if (error) { - error = errno; - pr_val_err("Renaming temporal file from '%s' to '%s': %s", - tmp_file_name, final_file_name, strerror(error)); - remove(tmp_file_name); - goto end; - } - -end: free(tmp_file_name); - return error; } /* @@ -458,9 +392,8 @@ end: free(tmp_file_name); * structure is created). */ int -http_direct_download(char const *remote, char const *dest) +http_download_direct(char const *src, char const *dst) { - bool changed; - pr_val_info("HTTP GET: %s -> %s", remote, dest); - return http_fetch(remote, dest, 0, &changed); + pr_val_info("HTTP GET: %s -> %s", src, dst); + return http_fetch(src, dst, 0, NULL); } diff --git a/src/http/http.h b/src/http/http.h index 41cb6692..2a446dc8 100644 --- a/src/http/http.h +++ b/src/http/http.h @@ -1,12 +1,13 @@ #ifndef SRC_HTTP_HTTP_H_ #define SRC_HTTP_HTTP_H_ +#include #include "types/uri.h" int http_init(void); void http_cleanup(void); -int http_download(struct rpki_uri *, bool *); -int http_direct_download(char const *, char const *); +int http_download(struct rpki_uri *, curl_off_t, bool *); +int http_download_direct(char const *, char const *); #endif /* SRC_HTTP_HTTP_H_ */ diff --git a/src/init.c b/src/init.c index 90181882..4b444eea 100644 --- a/src/init.c +++ b/src/init.c @@ -47,7 +47,7 @@ fetch_url(char const *url) offset += strlen(dest_file); dest[offset] = '\0'; - error = http_direct_download(url, dest); + error = http_download_direct(url, dest); if (error) { fprintf(stderr, "Couldn't fetch '%s'.\n", dest); free(dest); diff --git a/src/json_util.c b/src/json_util.c index 870ecadd..439caf6f 100644 --- a/src/json_util.c +++ b/src/json_util.c @@ -29,24 +29,6 @@ json_get_str(json_t *parent, char const *name, char const **result) return 0; } -int -json_get_bool(json_t *parent, char const *name, bool *result) -{ - json_t *child; - - *result = false; - - child = json_object_get(parent, name); - if (child == NULL) - return ENOENT; - - if (!json_is_boolean(child)) - return pr_op_err("Tag '%s' is not a JSON boolean.", name); - - *result = json_boolean_value(child); - return 0; -} - static int json_get_int_t(json_t *parent, char const *name, json_int_t *result) { @@ -183,18 +165,6 @@ json_valid_members_count(json_t *object, size_t expected_size) return json_object_size(object) == expected_size; } -int -json_add_bool(json_t *parent, char const *name, bool value) -{ - if (json_object_set_new(parent, name, json_boolean(value))) - return pr_op_err( - "Cannot convert %s '%u' to json; unknown cause.", - name, value - ); - - return 0; -} - int json_add_int(json_t *parent, char const *name, int value) { diff --git a/src/json_util.h b/src/json_util.h index 5c6dc959..33d32292 100644 --- a/src/json_util.h +++ b/src/json_util.h @@ -24,7 +24,6 @@ * result < 0: Tag was fatally invalid, outbound param reset, logged */ -int json_get_bool(json_t *, char const *, bool *); int json_get_int(json_t *, char const *, int *); int json_get_u32(json_t *, char const *, uint32_t *); int json_get_ts(json_t *, char const *, time_t *); @@ -34,7 +33,6 @@ int json_get_object(json_t *, char const *, json_t **); bool json_valid_members_count(json_t *, size_t); -int json_add_bool(json_t *, char const *, bool); int json_add_int(json_t *, char const *, int); int json_add_str(json_t *, char const *, char const *); int json_add_date(json_t *, char const *, time_t); diff --git a/src/object/certificate.c b/src/object/certificate.c index 407c6e9f..bd4dc248 100644 --- a/src/object/certificate.c +++ b/src/object/certificate.c @@ -73,7 +73,7 @@ struct ad_metadata { static const struct ad_metadata CA_ISSUERS = { .name = "caIssuers", .ia_name = "AIA", - .type = UT_RSYNC, + .type = UT_AIA, .type_str = "rsync", .required = true, }; @@ -81,7 +81,7 @@ static const struct ad_metadata CA_ISSUERS = { static const struct ad_metadata SIGNED_OBJECT = { .name = "signedObject", .ia_name = "SIA", - .type = UT_RSYNC, + .type = UT_SO, .type_str = "rsync", .required = true, }; @@ -89,7 +89,7 @@ static const struct ad_metadata SIGNED_OBJECT = { static const struct ad_metadata CA_REPOSITORY = { .name = "caRepository", .ia_name = "SIA", - .type = UT_RSYNC, + .type = UT_RPP, .type_str = "rsync", .required = false, }; @@ -97,7 +97,7 @@ static const struct ad_metadata CA_REPOSITORY = { static const struct ad_metadata RPKI_NOTIFY = { .name = "rpkiNotify", .ia_name = "SIA", - .type = UT_HTTPS, + .type = UT_NOTIF, .type_str = "HTTPS", .required = false, }; @@ -105,7 +105,7 @@ static const struct ad_metadata RPKI_NOTIFY = { static const struct ad_metadata RPKI_MANIFEST = { .name = "rpkiManifest", .ia_name = "SIA", - .type = UT_RSYNC, + .type = UT_MFT, .type_str = "rsync", .required = true, }; @@ -1523,8 +1523,7 @@ uri_create_ad(struct rpki_uri **uri, ACCESS_DESCRIPTION *ad, enum uri_type type, * But ask the testers to keep an eye on it anyway. */ return __uri_create(uri, - tal_get_file_name(validation_tal(state_retrieve())), type, - is_notif, NULL, + tal_get_file_name(validation_tal(state_retrieve())), type, NULL, ASN1_STRING_get0_data(asn1str), ASN1_STRING_length(asn1str)); } @@ -1941,7 +1940,8 @@ download_rpp(struct sia_uris *uris) } cache = validation_cache(state_retrieve()); - error = cache_download_alt(cache, &uris->rpp, true, retrieve_uri, &uri); + error = cache_download_alt(cache, &uris->rpp, UT_NOTIF, UT_RPP, + retrieve_uri, &uri); return error ? NULL : uri; } @@ -2034,7 +2034,7 @@ certificate_traverse(struct rpp *rpp_parent, struct rpki_uri *cert_uri) cert = NULL; /* Ownership stolen */ error = handle_manifest(sia_uris.mft, - (uri_get_type(downloaded) == UT_HTTPS) ? downloaded : NULL, + (uri_get_type(downloaded) == UT_NOTIF) ? downloaded : NULL, &pp); if (error) { x509stack_cancel(validation_certstack(state)); diff --git a/src/object/manifest.c b/src/object/manifest.c index 4ee6c1c1..f527db86 100644 --- a/src/object/manifest.c +++ b/src/object/manifest.c @@ -323,7 +323,7 @@ fail: /** * Validates the manifest pointed by @uri, returns the RPP described by it in - * @pp. If @rrdp_workspace is true, use the local RRDP repository. + * @pp. */ int handle_manifest(struct rpki_uri *uri, struct rpki_uri *notif, struct rpp **pp) diff --git a/src/object/tal.c b/src/object/tal.c index 14e62c5b..a9ee59ba 100644 --- a/src/object/tal.c +++ b/src/object/tal.c @@ -77,11 +77,11 @@ add_uri(struct tal *tal, char *uri) int error; if (str_starts_with(uri, "rsync://")) - error = uri_create(&new, tal->file_name, UT_RSYNC, false, NULL, uri); + error = uri_create(&new, tal->file_name, UT_TA_RSYNC, NULL, uri); else if (str_starts_with(uri, "https://")) - error = uri_create(&new, tal->file_name, UT_HTTPS, false, NULL, uri); + error = uri_create(&new, tal->file_name, UT_TA_HTTP, NULL, uri); else - return pr_op_err("TAL has non-RSYNC/HTTPS URI: %s", uri); + return pr_op_err("TAL has non-rsync/HTTPS URI: %s", uri); if (error) return error; @@ -303,7 +303,7 @@ do_file_validation(void *arg) args.db = db_table_create(); thread->error = cache_download_alt(args.tal.cache, &args.tal.uris, - false, __handle_tal_uri, &args); + UT_TA_HTTP, UT_TA_RSYNC, __handle_tal_uri, &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/rrdp.c b/src/rrdp.c index 4e4255c0..6f60a9ed 100644 --- a/src/rrdp.c +++ b/src/rrdp.c @@ -422,8 +422,7 @@ parse_file_metadata(xmlTextReaderPtr reader, struct rpki_uri *notif, return -EINVAL; error = uri_create(&meta->uri, tal_get_file_name(validation_tal(state_retrieve())), - (notif != NULL) ? UT_CAGED : UT_HTTPS, - false, notif, (char const *)uri); + (notif != NULL) ? UT_CAGED : UT_TMP, notif, (char const *)uri); xmlFree(uri); if (error) return error; @@ -780,7 +779,7 @@ handle_snapshot(struct update_notification *notif) * Maybe stream it instead. * Same for deltas. */ - error = cache_download(validation_cache(state), uri, NULL); + error = cache_download(validation_cache(state), uri, 0, NULL); if (error) goto end; error = validate_hash(¬if->snapshot); @@ -853,7 +852,7 @@ handle_delta(struct update_notification *notif, struct notification_delta *delta pr_val_debug("Processing delta '%s'.", uri_val_get_printable(uri)); fnstack_push_uri(uri); - error = cache_download(validation_cache(state_retrieve()), uri, NULL); + error = cache_download(validation_cache(state_retrieve()), uri, 0, NULL); if (error) goto end; error = parse_delta(notif, delta); @@ -946,6 +945,7 @@ rrdp_update(struct rpki_uri *uri) { struct rrdp_session old = { 0 }; struct update_notification new; + time_t ims; bool changed; int error; @@ -958,7 +958,12 @@ rrdp_update(struct rpki_uri *uri) pr_val_debug("Old session/serial: %s/%s", old.session_id, old.serial.str); - error = cache_download(validation_cache(state_retrieve()), uri, &changed); + error = file_get_mtim(uri_get_local(uri), &ims); + if (error) + return error; + + error = cache_download(validation_cache(state_retrieve()), uri, + ims, &changed); if (error) goto end; if (!changed) { diff --git a/src/types/uri.c b/src/types/uri.c index cc7fb74e..e381bf18 100644 --- a/src/types/uri.c +++ b/src/types/uri.c @@ -8,6 +8,7 @@ #include "state.h" #include "str_token.h" #include "thread_var.h" +#include "cache/local_cache.h" #include "config/filename_format.h" #include "data_structure/path_builder.h" @@ -63,7 +64,6 @@ struct rpki_uri { /* "local_len" is never needed right now. */ enum uri_type type; - bool is_notif; /* Does it point to an RRDP Notification? */ unsigned int references; }; @@ -376,12 +376,25 @@ autocomplete_local(struct rpki_uri *uri, char const *tal, struct rpki_uri *notif) { switch (uri->type) { - case UT_RSYNC: + case UT_TA_RSYNC: + case UT_RPP: return map_simple(uri, tal, "rsync://", ENOTRSYNC); - case UT_HTTPS: + + case UT_TA_HTTP: + case UT_NOTIF: return map_simple(uri, tal, "https://", ENOTHTTPS); + + case UT_TMP: + return cache_tmpfile(&uri->local); + case UT_CAGED: return map_caged(uri, tal, notif); + + case UT_AIA: + case UT_SO: + case UT_MFT: + uri->local = NULL; + return 0; } pr_crit("Unknown URI type: %u", uri->type); @@ -393,7 +406,7 @@ autocomplete_local(struct rpki_uri *uri, char const *tal, */ int __uri_create(struct rpki_uri **result, char const *tal, enum uri_type type, - bool is_notif, struct rpki_uri *notif, void const *guri, size_t guri_len) + struct rpki_uri *notif, void const *guri, size_t guri_len) { struct rpki_uri *uri; int error; @@ -407,7 +420,6 @@ __uri_create(struct rpki_uri **result, char const *tal, enum uri_type type, } uri->type = type; - uri->is_notif = is_notif; error = autocomplete_local(uri, tal, notif); if (error) { @@ -441,7 +453,7 @@ uri_create_mft(struct rpki_uri **result, char const *tal, return error; } - uri->type = (notif == NULL) ? UT_RSYNC : UT_CAGED; + uri->type = (notif == NULL) ? UT_RPP : UT_CAGED; error = autocomplete_local(uri, tal, notif); if (error) { @@ -535,30 +547,12 @@ uri_is_certificate(struct rpki_uri *uri) return uri_has_extension(uri, ".cer"); } -bool -uri_is_notif(struct rpki_uri *uri) -{ - return uri->is_notif; -} - enum uri_type uri_get_type(struct rpki_uri *uri) { return uri->type; } -bool -uri_is_rsync(struct rpki_uri *uri) -{ - return uri->type == UT_RSYNC; -} - -bool -uri_is_https(struct rpki_uri *uri) -{ - return uri->type == UT_HTTPS; -} - static char const * get_filename(char const *file_path) { diff --git a/src/types/uri.h b/src/types/uri.h index 8e7392fb..dbfe9c32 100644 --- a/src/types/uri.h +++ b/src/types/uri.h @@ -5,29 +5,30 @@ #include "data_structure/array_list.h" enum uri_type { - /* rsync URL */ - UT_RSYNC, - /* HTTPS URL */ - UT_HTTPS, - /* - * URI (not URL). - * In practice it's always rsync, but it doesn't matter. - */ - UT_CAGED, + UT_TA_RSYNC, /* TAL's TA URL; downloaded via rsync. */ + UT_TA_HTTP, /* TAL's TA URL; downloaded via HTTP. */ + UT_RPP, /* caRepository; downloaded via rsync. */ + UT_NOTIF, /* rpkiNotify; downloaded via HTTP. */ + UT_TMP, /* Snapshot or delta; Downloaded via HTTP. */ + UT_CAGED, /* Endangered species. */ + + UT_AIA, /* caIssuers. Not downloaded. */ + UT_SO, /* signedObject. Not downloaded. */ + UT_MFT, /* rpkiManifest. Not downloaded. */ }; struct rpki_uri; int __uri_create(struct rpki_uri **, char const *, enum uri_type, - bool, struct rpki_uri *, void const *, size_t); + struct rpki_uri *, void const *, size_t); int uri_create_mft(struct rpki_uri **, char const *, struct rpki_uri *, struct rpki_uri *, IA5String_t *); struct rpki_uri *uri_create_cache(char const *); -#define uri_create(uri, tal, type, is_notif, notif, guri) \ - __uri_create(uri, tal, type, is_notif, notif, guri, strlen(guri)) +#define uri_create(uri, tal, type, notif, guri) \ + __uri_create(uri, tal, type, notif, guri, strlen(guri)) #define uri_create_caged(uri, tal, notif, guri, guri_len) \ - __uri_create(uri, tal, UT_CAGED, false, notif, guri, guri_len) + __uri_create(uri, tal, UT_CAGED, notif, guri, guri_len) #define uri_create_cage(uri, tal, notif) \ uri_create_caged(uri, tal, notif, "", 0) @@ -45,11 +46,8 @@ size_t uri_get_global_len(struct rpki_uri *); bool uri_equals(struct rpki_uri *, struct rpki_uri *); bool uri_has_extension(struct rpki_uri *, char const *); bool uri_is_certificate(struct rpki_uri *); -bool uri_is_notif(struct rpki_uri *); enum uri_type uri_get_type(struct rpki_uri *); -bool uri_is_rsync(struct rpki_uri *); -bool uri_is_https(struct rpki_uri *); char const *uri_val_get_printable(struct rpki_uri *); char const *uri_op_get_printable(struct rpki_uri *); diff --git a/test/cache/local_cache_test.c b/test/cache/local_cache_test.c index 3cd53ae7..054c3f67 100644 --- a/test/cache/local_cache_test.c +++ b/test/cache/local_cache_test.c @@ -57,6 +57,15 @@ file_rm_rf(char const *file) return ENOENT; } +int +file_rm_f(char const *file) +{ + file_rm_rf(file); + return 0; +} + +MOCK_ABORT_INT(file_get_mtim, char const *file, time_t *ims) + static int pretend_download(struct rpki_uri *uri) { @@ -82,7 +91,7 @@ rsync_download(struct rpki_uri *uri) } int -http_download(struct rpki_uri *uri, bool *changed) +http_download(struct rpki_uri *uri, curl_off_t ims, bool *changed) { int error; https_counter++; @@ -115,17 +124,17 @@ run_cache_download(char const *url, int expected_error, enum uri_type type; if (str_starts_with(url, "https://")) - type = UT_HTTPS; + type = UT_TA_HTTP; else if (str_starts_with(url, "rsync://")) - type = UT_RSYNC; + type = UT_RPP; else ck_abort_msg("Bad protocol: %s", url); rsync_counter = 0; https_counter = 0; - ck_assert_int_eq(0, uri_create(&uri, TAL_FILE, type, false, NULL, url)); - ck_assert_int_eq(expected_error, cache_download(cache, uri, NULL)); + ck_assert_int_eq(0, uri_create(&uri, TAL_FILE, type, NULL, url)); + ck_assert_int_eq(expected_error, cache_download(cache, uri, 0, NULL)); ck_assert_uint_eq(rsync_calls, rsync_counter); ck_assert_uint_eq(https_calls, https_counter); @@ -140,15 +149,14 @@ node(char const *url, time_t attempt, int err, bool succeeded, time_t success, struct cache_node *result; if (str_starts_with(url, "https://")) - type = UT_HTTPS; + type = is_notif ? UT_NOTIF : UT_TA_HTTP; else if (str_starts_with(url, "rsync://")) - type = UT_RSYNC; + type = UT_RPP; else ck_abort_msg("Bad protocol: %s", url); result = pzalloc(sizeof(struct cache_node)); - ck_assert_int_eq(0, uri_create(&result->url, TAL_FILE, type, is_notif, - NULL, url)); + ck_assert_int_eq(0, uri_create(&result->url, TAL_FILE, type, NULL, url)); result->attempt.ts = attempt; result->attempt.result = err; result->success.happened = succeeded; @@ -735,11 +743,11 @@ START_TEST(test_tal_json) json_decref(json); ck_assert_str_eq( - "[{\"url\":\"rsync://a.b.c/d\",\"attempt-timestamp\":\"1970-01-01T00:00:00Z\",\"attempt-result\":0,\"success-timestamp\":\"1970-01-01T00:00:00Z\"}," - "{\"url\":\"rsync://a.b.c/e\",\"attempt-timestamp\":\"1970-01-01T00:00:00Z\",\"attempt-result\":1}," - "{\"url\":\"rsync://x.y.z/e\",\"attempt-timestamp\":\"1970-01-01T00:00:00Z\",\"attempt-result\":0,\"success-timestamp\":\"1970-01-01T00:00:00Z\"}," - "{\"url\":\"https://a/b\",\"attempt-timestamp\":\"1970-01-01T00:00:00Z\",\"attempt-result\":1,\"success-timestamp\":\"1970-01-01T00:00:00Z\"}," - "{\"url\":\"https://a/c\",\"is-rrdp-notification\":true,\"attempt-timestamp\":\"1970-01-01T00:00:00Z\",\"attempt-result\":0,\"success-timestamp\":\"1970-01-01T00:00:00Z\"}]", + "[{\"type\":\"RPP\",\"url\":\"rsync://a.b.c/d\",\"attempt-timestamp\":\"1970-01-01T00:00:00Z\",\"attempt-result\":0,\"success-timestamp\":\"1970-01-01T00:00:00Z\"}," + "{\"type\":\"RPP\",\"url\":\"rsync://a.b.c/e\",\"attempt-timestamp\":\"1970-01-01T00:00:00Z\",\"attempt-result\":1}," + "{\"type\":\"RPP\",\"url\":\"rsync://x.y.z/e\",\"attempt-timestamp\":\"1970-01-01T00:00:00Z\",\"attempt-result\":0,\"success-timestamp\":\"1970-01-01T00:00:00Z\"}," + "{\"type\":\"TA (HTTP)\",\"url\":\"https://a/b\",\"attempt-timestamp\":\"1970-01-01T00:00:00Z\",\"attempt-result\":1,\"success-timestamp\":\"1970-01-01T00:00:00Z\"}," + "{\"type\":\"RRDP Notification\",\"url\":\"https://a/c\",\"attempt-timestamp\":\"1970-01-01T00:00:00Z\",\"attempt-result\":0,\"success-timestamp\":\"1970-01-01T00:00:00Z\"}]", str); free(str); @@ -773,13 +781,12 @@ prepare_uri_list(struct uri_list *uris, ...) va_start(args, uris); while ((str = va_arg(args, char const *)) != NULL) { if (str_starts_with(str, "https://")) - type = UT_HTTPS; + type = UT_TA_HTTP; else if (str_starts_with(str, "rsync://")) - type = UT_RSYNC; + type = UT_RPP; else ck_abort_msg("Bad protocol: %s", str); - ck_assert_int_eq(0, uri_create(&uri, TAL_FILE, type, false, - NULL, str)); + ck_assert_int_eq(0, uri_create(&uri, TAL_FILE, type, NULL, str)); uris_add(uris, uri); } va_end(args); @@ -795,7 +802,7 @@ START_TEST(test_recover) /* Query on empty database */ PREPARE_URI_LIST(&uris, "rsync://a.b.c/d", "https://a.b.c/d"); - ck_assert_ptr_eq(NULL, cache_recover(cache, &uris, false)); + ck_assert_ptr_eq(NULL, cache_recover(cache, &uris)); uris_cleanup(&uris); /* Only first URI is cached */ @@ -803,7 +810,7 @@ START_TEST(test_recover) run_cache_download("rsync://a/b/c", 0, 1, 0); PREPARE_URI_LIST(&uris, "rsync://a/b/c", "https://d/e", "https://f"); - ck_assert_ptr_eq(uris.array[0], cache_recover(cache, &uris, false)); + ck_assert_ptr_eq(uris.array[0], cache_recover(cache, &uris)); uris_cleanup(&uris); /* Only second URI is cached */ @@ -811,7 +818,7 @@ START_TEST(test_recover) run_cache_download("https://d/e", 0, 0, 1); PREPARE_URI_LIST(&uris, "rsync://a/b/c", "https://d/e", "https://f"); - ck_assert_ptr_eq(uris.array[1], cache_recover(cache, &uris, false)); + ck_assert_ptr_eq(uris.array[1], cache_recover(cache, &uris)); uris_cleanup(&uris); /* Only third URI is cached */ @@ -819,7 +826,7 @@ START_TEST(test_recover) run_cache_download("https://f", 0, 0, 1); PREPARE_URI_LIST(&uris, "rsync://a/b/c", "https://d/e", "https://f"); - ck_assert_ptr_eq(uris.array[2], cache_recover(cache, &uris, false)); + ck_assert_ptr_eq(uris.array[2], cache_recover(cache, &uris)); uris_cleanup(&uris); /* None was cached */ @@ -827,7 +834,7 @@ START_TEST(test_recover) run_cache_download("rsync://d/e", 0, 1, 0); PREPARE_URI_LIST(&uris, "rsync://a/b/c", "https://d/e", "https://f"); - ck_assert_ptr_eq(NULL, cache_recover(cache, &uris, false)); + ck_assert_ptr_eq(NULL, cache_recover(cache, &uris)); uris_cleanup(&uris); /* @@ -854,21 +861,21 @@ START_TEST(test_recover) /* Multiple successful caches: Prioritize the most recent one */ PREPARE_URI_LIST(&uris, "rsync://a/1", "rsync://a/3", "rsync://a/5"); - ck_assert_ptr_eq(uris.array[2], cache_recover(cache, &uris, false)); + ck_assert_ptr_eq(uris.array[2], cache_recover(cache, &uris)); uris_cleanup(&uris); PREPARE_URI_LIST(&uris, "rsync://a/5", "rsync://a/1", "rsync://a/3"); - ck_assert_ptr_eq(uris.array[0], cache_recover(cache, &uris, false)); + ck_assert_ptr_eq(uris.array[0], cache_recover(cache, &uris)); uris_cleanup(&uris); /* No successful caches: No viable candidates */ PREPARE_URI_LIST(&uris, "rsync://b/2", "rsync://b/4", "rsync://b/6"); - ck_assert_ptr_eq(NULL, cache_recover(cache, &uris, false)); + ck_assert_ptr_eq(NULL, cache_recover(cache, &uris)); uris_cleanup(&uris); /* Status: CNF_SUCCESS is better than 0. */ PREPARE_URI_LIST(&uris, "rsync://b/1", "rsync://a/1"); - ck_assert_ptr_eq(uris.array[1], cache_recover(cache, &uris, false)); + ck_assert_ptr_eq(uris.array[1], cache_recover(cache, &uris)); uris_cleanup(&uris); /* @@ -879,12 +886,12 @@ START_TEST(test_recover) * outdatedness is not that severe. */ PREPARE_URI_LIST(&uris, "rsync://a/2", "rsync://b/2"); - ck_assert_ptr_eq(uris.array[0], cache_recover(cache, &uris, false)); + ck_assert_ptr_eq(uris.array[0], cache_recover(cache, &uris)); uris_cleanup(&uris); /* Parents of downloaded nodes */ PREPARE_URI_LIST(&uris, "rsync://a", "rsync://b"); - ck_assert_ptr_eq(NULL, cache_recover(cache, &uris, false)); + ck_assert_ptr_eq(NULL, cache_recover(cache, &uris)); uris_cleanup(&uris); /* Try them all at the same time */ @@ -894,7 +901,7 @@ START_TEST(test_recover) "rsync://b", "rsync://b/1", "rsync://b/2", "rsync://b/3", "rsync://b/4", "rsync://b/5", "rsync://b/6", "rsync://e/1"); - ck_assert_ptr_eq(uris.array[5], cache_recover(cache, &uris, false)); + ck_assert_ptr_eq(uris.array[5], cache_recover(cache, &uris)); uris_cleanup(&uris); cleanup_test(); diff --git a/test/crypto/hash_test.c b/test/crypto/hash_test.c index cbd4a86c..5673aa58 100644 --- a/test/crypto/hash_test.c +++ b/test/crypto/hash_test.c @@ -9,6 +9,8 @@ #include "types/uri.c" #include "crypto/hash.c" +MOCK_ABORT_INT(cache_tmpfile, char **filename) + /* Actually mostly tests libcrypto's sanity, not Fort's. */ START_TEST(test_hash) { @@ -45,8 +47,7 @@ START_TEST(test_hash) uri.global = "https://example.com/resources/lorem-ipsum.txt"; uri.global_len = strlen(uri.global); uri.local = "resources/lorem-ipsum.txt"; - uri.type = UT_HTTPS; - uri.is_notif = false; + uri.type = UT_TA_HTTP; uri.references = 1; ha = hash_get_sha1(); diff --git a/test/rrdp_test.c b/test/rrdp_test.c index 60595ef4..e5ac7acb 100644 --- a/test/rrdp_test.c +++ b/test/rrdp_test.c @@ -15,8 +15,23 @@ /* Mocks */ +int +cache_tmpfile(char **filename) +{ + static unsigned int file_counter = 0; + char *result; + int written; + + result = pmalloc(10); + written = snprintf(result, 10, "tmp/%u", file_counter); + ck_assert(4 < written && written < 10); + + *filename = result; + return 0; +} + MOCK_ABORT_INT(cache_download, struct rpki_cache *cache, struct rpki_uri *uri, - bool *changed) + curl_off_t ims, bool *changed) MOCK_ABORT_VOID(fnstack_pop, void) MOCK_ABORT_VOID(fnstack_push_uri, struct rpki_uri *uri) MOCK_ABORT_PTR(validation_cache, rpki_cache, struct validation *state) @@ -242,6 +257,7 @@ START_TEST(test_parse_notification_ok) ck_assert_int_eq(0, relax_ng_init()); uri.local = "resources/rrdp/notif-ok.xml"; + uri.type = UT_NOTIF; uri.references = 1; ck_assert_int_eq(0, parse_notification(&uri, ¬if)); @@ -276,6 +292,7 @@ START_TEST(test_parse_notification_0deltas) ck_assert_int_eq(0, relax_ng_init()); uri.local = "resources/rrdp/notif-0deltas.xml"; + uri.type = UT_NOTIF; uri.references = 1; ck_assert_int_eq(0, parse_notification(&uri, ¬if)); @@ -300,6 +317,7 @@ START_TEST(test_parse_notification_large_serial) ck_assert_int_eq(0, relax_ng_init()); uri.local = "resources/rrdp/notif-large-serial.xml"; + uri.type = UT_NOTIF; uri.references = 1; ck_assert_int_eq(0, parse_notification(&uri, ¬if)); @@ -331,6 +349,7 @@ test_parse_notification_error(char *file) ck_assert_int_eq(0, relax_ng_init()); uri.local = file; + uri.type = UT_NOTIF; uri.references = 1; ck_assert_int_eq(-EINVAL, parse_notification(&uri, ¬if)); @@ -396,8 +415,7 @@ START_TEST(test_parse_snapshot_bad_publish) notif_uri.global = "https://example.com/notification.xml"; notif_uri.global_len = strlen(notif_uri.global); notif_uri.local = "cache/example.com/notification.xml"; - notif_uri.type = UT_HTTPS; - notif_uri.is_notif = true; + notif_uri.type = UT_NOTIF; notif_uri.references = 1; snapshot_uri.local = "resources/rrdp/snapshot-bad-publish.xml"; diff --git a/test/tal_test.c b/test/tal_test.c index 5001f8fe..8adf18f0 100644 --- a/test/tal_test.c +++ b/test/tal_test.c @@ -16,11 +16,13 @@ MOCK_ABORT_VOID(cache_setup, void) MOCK(cache_create, struct rpki_cache *, NULL, char const *tal) MOCK_VOID(cache_destroy, struct rpki_cache *cache) MOCK_ABORT_INT(cache_download, struct rpki_cache *cache, struct rpki_uri *uri, - bool *changed) + curl_off_t ims, bool *changed) MOCK_ABORT_INT(cache_download_alt, struct rpki_cache *cache, - struct uri_list *uris, bool use_rrdp, uris_dl_cb cb, void *arg) + struct uri_list *uris, enum uri_type http_type, enum uri_type rsync_type, + uris_dl_cb cb, void *arg) MOCK_ABORT_PTR(cache_recover, rpki_uri, struct rpki_cache *cache, - struct uri_list *uris, bool use_rrdp) + struct uri_list *uris) +MOCK_ABORT_INT(cache_tmpfile, char **filename) MOCK_ABORT_VOID(cache_teardown, void) MOCK_ABORT_INT(certificate_traverse, struct rpp *rpp_parent, struct rpki_uri *cert_uri) diff --git a/test/types/uri_test.c b/test/types/uri_test.c index d8196093..8b611e8d 100644 --- a/test/types/uri_test.c +++ b/test/types/uri_test.c @@ -18,10 +18,25 @@ MOCK(tal_get_file_name, char const *, "test.tal", struct tal *tal) MOCK_ABORT_INT(rrdp_update, struct rpki_uri *uri) +int +cache_tmpfile(char **filename) +{ + static bool used = false; + + if (used) { + ck_abort_msg("cache_tmpfile() called a second time!"); + return -EINVAL; + } + + *filename = pstrdup("tmp/tmp/0"); + used = true; + return 0; +} + /* Tests */ -#define URI_CREATE_HTTP(uri, str) uri_create(&uri, "test.tal", UT_HTTPS, false, NULL, str) -#define URI_CREATE_RSYNC(uri, str) uri_create(&uri, "test.tal", UT_RSYNC, false, NULL, str) +#define URI_CREATE_HTTP(uri, str) uri_create(&uri, "test.tal", UT_TA_HTTP, NULL, str) +#define URI_CREATE(uri, type, str) uri_create(&uri, "test.tal", type, NULL, str) START_TEST(test_constructor) { @@ -87,7 +102,27 @@ START_TEST(test_constructor) ck_assert_int_eq(ENOTHTTPS, URI_CREATE_HTTP(uri, "rsync://a.b.c/d")); ck_assert_int_eq(ENOTHTTPS, URI_CREATE_HTTP(uri, "http://a.b.c/d")); - ck_assert_int_eq(ENOTRSYNC, URI_CREATE_RSYNC(uri, "https://a.b.c/d")); + ck_assert_int_eq(ENOTRSYNC, URI_CREATE(uri, UT_RPP, "https://a.b.c/d")); + + ck_assert_int_eq(0, URI_CREATE(uri, UT_RPP, "rsync://a.b.c/d")); + ck_assert_str_eq("rsync://a.b.c/d", uri_get_global(uri)); + ck_assert_str_eq("tmp/test.tal/rsync/a.b.c/d", uri_get_local(uri)); + uri_refput(uri); + + ck_assert_int_eq(0, URI_CREATE(uri, UT_TA_RSYNC, "rsync://a.b.c/d.cer")); + ck_assert_str_eq("rsync://a.b.c/d.cer", uri_get_global(uri)); + ck_assert_str_eq("tmp/test.tal/rsync/a.b.c/d.cer", uri_get_local(uri)); + uri_refput(uri); + + ck_assert_int_eq(0, URI_CREATE(uri, UT_NOTIF, "https://a.b.c/notification.xml")); + ck_assert_str_eq("https://a.b.c/notification.xml", uri_get_global(uri)); + ck_assert_str_eq("tmp/test.tal/https/a.b.c/notification.xml", uri_get_local(uri)); + uri_refput(uri); + + ck_assert_int_eq(0, URI_CREATE(uri, UT_TMP, "https://a.b.c/snapshot.xml")); + ck_assert_str_eq("https://a.b.c/snapshot.xml", uri_get_global(uri)); + ck_assert_str_eq("tmp/tmp/0", uri_get_local(uri)); + uri_refput(uri); } END_TEST @@ -147,14 +182,14 @@ START_TEST(check_caged) { struct rpki_uri *uri; - ck_assert_int_eq(0, uri_create(¬if, "test.tal", UT_HTTPS, true, NULL, "https://a.b.c/d/e.xml")); - ck_assert_int_eq(0, uri_create(&uri, "test.tal", UT_CAGED, false, notif, "rsync://x.y.z/v/w.cer")); + ck_assert_int_eq(0, uri_create(¬if, "test.tal", UT_NOTIF, NULL, "https://a.b.c/d/e.xml")); + ck_assert_int_eq(0, uri_create(&uri, "test.tal", UT_CAGED, notif, "rsync://x.y.z/v/w.cer")); ck_assert_str_eq("tmp/test.tal/rrdp/a.b.c/d/e.xml/x.y.z/v/w.cer", uri_get_local(uri)); uri_refput(uri); uri_refput(notif); - ck_assert_int_eq(0, uri_create(¬if, "test.tal", UT_HTTPS, true, NULL, "https://a.b.c")); - ck_assert_int_eq(0, uri_create(&uri, "test.tal", UT_CAGED, false, notif, "rsync://w")); + ck_assert_int_eq(0, uri_create(¬if, "test.tal", UT_NOTIF, NULL, "https://a.b.c")); + ck_assert_int_eq(0, uri_create(&uri, "test.tal", UT_CAGED, notif, "rsync://w")); ck_assert_str_eq("tmp/test.tal/rrdp/a.b.c/w", uri_get_local(uri)); uri_refput(uri); uri_refput(notif);