]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Fix bug: data can be stale when the local-repository is deleted.
authorpcarana <pc.moreno2099@gmail.com>
Sat, 17 Oct 2020 01:27:26 +0000 (20:27 -0500)
committerpcarana <pc.moreno2099@gmail.com>
Sat, 17 Oct 2020 01:27:26 +0000 (20:27 -0500)
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.

15 files changed:
src/common.c
src/common.h
src/delete_dir_daemon.c
src/delete_dir_daemon.h
src/object/certificate.c
src/rrdp/db/db_rrdp.c
src/rrdp/db/db_rrdp_uris.c
src/rrdp/db/db_rrdp_uris.h
src/rrdp/rrdp_loader.c
src/rrdp/rrdp_loader.h
src/rrdp/rrdp_parser.c
src/rrdp/rrdp_parser.h
src/uri.c
src/visited_uris.c
src/visited_uris.h

index 85d86893b5b4be277abac12bf3b2b1b0e6b45721..05e386e0b8838150c4abe334ee5a1b1f55014a54 100644 (file)
@@ -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;
+}
index f4f311be5c2c05fb46a168ab0604c8502e21b660..24fd976a0933b7d1cf79fbd5dfe2b99d8e3b65a3 100644 (file)
@@ -2,7 +2,6 @@
 #define SRC_RTR_COMMON_H_
 
 #include <pthread.h>
-#include <semaphore.h>
 #include <stdbool.h>
 #include <time.h>
 #include <netinet/in.h>
@@ -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_ */
index d81e82f1f79f1772b64791561746bc4282cbf7cb..92f25843162e135f4835676e605924457ee3c927 100644 (file)
@@ -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;
index 992d9234ea050150bdcfd50f96e154f40eef788c..3bee47f5acfb906706c05436549fccd3f80db46b 100644 (file)
@@ -3,6 +3,6 @@
 
 #include <stddef.h>
 
-int delete_dir_daemon_start(char **, size_t);
+int delete_dir_daemon_start(char **, size_t, char const *);
 
 #endif /* SRC_DELETE_DIR_DAEMON_H_ */
index 2446ab004f106f9d6f94759a190207e57041c2ee..65fd0f102ecea8ad9e474e71b4428406b087c373 100644 (file)
@@ -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 */
index e1bccc9792b106f56aaff64dcd572b554a6d7711..45fd480a75c158e4b0c0f47ee28140359d726d47 100644 (file)
@@ -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);
index 9928a7eb5b3fa67568b37a504e831d6a858d79ee..51f24ee80ddd8af09b962a4f261f65ee908fd92c 100644 (file)
@@ -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;
        }
index e9896276912f62b150cc730c48c68db937552eb9..63ac806069d171029a30a71f3c2bd5a38257af9e 100644 (file)
@@ -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);
index 3755051ebf7c24631aa3a2dbb842f3f7e401e694..14dd65f3346d99333a1cac3e99404596a790334d 100644 (file)
@@ -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);
+}
index 3b8025acd13987342a8a18a012a116aa4cd1b71a..2cf8f8b0f9690d0e7cb9d6cb78470a7fe40549bc 100644 (file)
@@ -1,8 +1,10 @@
 #ifndef SRC_RRDP_RRDP_LOADER_H_
 #define SRC_RRDP_RRDP_LOADER_H_
 
+#include <stdbool.h>
 #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_ */
index 69d33063230fe77fba1f155096b12ac92eccb0eb..b9593162baa3d6034668ad517f8ed2781c5cc097 100644 (file)
@@ -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)
index c5bd60adce55139c854e26922414280accb9bdf1..c774ba40dd6bdc768b9ad65f7b030a6570e1edfb 100644 (file)
@@ -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);
index ebdfadae418ddb7660b265818221e9c2ad2efd52..598e01a40a5df90527301cc0604ec7c8606b1b63 100644 (file)
--- 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;
index a1ee1e8c5bef592fb5efb1d30251d6c71b3b42ae..987c73575a2276bf34ed63a5de0cdf1960aaa167 100644 (file)
@@ -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:
index 9e30ab396b9f5f78646a7e4d63b7a8b421e23054..9557482b74974317687c4c036628463fda2123ec 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef SRC_VISITED_URIS_H_
 #define SRC_VISITED_URIS_H_
 
-#include <stdbool.h>
-
 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_ */