]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Avoid HTTP requests on previously error'd URIs.
authorpcarana <pc.moreno2099@gmail.com>
Fri, 17 Jan 2020 23:40:18 +0000 (17:40 -0600)
committerpcarana <pc.moreno2099@gmail.com>
Fri, 17 Jan 2020 23:40:18 +0000 (17:40 -0600)
+Create type to set RRDP URIs request status (error, unvisited, visited). The status is set accordingly to the result of the last request and processing of the RRDP Update Notification URIs; during RRDP loading, the status is validated to either do a request (URIs hasn't been visited) or skip it (was previously visited or had an error). If a request had an error, then continue the access methods flow considering priorities.
+Update RET_NOT_FOUND_URI macro, it always returned the same error code.
+Remove downloaded files via HTTP (and its local directory structure) whenever there's an error during the download process.

src/http/http.c
src/object/certificate.c
src/object/tal.c
src/rrdp/db/db_rrdp_uris.c
src/rrdp/db/db_rrdp_uris.h
src/rrdp/rrdp_loader.c
src/rrdp/rrdp_parser.c

index a55faf08e1408e640dcb3d46d1166b09fbb81378..3ae0f89bb5801453d01097188e08e6424c220e1d 100644 (file)
@@ -146,7 +146,7 @@ __http_download_file(struct rpki_uri *uri, http_write_cb cb,
 
        error = file_write(uri_get_local(uri), &out, &stat);
        if (error)
-               return ENSURE_NEGATIVE(error);
+               goto delete_dir;
 
        error = http_easy_init(&handler);
        if (error)
@@ -164,10 +164,13 @@ __http_download_file(struct rpki_uri *uri, http_write_cb cb,
        http_easy_cleanup(&handler);
        file_close(out);
 
-       /* Error 0 it's ok */
-       return ENSURE_NEGATIVE(error);
+       if (error)
+               goto delete_dir;
+
+       return 0;
 close_file:
        file_close(out);
+delete_dir:
        delete_dir_recursive_bottom_up(uri_get_local(uri));
        return ENSURE_NEGATIVE(error);
 }
index 5def8cab4608fe376c56f5cd6365f652e024398a..3b720ec4a50fc1c2cd703c8f8b1dbdb6431997e7 100644 (file)
@@ -1930,14 +1930,20 @@ use_access_method(struct sia_ca_uris *sia_uris,
        if (!error)
                return 0;
 
-       if (primary_rrdp)
-               pr_warn("Couldn't fetch data from RRDP repository '%s', trying to fetch data now from '%s'.",
-                   uri_get_global(sia_uris->rpkiNotify.uri),
-                   uri_get_global(sia_uris->caRepository.uri));
-       else
+       if (primary_rrdp) {
+               if (error != -EPERM)
+                       pr_warn("Couldn't fetch data from RRDP repository '%s', trying to fetch data now from '%s'.",
+                           uri_get_global(sia_uris->rpkiNotify.uri),
+                           uri_get_global(sia_uris->caRepository.uri));
+               else
+                       pr_debug("RRDP repository '%s' download/processing returned error previously, now I will try to fetch data from '%s'.",
+                           uri_get_global(sia_uris->rpkiNotify.uri),
+                           uri_get_global(sia_uris->caRepository.uri));
+       } else {
                pr_warn("Couldn't fetch data from repository '%s', trying to fetch data now from RRDP '%s'.",
                    uri_get_global(sia_uris->caRepository.uri),
                    uri_get_global(sia_uris->rpkiNotify.uri));
+       }
 
        return cb_secondary(sia_uris);
 }
index 187f154a71c17da1b0bb73ce7e7ab5c01c6029cc..d1b908e25494f88ef7da01849b0e210213556b87 100644 (file)
@@ -510,7 +510,7 @@ handle_tal_uri(struct tal *tal, struct rpki_uri *uri, void *arg)
         * Set all RRDPs URIs to non-requested, this way we will force the
         * request on every cycle (to check if there are updates).
         */
-       error = db_rrdp_uris_set_all_nonrequested();
+       error = db_rrdp_uris_set_all_unvisited();
        if (error)
                goto end;
 
index e99c6b3b03b45d2094e8e17adb97118551174a06..b00a222a1a8ae0808030c35045d119c7d587e404 100644 (file)
@@ -16,7 +16,7 @@ struct uris_table {
        /* Last local update of the URI (after a successful processing) */
        long last_update;
        /* The URI has been requested (HTTPS) at this cycle? */
-       bool requested;
+       rrdp_req_status_t request_status;
        /* MFT URIs loaded from the @uri */
        struct visited_uris *visited_uris;
        UT_hash_handle hh;
@@ -28,7 +28,8 @@ struct db_rrdp_uri {
 
 static int
 uris_table_create(char const *uri, char const *session_id,
-    unsigned long serial, struct uris_table **result)
+    unsigned long serial, rrdp_req_status_t req_status,
+    struct uris_table **result)
 {
        struct uris_table *tmp;
        int error;
@@ -53,7 +54,7 @@ uris_table_create(char const *uri, char const *session_id,
 
        tmp->data.serial = serial;
        tmp->last_update = 0;
-       tmp->requested = true;
+       tmp->request_status = req_status;
        tmp->visited_uris = NULL;
 
        *result = tmp;
@@ -82,10 +83,10 @@ find_rrdp_uri(struct db_rrdp_uri *uris, const char *search)
        return found;
 }
 
-#define RET_NOT_FOUND_URI(uris, search, found, retval)                 \
+#define RET_NOT_FOUND_URI(uris, search, found)                         \
        found = find_rrdp_uri(uris, search);                            \
        if (found == NULL)                                              \
-               return retval;
+               return -ENOENT;
 
 static void
 add_rrdp_uri(struct db_rrdp_uri *uris, struct uris_table *new_uri)
@@ -175,7 +176,8 @@ db_rrdp_uris_cmp(char const *uri, char const *session_id, unsigned long serial,
 
 int
 db_rrdp_uris_update(char const *uri, char const *session_id,
-    unsigned long serial, struct visited_uris *visited_uris)
+    unsigned long serial, rrdp_req_status_t req_status,
+    struct visited_uris *visited_uris)
 {
        struct db_rrdp_uri *uris;
        struct uris_table *db_uri;
@@ -186,7 +188,7 @@ db_rrdp_uris_update(char const *uri, char const *session_id,
                return error;
 
        db_uri = NULL;
-       error = uris_table_create(uri, session_id, serial, &db_uri);
+       error = uris_table_create(uri, session_id, serial, req_status, &db_uri);
        if (error)
                return error;
 
@@ -209,7 +211,7 @@ db_rrdp_uris_get_serial(char const *uri, unsigned long *serial)
        if (error)
                return error;
 
-       RET_NOT_FOUND_URI(uris, uri, found, -ENOENT)
+       RET_NOT_FOUND_URI(uris, uri, found)
        *serial = found->data.serial;
        return 0;
 }
@@ -225,7 +227,7 @@ db_rrdp_uris_get_last_update(char const *uri, long *date)
        if (error)
                return error;
 
-       RET_NOT_FOUND_URI(uris, uri, found, -ENOENT)
+       RET_NOT_FOUND_URI(uris, uri, found)
        *date = found->last_update;
        return 0;
 }
@@ -255,12 +257,12 @@ db_rrdp_uris_set_last_update(char const *uri)
        if (error)
                return error;
 
-       RET_NOT_FOUND_URI(uris, uri, found, -ENOENT)
+       RET_NOT_FOUND_URI(uris, uri, found)
        return get_current_time(&found->last_update);
 }
 
 int
-db_rrdp_uris_get_requested(char const *uri, bool *result)
+db_rrdp_uris_get_request_status(char const *uri, rrdp_req_status_t *result)
 {
        struct db_rrdp_uri *uris;
        struct uris_table *found;
@@ -270,13 +272,13 @@ db_rrdp_uris_get_requested(char const *uri, bool *result)
        if (error)
                return error;
 
-       RET_NOT_FOUND_URI(uris, uri, found, -ENOENT)
-       *result = found->requested;
+       RET_NOT_FOUND_URI(uris, uri, found)
+       *result = found->request_status;
        return 0;
 }
 
 int
-db_rrdp_uris_set_requested(char const *uri, bool value)
+db_rrdp_uris_set_request_status(char const *uri, rrdp_req_status_t value)
 {
        struct db_rrdp_uri *uris;
        struct uris_table *found;
@@ -286,13 +288,13 @@ db_rrdp_uris_set_requested(char const *uri, bool value)
        if (error)
                return error;
 
-       RET_NOT_FOUND_URI(uris, uri, found, -ENOENT)
-       found->requested = value;
+       RET_NOT_FOUND_URI(uris, uri, found)
+       found->request_status = value;
        return 0;
 }
 
 int
-db_rrdp_uris_set_all_nonrequested(void)
+db_rrdp_uris_set_all_unvisited(void)
 {
        struct db_rrdp_uri *uris;
        struct uris_table *uri_node, *uri_tmp;
@@ -303,7 +305,7 @@ db_rrdp_uris_set_all_nonrequested(void)
                return error;
 
        HASH_ITER(hh, uris->table, uri_node, uri_tmp)
-               uri_node->requested = false;
+               uri_node->request_status = RRDP_URI_REQ_UNVISITED;
 
        return 0;
 }
@@ -323,7 +325,7 @@ db_rrdp_uris_get_visited_uris(char const *uri, struct visited_uris **result)
        if (error)
                return error;
 
-       RET_NOT_FOUND_URI(uris, uri, found, -ENOENT)
+       RET_NOT_FOUND_URI(uris, uri, found)
        *result = found->visited_uris;
        return 0;
 }
index f221987a5fd2a959ffff08f690d5fe1b7c55e7f1..737c38bd34f9c432911f7e2d07166a8d303e5df8 100644 (file)
@@ -5,6 +5,12 @@
 #include "rrdp/rrdp_objects.h"
 #include "visited_uris.h"
 
+typedef enum {
+       RRDP_URI_REQ_ERROR,
+       RRDP_URI_REQ_UNVISITED,
+       RRDP_URI_REQ_VISITED,
+} rrdp_req_status_t;
+
 /*
  * RRDP URI fetched from 'rpkiNotify' OID at a CA certificate, each TAL thread
  * may have a reference to one of these (it holds information such as update
@@ -18,15 +24,15 @@ void db_rrdp_uris_destroy(struct db_rrdp_uri *);
 int db_rrdp_uris_cmp(char const *, char const *, unsigned long,
     rrdp_uri_cmp_result_t *);
 int db_rrdp_uris_update(char const *, char const *session_id, unsigned long,
-    struct visited_uris *);
+    rrdp_req_status_t, struct visited_uris *);
 int db_rrdp_uris_get_serial(char const *, unsigned long *);
 
 int db_rrdp_uris_get_last_update(char const *, long *);
 int db_rrdp_uris_set_last_update(char const *);
 
-int db_rrdp_uris_get_requested(char const *, bool *);
-int db_rrdp_uris_set_requested(char const *, bool);
-int db_rrdp_uris_set_all_nonrequested(void);
+int db_rrdp_uris_get_request_status(char const *, rrdp_req_status_t *);
+int db_rrdp_uris_set_request_status(char const *, rrdp_req_status_t);
+int db_rrdp_uris_set_all_unvisited(void);
 
 int db_rrdp_uris_get_visited_uris(char const *, struct visited_uris **);
 
index 40913b48de71c720579a2529c4006151f486c3a3..301abf70e692a2ed727268fedb533fba02d88962 100644 (file)
@@ -65,30 +65,73 @@ remove_rrdp_uri_files(char const *notification_uri)
        return visited_uris_remove_local(tmp);
 }
 
+/* Mark the URI as errored with dummy data, so it won't be requested again */
+static int
+mark_rrdp_uri_request_err(char const *notification_uri)
+{
+       struct visited_uris *tmp;
+       int error;
+
+       pr_debug("RRDP data of '%s' won't be requested again during this cycle due to previous error.",
+           notification_uri);
+
+       error = visited_uris_create(&tmp);
+       if (error)
+               return error;
+
+       error = db_rrdp_uris_update(notification_uri, "", 0,
+           RRDP_URI_REQ_ERROR, tmp);
+       if (error) {
+               visited_uris_refput(tmp);
+               return error;
+       }
+
+       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)
 {
        struct update_notification *upd_notification;
        struct visited_uris *visited;
+       rrdp_req_status_t requested;
        rrdp_uri_cmp_result_t res;
-       int error;
-       bool requested;
+       int error, upd_error;
 
        if (!config_get_rrdp_enabled())
                return 0;
 
        /* Avoid multiple requests on the same run */
-       requested = false;
-       error = db_rrdp_uris_get_requested(uri_get_global(uri), &requested);
+       requested = RRDP_URI_REQ_UNVISITED;
+       error = db_rrdp_uris_get_request_status(uri_get_global(uri), &requested);
        if (error && error != -ENOENT)
                return error;
 
-       if (requested)
+       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;
+       }
 
        error = rrdp_parse_notification(uri, &upd_notification);
        if (error)
-               return error;
+               goto upd_error;
 
        /* No updates at the file (yet), didn't pushed to fnstack */
        if (upd_notification == NULL) {
@@ -101,7 +144,7 @@ rrdp_load(struct rpki_uri *uri)
            upd_notification->global_data.serial,
            &res);
        if (error)
-               goto end;
+               goto upd_destroy;
 
        switch (res) {
        case RRDP_URI_EQUAL:
@@ -127,7 +170,7 @@ rrdp_load(struct rpki_uri *uri)
        }
 
        if (error)
-               goto end;
+               goto upd_destroy;
 
        /* Any update, and no error during the process, update db as well */
        pr_debug("Updating local RRDP data of '%s' to:", uri_get_global(uri));
@@ -136,20 +179,27 @@ rrdp_load(struct rpki_uri *uri)
        error = db_rrdp_uris_update(uri_get_global(uri),
            upd_notification->global_data.session_id,
            upd_notification->global_data.serial,
+           RRDP_URI_REQ_VISITED,
            visited);
        if (error)
-               goto end;
+               goto upd_destroy;
 
 set_update:
        /* Set the last update to now */
        pr_debug("Set last update of RRDP data of '%s' to now.",
            uri_get_global(uri));
-       error = db_rrdp_uris_set_last_update(uri_get_global(uri));
-end:
+       db_rrdp_uris_set_last_update(uri_get_global(uri));
+upd_destroy:
        if (upd_notification != NULL) {
                update_notification_destroy(upd_notification);
                fnstack_pop(); /* Pop from rrdp_parse_notification */
        }
-
+upd_error:
+       /* Don't fall here on success */
+       if (error) {
+               upd_error = mark_rrdp_uri_request_err(uri_get_global(uri));
+               if (upd_error)
+                       return upd_error;
+       }
        return error;
 }
index 9780b0afda002804af8b88826e1e83c42467515e..55bad006270a6fe8ce4d909b75cb22f13428172d 100644 (file)
@@ -1120,9 +1120,10 @@ rrdp_parse_notification(struct rpki_uri *uri,
         * this is probably the first time is visited (first run), so it will
         * be marked as visited when the URI is stored at DB.
         */
-       vis_err = db_rrdp_uris_set_requested(uri_get_global(uri), true);
+       vis_err = db_rrdp_uris_set_request_status(uri_get_global(uri),
+           RRDP_URI_REQ_VISITED);
        if (vis_err && vis_err != -ENOENT)
-               return pr_err("Coudln't mark '%s' as visited",
+               return pr_err("Couldn't mark '%s' as visited",
                    uri_get_global(uri));
 
        /* No updates yet */