From: pcarana Date: Sat, 17 Oct 2020 01:27:26 +0000 (-0500) Subject: Fix bug: data can be stale when the local-repository is deleted. X-Git-Tag: v1.4.2~1 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=defa389006f882cdd36e9438aac4807f36445f99;p=thirdparty%2FFORT-validator.git Fix bug: data can be stale when the local-repository is deleted. The data remained the same until an RRDP server had a delta update; in such case the updated files weren't found and the snapshot was processed, so the local cache was built again. In case that the RRDP server didn't had updates, the root manifest wasn't found and the whole validation cycle results were discarded. Now, when the manifest isn't found and the RRDP has no updates, force the snapshot processing to assure that the error isn't of the RP. Also, update the daemon that cleans up the RRDP visited URIs, so that it deletes the files from its corresponding workspace. --- diff --git a/src/common.c b/src/common.c index 85d86893..05e386e0 100644 --- a/src/common.c +++ b/src/common.c @@ -420,3 +420,62 @@ get_current_time(time_t *result) *result = now; return 0; } + +/* + * Maps an absolute @uri that begins with @uri_prefix (either 'rsync://' or + * 'https://') to a local URI. If a @workspace is set, append such location + * to the local-repository location (this workspace is used at https URIs). + * + * @result is allocated with the local URI. + * + * Returns 0 on success, otherwise an error code. + */ +int +map_uri_to_local(char const *uri, char const *uri_prefix, char const *workspace, + char **result) +{ + char const *repository; + char *local; + size_t repository_len; + size_t uri_prefix_len; + size_t uri_len; + size_t workspace_len; + size_t extra_slash; + size_t offset; + + repository = config_get_local_repository(); + repository_len = strlen(repository); + uri_prefix_len = strlen(uri_prefix); + uri_len = strlen(uri); + + uri += uri_prefix_len; + uri_len -= uri_prefix_len; + extra_slash = (repository[repository_len - 1] == '/') ? 0 : 1; + + workspace_len = 0; + if (workspace != NULL) + workspace_len = strlen(workspace); + + local = malloc(repository_len + extra_slash + workspace_len + uri_len + + 1); + if (local == NULL) + return pr_enomem(); + + offset = 0; + strcpy(local + offset, repository); + offset += repository_len; + if (extra_slash) { + strcpy(local + offset, "/"); + offset += extra_slash; + } + if (workspace_len > 0) { + strcpy(local + offset, workspace); + offset += workspace_len; + } + strncpy(local + offset, uri, uri_len); + offset += uri_len; + local[offset] = '\0'; + + *result = local; + return 0; +} diff --git a/src/common.h b/src/common.h index f4f311be..24fd976a 100644 --- a/src/common.h +++ b/src/common.h @@ -2,7 +2,6 @@ #define SRC_RTR_COMMON_H_ #include -#include #include #include #include @@ -66,4 +65,6 @@ int delete_dir_recursive_bottom_up(char const *); int get_current_time(time_t *); +int map_uri_to_local(char const *, char const*, char const *, char **); + #endif /* SRC_RTR_COMMON_H_ */ diff --git a/src/delete_dir_daemon.c b/src/delete_dir_daemon.c index d81e82f1..92f25843 100644 --- a/src/delete_dir_daemon.c +++ b/src/delete_dir_daemon.c @@ -12,7 +12,6 @@ #include "common.h" #include "log.h" #include "random.h" -#include "uri.h" #define MAX_FD_ALLOWED 20 @@ -112,23 +111,18 @@ remove_from_root(void *arg) * - '= 0' no error */ static int -get_local_path(char const *rcvd, char **result) +get_local_path(char const *rcvd, char const *workspace, char **result) { struct stat attr; - struct rpki_uri *uri; char *tmp, *local_path; size_t tmp_size; int error; - error = uri_create_mixed_str(&uri, rcvd, strlen(rcvd)); + /* Currently, only rsync URIs are utilized */ + local_path = NULL; + error = map_uri_to_local(rcvd, "rsync://", workspace, &local_path); if (error) - return error != -ENOMEM ? EINVAL : error; - - local_path = strdup(uri_get_local(uri)); - if (local_path == NULL) { - error = pr_enomem(); - goto release_uri; - } + return error; error = stat(local_path, &attr); if (error) { @@ -161,14 +155,11 @@ get_local_path(char const *rcvd, char **result) tmp[tmp_size] = '\0'; free(local_path); - uri_refput(uri); *result = tmp; return 0; release_local: free(local_path); -release_uri: - uri_refput(uri); return error; } @@ -212,7 +203,7 @@ rename_local_path(char const *rcvd, char **result) } static int -rename_all_roots(struct rem_dirs *rem_dirs, char **src) +rename_all_roots(struct rem_dirs *rem_dirs, char **src, char const *workspace) { char *local_path, *delete_path; size_t i; @@ -221,7 +212,7 @@ rename_all_roots(struct rem_dirs *rem_dirs, char **src) for (i = 0; i < rem_dirs->arr_len; i++) { local_path = NULL; error = get_local_path(src[(rem_dirs->arr_len - 1) - i], - &local_path); + workspace, &local_path); if (error < 0) return error; if (error > 0) @@ -274,7 +265,8 @@ rem_dirs_destroy(struct rem_dirs *rem_dirs) } /* - * Remove the files listed at @roots array of @roots_len size. + * Remove the files listed at @roots array of @roots_len size. The local files + * will be searched at the specified HTTP local @workspace. * * The daemon will be as quiet as possible, since most of its job is done * asynchronously. Also, it works on the best possible effort; some errors are @@ -282,7 +274,7 @@ rem_dirs_destroy(struct rem_dirs *rem_dirs) * considers the relations (parent-child) at dirs. */ int -delete_dir_daemon_start(char **roots, size_t roots_len) +delete_dir_daemon_start(char **roots, size_t roots_len, char const *workspace) { pthread_t thread; struct rem_dirs *arg; @@ -293,7 +285,7 @@ delete_dir_daemon_start(char **roots, size_t roots_len) if (error) return error; - error = rename_all_roots(arg, roots); + error = rename_all_roots(arg, roots, workspace); if (error) { rem_dirs_destroy(arg); return error; diff --git a/src/delete_dir_daemon.h b/src/delete_dir_daemon.h index 992d9234..3bee47f5 100644 --- a/src/delete_dir_daemon.h +++ b/src/delete_dir_daemon.h @@ -3,6 +3,6 @@ #include -int delete_dir_daemon_start(char **, size_t); +int delete_dir_daemon_start(char **, size_t, char const *); #endif /* SRC_DELETE_DIR_DAEMON_H_ */ diff --git a/src/object/certificate.c b/src/object/certificate.c index 2446ab00..65fd0f10 100644 --- a/src/object/certificate.c +++ b/src/object/certificate.c @@ -2027,13 +2027,12 @@ verify_mft_loc(struct rpki_uri *mft_uri) } /* - * Verify the manifest location at the local RRDP workspace. If the manifest - * exists, then update @mft_uri so that its location be at the workspace. + * Verify the manifest location at the local RRDP workspace. * * Don't log in case the @mft_uri doesn't exist at the RRDP workspace. */ static int -verify_rrdp_mft_loc(struct rpki_uri **mft_uri) +verify_rrdp_mft_loc(struct rpki_uri *mft_uri) { struct rpki_uri *tmp; int error; @@ -2042,18 +2041,17 @@ verify_rrdp_mft_loc(struct rpki_uri **mft_uri) return -ENOENT; tmp = NULL; - error = uri_create_rsync_str_rrdp(&tmp, uri_get_global(*mft_uri), - uri_get_global_len(*mft_uri)); + error = uri_create_rsync_str_rrdp(&tmp, uri_get_global(mft_uri), + uri_get_global_len(mft_uri)); if (error) return error; if (!valid_file_or_dir(uri_get_local(tmp), true, false, NULL)) { uri_refput(tmp); - return -EINVAL; + return -ENOENT; } - uri_refput(*mft_uri); - *mft_uri = tmp; + uri_refput(tmp); return 0; } @@ -2079,6 +2077,7 @@ replace_rrdp_mft_uri(struct sia_uri *sia_mft) static int exec_rrdp_method(struct sia_ca_uris *sia_uris) { + bool data_updated; int error; /* Start working on the RRDP local workspace */ @@ -2086,34 +2085,64 @@ exec_rrdp_method(struct sia_ca_uris *sia_uris) if (error) return error; - error = rrdp_load(sia_uris->rpkiNotify.uri); - if (error) { - db_rrdp_uris_workspace_disable(); - return error; + data_updated = false; + error = rrdp_load(sia_uris->rpkiNotify.uri, &data_updated); + if (error) + goto err; + + error = verify_rrdp_mft_loc(sia_uris->mft.uri); + switch(error) { + case 0: + /* MFT exists, great! We're good to go. */ + break; + case -ENOENT: + /* Doesn't exist and the RRDP data was updated: error */ + if (data_updated) + goto err; + + /* Otherwise, force the snapshot processing and check again */ + error = rrdp_reload_snapshot(sia_uris->rpkiNotify.uri); + if (error) + goto err; + error = verify_rrdp_mft_loc(sia_uris->mft.uri); + if (error) + goto err; + break; + default: + goto err; } /* Successfully loaded (or no updates yet), update MFT local URI */ error = replace_rrdp_mft_uri(&sia_uris->mft); - if (error) { - db_rrdp_uris_workspace_disable(); - return error; - } + if (error) + goto err; return 0; +err: + db_rrdp_uris_workspace_disable(); + return error; } static int exec_rsync_method(struct sia_ca_uris *sia_uris) { + int error; + /* Stop working on the RRDP local workspace */ db_rrdp_uris_workspace_disable(); - return download_files(sia_uris->caRepository.uri, false, false); + error = download_files(sia_uris->caRepository.uri, false, false); + if (error) + return error; + + return verify_mft_loc(sia_uris->mft.uri); } /* * Currently only two access methods are supported, just consider those two: * rsync and RRDP. If a new access method is supported, this function must * change (and probably the sia_ca_uris struct as well). + * + * Both access method callbacks must verify the manifest existence. */ static int use_access_method(struct sia_ca_uris *sia_uris, @@ -2151,7 +2180,7 @@ use_access_method(struct sia_ca_uris *sia_uris, */ if (!new_level && db_rrdp_uris_workspace_get() != NULL && sia_uris->rpkiNotify.uri == NULL && - verify_rrdp_mft_loc(&sia_uris->mft.uri) == 0) { + verify_rrdp_mft_loc(sia_uris->mft.uri) == 0) { (*retry_repo_sync) = false; return replace_rrdp_mft_uri(&sia_uris->mft); } @@ -2164,6 +2193,8 @@ use_access_method(struct sia_ca_uris *sia_uris, if (sia_uris->rpkiNotify.uri == NULL) { primary_rrdp = false; error = rsync_cb(sia_uris); + if (!error) + return 0; goto verify_mft; } @@ -2208,7 +2239,7 @@ use_access_method(struct sia_ca_uris *sia_uris, error = cb_primary(sia_uris); if (!error) { (*retry_repo_sync) = !primary_rrdp; - goto verify_mft; + return 0; } if (primary_rrdp) { @@ -2235,6 +2266,7 @@ use_access_method(struct sia_ca_uris *sia_uris, working_repo_pop(); verify_mft: + /* Reach here on error or when both access methods were utilized */ switch (error) { case 0: /* Remove the error'd URI, since we got the repo files */ diff --git a/src/rrdp/db/db_rrdp.c b/src/rrdp/db/db_rrdp.c index e1bccc97..45fd480a 100644 --- a/src/rrdp/db/db_rrdp.c +++ b/src/rrdp/db/db_rrdp.c @@ -126,7 +126,7 @@ static void tal_elem_destroy(struct tal_elem *elem, bool remove_local) { if (remove_local) - db_rrdp_uris_remove_all_local(elem->uris); + db_rrdp_uris_remove_all_local(elem->uris, elem->workspace); db_rrdp_uris_destroy(elem->uris); free(elem->file_name); free(elem->workspace); diff --git a/src/rrdp/db/db_rrdp_uris.c b/src/rrdp/db/db_rrdp_uris.c index 9928a7eb..51f24ee8 100644 --- a/src/rrdp/db/db_rrdp_uris.c +++ b/src/rrdp/db/db_rrdp_uris.c @@ -350,14 +350,15 @@ db_rrdp_uris_get_visited_uris(char const *uri, struct visited_uris **result) } int -db_rrdp_uris_remove_all_local(struct db_rrdp_uri *uris) +db_rrdp_uris_remove_all_local(struct db_rrdp_uri *uris, char const *workspace) { struct uris_table *uri_node, *uri_tmp; int error; /* Remove each 'visited_uris' from all the table */ HASH_ITER(hh, uris->table, uri_node, uri_tmp) { - error = visited_uris_delete_local(uri_node->visited_uris); + error = visited_uris_delete_local(uri_node->visited_uris, + workspace); if (error) return error; } diff --git a/src/rrdp/db/db_rrdp_uris.h b/src/rrdp/db/db_rrdp_uris.h index e9896276..63ac8060 100644 --- a/src/rrdp/db/db_rrdp_uris.h +++ b/src/rrdp/db/db_rrdp_uris.h @@ -36,7 +36,7 @@ int db_rrdp_uris_set_all_unvisited(void); int db_rrdp_uris_get_visited_uris(char const *, struct visited_uris **); -int db_rrdp_uris_remove_all_local(struct db_rrdp_uri *); +int db_rrdp_uris_remove_all_local(struct db_rrdp_uri *, char const *); char const *db_rrdp_uris_workspace_get(void); int db_rrdp_uris_workspace_enable(void); diff --git a/src/rrdp/rrdp_loader.c b/src/rrdp/rrdp_loader.c index 3755051e..14dd65f3 100644 --- a/src/rrdp/rrdp_loader.c +++ b/src/rrdp/rrdp_loader.c @@ -59,6 +59,7 @@ static int remove_rrdp_uri_files(char const *notification_uri) { struct visited_uris *tmp; + char const *workspace; int error; /* Work with the existent visited uris */ @@ -66,7 +67,9 @@ remove_rrdp_uri_files(char const *notification_uri) if (error) return error; - return visited_uris_delete_local(tmp); + workspace = db_rrdp_uris_workspace_get(); + + return visited_uris_delete_local(tmp, workspace); } /* Mark the URI as errored with dummy data, so it won't be requested again */ @@ -93,20 +96,21 @@ mark_rrdp_uri_request_err(char const *notification_uri) return 0; } -/* - * Try to get RRDP Update Notification file and process it accordingly. - * - * If there's an error that could lead to an inconsistent local repository - * state, marks the @uri as error'd so that it won't be requested again during - * the same validation cycle. - * - * If there are no errors, updates the local DB and marks the @uri as visited. - * - * If the @uri is being visited again, verify its previous visit state. If there - * were no errors, just return success; otherwise, return error code -EPERM. - */ -int -rrdp_load(struct rpki_uri *uri) +static int +process_diff_session(struct update_notification *notification, + bool log_operation, struct visited_uris **visited) +{ + int error; + + error = remove_rrdp_uri_files(notification->uri); + if (error) + return error; + + return process_snapshot(notification, log_operation, visited); +} + +static int +__rrdp_load(struct rpki_uri *uri, bool force_snapshot, bool *data_updated) { struct update_notification *upd_notification; struct visited_uris *visited; @@ -115,8 +119,12 @@ rrdp_load(struct rpki_uri *uri) bool log_operation; int error, upd_error; - if (!config_get_http_enabled()) + (*data_updated) = false; + + if (!config_get_http_enabled()) { + (*data_updated) = true; return 0; + } /* Avoid multiple requests on the same run */ requested = RRDP_URI_REQ_UNVISITED; @@ -125,18 +133,27 @@ rrdp_load(struct rpki_uri *uri) if (error && error != -ENOENT) return error; - switch(requested) { - case RRDP_URI_REQ_VISITED: - return 0; - case RRDP_URI_REQ_UNVISITED: - break; - case RRDP_URI_REQ_ERROR: - /* Log has been done before this call */ - return -EPERM; + if (!force_snapshot) { + switch(requested) { + case RRDP_URI_REQ_VISITED: + (*data_updated) = true; + return 0; + case RRDP_URI_REQ_UNVISITED: + break; + case RRDP_URI_REQ_ERROR: + /* Log has been done before this call */ + return -EPERM; + } + } else { + if (requested != RRDP_URI_REQ_VISITED) { + pr_val_info("Skipping RRDP snapshot reload"); + return -EINVAL; + } } log_operation = reqs_errors_log_uri(uri_get_global(uri)); - error = rrdp_parse_notification(uri, log_operation, &upd_notification); + error = rrdp_parse_notification(uri, log_operation, force_snapshot, + &upd_notification); if (error) goto upd_end; @@ -146,44 +163,56 @@ rrdp_load(struct rpki_uri *uri) goto upd_end; } - error = db_rrdp_uris_cmp(uri_get_global(uri), - upd_notification->global_data.session_id, - upd_notification->global_data.serial, - &res); - if (error) - goto upd_destroy; + do { + /* Same flow as a session update */ + if (force_snapshot) { + error = process_diff_session(upd_notification, + log_operation, &visited); + if (error) + goto upd_destroy; + (*data_updated) = true; + break; + } - switch (res) { - case RRDP_URI_EQUAL: - goto set_update; - case RRDP_URI_DIFF_SESSION: - /* Delete the old session files */ - error = remove_rrdp_uri_files(upd_notification->uri); - if (error) - goto upd_destroy; - error = process_snapshot(upd_notification, log_operation, - &visited); + error = db_rrdp_uris_cmp(uri_get_global(uri), + upd_notification->global_data.session_id, + upd_notification->global_data.serial, + &res); if (error) goto upd_destroy; - break; - case RRDP_URI_DIFF_SERIAL: - error = process_diff_serial(upd_notification, log_operation, - &visited); - if (!error) { - visited_uris_refget(visited); + + switch (res) { + case RRDP_URI_EQUAL: + goto set_update; + case RRDP_URI_DIFF_SESSION: + /* Delete the old session files */ + error = process_diff_session(upd_notification, + log_operation, &visited); + if (error) + goto upd_destroy; + (*data_updated) = true; + break; + case RRDP_URI_DIFF_SERIAL: + error = process_diff_serial(upd_notification, + log_operation, &visited); + if (!error) { + visited_uris_refget(visited); + (*data_updated) = true; + break; + } + /* Something went wrong, use snapshot */ + pr_val_info("There was an error processing RRDP deltas, using the snapshot instead."); + case RRDP_URI_NOTFOUND: + error = process_snapshot(upd_notification, log_operation, + &visited); + if (error) + goto upd_destroy; + (*data_updated) = true; break; + default: + pr_crit("Unexpected RRDP URI comparison result"); } - /* Something went wrong, use snapshot */ - pr_val_info("There was an error processing RRDP deltas, using the snapshot instead."); - case RRDP_URI_NOTFOUND: - error = process_snapshot(upd_notification, log_operation, - &visited); - if (error) - goto upd_destroy; - break; - default: - pr_crit("Unexpected RRDP URI comparison result"); - } + } while (0); /* Any update, and no error during the process, update db as well */ pr_val_debug("Updating local RRDP data of '%s' to:", uri_get_global(uri)); @@ -231,3 +260,42 @@ upd_end: return error; } + +/* + * Try to get RRDP Update Notification file and process it accordingly. + * + * If there's an error that could lead to an inconsistent local repository + * state, marks the @uri as error'd so that it won't be requested again during + * the same validation cycle. + * + * If there are no errors, updates the local DB and marks the @uri as visited. + * + * If the @uri is being visited again, verify its previous visit state. If there + * were no errors, just return success; otherwise, return error code -EPERM. + * + * @data_updated will be true if: + * - Delta files were processed + * - Snapshot file was processed + * - @uri was already visited at this cycle + */ +int +rrdp_load(struct rpki_uri *uri, bool *data_updated) +{ + return __rrdp_load(uri, false, data_updated); +} + +/* + * Force the processing of the snapshot. The update notification is requested + * again, omitting the 'If-Modified-Since' header at the HTTP request. + * + * Shouldn't be called if @uri had a previous error or hasn't been requested, + * still the check is done. + */ +int +rrdp_reload_snapshot(struct rpki_uri *uri) +{ + bool tmp; + + tmp = false; + return __rrdp_load(uri, true, &tmp); +} diff --git a/src/rrdp/rrdp_loader.h b/src/rrdp/rrdp_loader.h index 3b8025ac..2cf8f8b0 100644 --- a/src/rrdp/rrdp_loader.h +++ b/src/rrdp/rrdp_loader.h @@ -1,8 +1,10 @@ #ifndef SRC_RRDP_RRDP_LOADER_H_ #define SRC_RRDP_RRDP_LOADER_H_ +#include #include "uri.h" -int rrdp_load(struct rpki_uri *); +int rrdp_load(struct rpki_uri *, bool *); +int rrdp_reload_snapshot(struct rpki_uri *); #endif /* SRC_RRDP_RRDP_LOADER_H_ */ diff --git a/src/rrdp/rrdp_parser.c b/src/rrdp/rrdp_parser.c index 69d33063..b9593162 100644 --- a/src/rrdp/rrdp_parser.c +++ b/src/rrdp/rrdp_parser.c @@ -1057,9 +1057,11 @@ release_uri: * * If the server didn't sent the file, due to the validation of * 'If-Modified-Since' header, return 0 and set @result to NULL. + * + * Set @force to true to omit 'If-Modified-Since' header. */ int -rrdp_parse_notification(struct rpki_uri *uri, bool log_operation, +rrdp_parse_notification(struct rpki_uri *uri, bool log_operation, bool force, struct update_notification **result) { long last_update; @@ -1070,9 +1072,11 @@ rrdp_parse_notification(struct rpki_uri *uri, bool log_operation, pr_val_debug("Processing notification '%s'.", uri_get_global(uri)); last_update = 0; - error = db_rrdp_uris_get_last_update(uri_get_global(uri), &last_update); - if (error && error != -ENOENT) - return error; + if (!force) { + error = db_rrdp_uris_get_last_update(uri_get_global(uri), &last_update); + if (error && error != -ENOENT) + return error; + } error = download_file(uri, last_update, log_operation); if (error < 0) diff --git a/src/rrdp/rrdp_parser.h b/src/rrdp/rrdp_parser.h index c5bd60ad..c774ba40 100644 --- a/src/rrdp/rrdp_parser.h +++ b/src/rrdp/rrdp_parser.h @@ -6,7 +6,7 @@ #include "uri.h" #include "visited_uris.h" -int rrdp_parse_notification(struct rpki_uri *, bool, +int rrdp_parse_notification(struct rpki_uri *, bool, bool, struct update_notification **); int rrdp_parse_snapshot(struct update_notification *, struct visited_uris *, bool); diff --git a/src/uri.c b/src/uri.c index ebdfadae..598e01a4 100644 --- a/src/uri.c +++ b/src/uri.c @@ -14,6 +14,9 @@ enum rpki_uri_type { URI_HTTPS, }; +static char const *const PFX_RSYNC = "rsync://"; +static char const *const PFX_HTTPS = "https://"; + /** * All rpki_uris are guaranteed to be RSYNC URLs right now. * @@ -192,7 +195,7 @@ succeed: static int validate_uri_begin(char const *uri_pfx, const size_t uri_pfx_len, - char const *global, size_t global_len, size_t *size, int error) + char const *global, size_t global_len, int error) { if (global_len < uri_pfx_len || strncasecmp(uri_pfx, global, uri_pfx_len) != 0) { @@ -203,16 +206,13 @@ validate_uri_begin(char const *uri_pfx, const size_t uri_pfx_len, return error; } - (*size) = uri_pfx_len; return 0; } static int validate_gprefix(char const *global, size_t global_len, uint8_t flags, - size_t *size, enum rpki_uri_type *type) + enum rpki_uri_type *type) { - static char const *const PFX_RSYNC = "rsync://"; - static char const *const PFX_HTTPS = "https://"; size_t const PFX_RSYNC_LEN = strlen(PFX_RSYNC); size_t const PFX_HTTPS_LEN = strlen(PFX_HTTPS); uint8_t l_flags; @@ -224,25 +224,25 @@ validate_gprefix(char const *global, size_t global_len, uint8_t flags, if (l_flags == URI_VALID_RSYNC) { (*type) = URI_RSYNC; return validate_uri_begin(PFX_RSYNC, PFX_RSYNC_LEN, global, - global_len, size, ENOTRSYNC); + global_len, ENOTRSYNC); } if (l_flags == URI_VALID_HTTPS) { (*type) = URI_HTTPS; return validate_uri_begin(PFX_HTTPS, PFX_HTTPS_LEN, global, - global_len, size, ENOTHTTPS); + global_len, ENOTHTTPS); } if (l_flags != (URI_VALID_RSYNC | URI_VALID_HTTPS)) pr_crit("Unknown URI flag"); /* It has both flags */ error = validate_uri_begin(PFX_RSYNC, PFX_RSYNC_LEN, global, global_len, - size, 0); + 0); if (!error) { (*type) = URI_RSYNC; return 0; } error = validate_uri_begin(PFX_HTTPS, PFX_HTTPS_LEN, global, global_len, - size, 0); + 0); if (error) { pr_val_warn("URI '%s' does not begin with '%s' nor '%s'.", global, PFX_RSYNC, PFX_HTTPS); @@ -255,7 +255,7 @@ validate_gprefix(char const *global, size_t global_len, uint8_t flags, } static int -get_local_workspace(char **result, size_t *result_len) +get_local_workspace(char **result) { char const *workspace; char *tmp; @@ -263,7 +263,6 @@ get_local_workspace(char **result, size_t *result_len) workspace = db_rrdp_uris_workspace_get(); if (workspace == NULL) { *result = NULL; - *result_len = 0; return 0; } @@ -272,7 +271,6 @@ get_local_workspace(char **result, size_t *result_len) return pr_enomem(); *result = tmp; - *result_len = strlen(tmp); return 0; } @@ -290,57 +288,30 @@ static int g2l(char const *global, size_t global_len, uint8_t flags, char **result, enum rpki_uri_type *result_type) { - char const *repository; char *local; char *workspace; - size_t prefix_len; - size_t repository_len; - size_t extra_slash; - size_t offset; - size_t workspace_len; enum rpki_uri_type type; int error; - repository = config_get_local_repository(); - repository_len = strlen(repository); - - error = validate_gprefix(global, global_len, flags, &prefix_len, &type); + error = validate_gprefix(global, global_len, flags, &type); if (error) return error; - global += prefix_len; - global_len -= prefix_len; - extra_slash = (repository[repository_len - 1] == '/') ? 0 : 1; - workspace = NULL; - workspace_len = 0; if ((flags & URI_USE_RRDP_WORKSPACE) != 0) { - error = get_local_workspace(&workspace, &workspace_len); + error = get_local_workspace(&workspace); if (error) return error; } - local = malloc(repository_len + extra_slash + workspace_len + - global_len + 1); - if (!local) { + error = map_uri_to_local(global, + type == URI_RSYNC ? PFX_RSYNC : PFX_HTTPS, + workspace, + &local); + if (error) { free(workspace); - return pr_enomem(); - } - - offset = 0; - strcpy(local + offset, repository); - offset += repository_len; - if (extra_slash) { - strcpy(local + offset, "/"); - offset += extra_slash; - } - if (workspace_len > 0) { - strcpy(local + offset, workspace); - offset += workspace_len; + return error; } - strncpy(local + offset, global, global_len); - offset += global_len; - local[offset] = '\0'; free(workspace); *result = local; diff --git a/src/visited_uris.c b/src/visited_uris.c index a1ee1e8c..987c7357 100644 --- a/src/visited_uris.c +++ b/src/visited_uris.c @@ -162,8 +162,11 @@ uris_root_destroy(char **elem) free(*elem); } +/* + * Delete all the corresponding local files of @uris located at @workspace + */ int -visited_uris_delete_local(struct visited_uris *uris) +visited_uris_delete_local(struct visited_uris *uris, char const *workspace) { struct uris_roots roots; int error; @@ -177,7 +180,7 @@ visited_uris_delete_local(struct visited_uris *uris) if (roots.len == 0) goto success; - error = delete_dir_daemon_start(roots.array, roots.len); + error = delete_dir_daemon_start(roots.array, roots.len, workspace); if (error) goto err; success: diff --git a/src/visited_uris.h b/src/visited_uris.h index 9e30ab39..9557482b 100644 --- a/src/visited_uris.h +++ b/src/visited_uris.h @@ -1,8 +1,6 @@ #ifndef SRC_VISITED_URIS_H_ #define SRC_VISITED_URIS_H_ -#include - struct visited_uris; int visited_uris_create(struct visited_uris **); @@ -11,6 +9,6 @@ void visited_uris_refget(struct visited_uris *); int visited_uris_add(struct visited_uris *, char const *); int visited_uris_remove(struct visited_uris *, char const *); -int visited_uris_delete_local(struct visited_uris *); +int visited_uris_delete_local(struct visited_uris *, char const *); #endif /* SRC_VISITED_URIS_H_ */