]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Add extra rsync and rrdp configurations (enabled and priority).
authorpcarana <pc.moreno2099@gmail.com>
Mon, 13 Jan 2020 19:58:47 +0000 (13:58 -0600)
committerpcarana <pc.moreno2099@gmail.com>
Mon, 13 Jan 2020 19:58:47 +0000 (13:58 -0600)
+The new configuration properties are: 'rsync.enabled', 'rsync.priority', 'rsync.strategy', 'rrdp.enabled', 'rrdp.priority', and 'work-offline'.
+'sync-strategy' will be deprecated but still it can be set. Whenever is set, its value will be set to 'rsync.priority'.
+Fix possible bug at 'visited_uris', a nul char was being set at a wrong location.
+Consider configured priorities and enabled flags whenever an access method is utilized while processing certificates.
+Boolean configuration parameters value can now be set also at command line, using the syntax '--key=value'.
+Remove 'http.disabled' and 'rrdp-disabled', they aren't needed anymore.

17 files changed:
src/Makefile.am
src/config.c
src/config.h
src/config/boolean.c
src/config/boolean.h
src/config/rsync_strategy.c [new file with mode: 0644]
src/config/rsync_strategy.h [new file with mode: 0644]
src/config/sync_strategy.c
src/config/sync_strategy.h
src/config/work_offline.c [new file with mode: 0644]
src/config/work_offline.h [new file with mode: 0644]
src/http/http.c
src/object/certificate.c
src/rrdp/rrdp_loader.c
src/rsync/rsync.c
src/visited_uris.c
test/impersonator.c

index 953a6ae5aba7681a2a9b562adb710edb94f9ce7c..6a10b99003e34b9d646abde3eef18a862009a250 100644 (file)
@@ -46,12 +46,14 @@ fort_SOURCES += config/filename_format.h config/filename_format.c
 fort_SOURCES += config/log_conf.h config/log_conf.c
 fort_SOURCES += config/mode.c config/mode.h
 fort_SOURCES += config/incidences.h config/incidences.c
+fort_SOURCES += config/rsync_strategy.h config/rsync_strategy.c
 fort_SOURCES += config/str.c config/str.h
 fort_SOURCES += config/string_array.h config/string_array.c
 fort_SOURCES += config/sync_strategy.h config/sync_strategy.c
 fort_SOURCES += config/types.h
 fort_SOURCES += config/uint.c config/uint.h
 fort_SOURCES += config/uint32.c config/uint32.h
+fort_SOURCES += config/work_offline.c config/work_offline.h
 
 fort_SOURCES += crypto/base64.h crypto/base64.c
 fort_SOURCES += crypto/hash.h crypto/hash.c
index b2d52794e44cc66fbcbe9c83594cdda83c1f39c4..c785900111cf690e8dbe20cdd1b3489816b4ddb6 100644 (file)
 #include "config/boolean.h"
 #include "config/incidences.h"
 #include "config/str.h"
+#include "config/sync_strategy.h"
 #include "config/uint.h"
 #include "config/uint32.h"
+#include "config/work_offline.h"
 
 /**
  * To add a member to this structure,
@@ -34,10 +36,8 @@ struct rpki_config {
        char *tal;
        /** Path of our local clone of the repository */
        char *local_repository;
-       /** Synchronization (currently only RSYNC) download strategy. */
-       enum sync_strategy sync_strategy;
-       /* Disable RRDP file processing */
-       bool rrdp_disabled;
+       /** FIXME (later) Deprecated, remove it. RSYNC download strategy. */
+       enum rsync_strategy sync_strategy;
        /**
         * Handle TAL URIs in random order?
         * (https://tools.ietf.org/html/rfc8630#section-3, last
@@ -53,6 +53,11 @@ struct rpki_config {
        char *slurm;
        /* Run as RTR server or standalone validation */
        enum mode mode;
+       /*
+        * Disable outgoing requests (currently rsync and http supported), if
+        * 'true' uses only local files located at local-repository.
+        */
+       bool work_offline;
 
        struct {
                /** The bound listening address of the RTR server. */
@@ -72,6 +77,15 @@ struct rpki_config {
        } server;
 
        struct {
+               /* Enables the protocol */
+               bool enabled;
+               /*
+                * Priority, this will override the order set at the CAs in
+                * their accessMethod extension.
+                */
+               unsigned int priority;
+               /* Synchronization download strategy. */
+               enum rsync_strategy strategy;
                char *program;
                struct {
                        struct string_array flat;
@@ -79,6 +93,16 @@ struct rpki_config {
                } args;
        } rsync;
 
+       struct {
+               /* Enables the protocol */
+               bool enabled;
+               /*
+                * Priority, this will override the order set at the CAs in
+                * their accessMethod extension.
+                */
+               unsigned int priority;
+       } rrdp;
+
        struct {
                /* User-Agent header set at requests */
                char *user_agent;
@@ -88,11 +112,6 @@ struct rpki_config {
                unsigned int transfer_timeout;
                /* Directory where CA certs to verify peers are found */
                char *ca_path;
-               /*
-                * Disable HTTP requests, if 'true' uses local files located at
-                * local-repository.
-                */
-               bool disabled;
        } http;
 
        struct {
@@ -194,13 +213,7 @@ static const struct option_field options[] = {
                .name = "sync-strategy",
                .type = &gt_sync_strategy,
                .offset = offsetof(struct rpki_config, sync_strategy),
-               .doc = "RSYNC download strategy",
-       }, {
-               .id = 2000,
-               .name = "rrdp-disabled",
-               .type = &gt_bool,
-               .offset = offsetof(struct rpki_config, rrdp_disabled),
-               .doc = "Disable RRDP file(s) processing",
+               .doc = "RSYNC download strategy. Will be deprecated, use 'rsync.strategy' instead.",
        }, {
                .id = 2001,
                .name = "shuffle-uris",
@@ -233,6 +246,12 @@ static const struct option_field options[] = {
                .type = &gt_mode,
                .offset = offsetof(struct rpki_config, mode),
                .doc = "Run mode: 'server' (run as RTR server), 'standalone' (run validation once and exit)",
+       }, {
+               .id = 1005,
+               .name = "work-offline",
+               .type = &gt_work_offline,
+               .offset = offsetof(struct rpki_config, work_offline),
+               .doc = "Disable all outgoing requests (rsync, http (implies RRDP)) and work only with local repository files.",
        },
 
        /* Server fields */
@@ -328,6 +347,26 @@ static const struct option_field options[] = {
        /* RSYNC fields */
        {
                .id = 3000,
+               .name = "rsync.enabled",
+               .type = &gt_bool,
+               .offset = offsetof(struct rpki_config, rsync.enabled),
+               .doc = "Enables RSYNC execution",
+       }, {
+               .id = 3001,
+               .name = "rsync.priority",
+               .type = &gt_uint32,
+               .offset = offsetof(struct rpki_config, rsync.priority),
+               .doc = "Priority of execution to fetch repositories files, a higher value means higher priority",
+               .min = 0,
+               .max = 100,
+       },{
+               .id = 3002,
+               .name = "rsync.strategy",
+               .type = &gt_rsync_strategy,
+               .offset = offsetof(struct rpki_config, rsync.strategy),
+               .doc = "RSYNC download strategy",
+       },{
+               .id = 3003,
                .name = "rsync.program",
                .type = &gt_string,
                .offset = offsetof(struct rpki_config, rsync.program),
@@ -335,14 +374,14 @@ static const struct option_field options[] = {
                .arg_doc = "<path to program>",
                .availability = AVAILABILITY_JSON,
        }, {
-               .id = 3001,
+               .id = 3004,
                .name = "rsync.arguments-recursive",
                .type = &gt_string_array,
                .offset = offsetof(struct rpki_config, rsync.args.recursive),
                .doc = "RSYNC program arguments that will trigger a recursive RSYNC",
                .availability = AVAILABILITY_JSON,
        }, {
-               .id = 3002,
+               .id = 3005,
                .name = "rsync.arguments-flat",
                .type = &gt_string_array,
                .offset = offsetof(struct rpki_config, rsync.args.flat),
@@ -350,6 +389,23 @@ static const struct option_field options[] = {
                .availability = AVAILABILITY_JSON,
        },
 
+       /* RRDP fields */
+       {
+               .id = 10000,
+               .name = "rrdp.enabled",
+               .type = &gt_bool,
+               .offset = offsetof(struct rpki_config, rrdp.enabled),
+               .doc = "Enables RRDP execution",
+       }, {
+               .id = 10001,
+               .name = "rrdp.priority",
+               .type = &gt_uint32,
+               .offset = offsetof(struct rpki_config, rrdp.priority),
+               .doc = "Priority of execution to fetch repositories files, a higher value means higher priority",
+               .min = 0,
+               .max = 100,
+       },
+
        /* HTTP requests parameters */
        {
                .id = 9000,
@@ -384,13 +440,6 @@ static const struct option_field options[] = {
                .doc = "Directory where CA certificates are found, used to verify the peer",
                .arg_doc = "<directory>",
        },
-       {
-               .id = 9004,
-               .name = "http.disabled",
-               .type = &gt_bool,
-               .offset = offsetof(struct rpki_config, http.disabled),
-               .doc = "Enable or disable HTTP requests",
-       },
 
        /* Logging fields */
        {
@@ -629,12 +678,15 @@ set_default_values(void)
                goto revert_port;
        }
 
-       rpki_config.rrdp_disabled = false;
-       rpki_config.sync_strategy = SYNC_ROOT;
+       rpki_config.sync_strategy = RSYNC_ROOT;
        rpki_config.shuffle_tal_uris = false;
        rpki_config.maximum_certificate_depth = 32;
        rpki_config.mode = SERVER;
+       rpki_config.work_offline = false;
 
+       rpki_config.rsync.enabled = true;
+       rpki_config.rsync.priority = 50;
+       rpki_config.rsync.strategy = RSYNC_ROOT;
        rpki_config.rsync.program = strdup("rsync");
        if (rpki_config.rsync.program == NULL) {
                error = pr_enomem();
@@ -651,15 +703,17 @@ set_default_values(void)
        if (error)
                goto revert_recursive_array;
 
+       rpki_config.rrdp.enabled = true;
+       rpki_config.rrdp.priority = 50;
+
        rpki_config.http.user_agent = strdup(PACKAGE_NAME "/" PACKAGE_VERSION);
        if (rpki_config.http.user_agent == NULL) {
                error = pr_enomem();
-               goto revert_recursive_array;
+               goto revert_flat_array;
        }
        rpki_config.http.connect_timeout = 30;
        rpki_config.http.transfer_timeout = 30;
        rpki_config.http.ca_path = NULL; /* Use system default */
-       rpki_config.http.disabled = false;
 
        rpki_config.log.color = false;
        rpki_config.log.filename_format = FNF_GLOBAL;
@@ -672,7 +726,8 @@ set_default_values(void)
        rpki_config.asn1_decode_max_stack = 4096; /* 4kB */
 
        return 0;
-
+revert_flat_array:
+       string_array_cleanup(&rpki_config.rsync.args.flat);
 revert_recursive_array:
        string_array_cleanup(&rpki_config.rsync.args.recursive);
 revert_rsync_program:
@@ -705,7 +760,7 @@ validate_config(void)
 
        if (rpki_config.output.bgpsec != NULL &&
            !valid_output_file(rpki_config.output.bgpsec))
-                       return pr_err("Invalid output.bgpsec file.");
+               return pr_err("Invalid output.bgpsec file.");
 
        return (rpki_config.tal != NULL)
            ? 0
@@ -849,6 +904,12 @@ config_get_server_queue(void)
        return rpki_config.server.backlog;
 }
 
+bool
+config_get_work_offline(void)
+{
+       return rpki_config.work_offline;
+}
+
 unsigned int
 config_get_validation_interval(void)
 {
@@ -891,18 +952,6 @@ config_get_local_repository(void)
        return rpki_config.local_repository;
 }
 
-enum sync_strategy
-config_get_sync_strategy(void)
-{
-       return rpki_config.sync_strategy;
-}
-
-bool
-config_get_rrdp_disabled(void)
-{
-       return rpki_config.rrdp_disabled;
-}
-
 bool
 config_get_shuffle_tal_uris(void)
 {
@@ -939,6 +988,24 @@ config_get_log_output(void)
        return rpki_config.log.output;
 }
 
+bool
+config_get_rsync_enabled(void)
+{
+       return rpki_config.rsync.enabled;
+}
+
+unsigned int
+config_get_rsync_priority(void)
+{
+       return rpki_config.rsync.priority;
+}
+
+enum rsync_strategy
+config_get_rsync_strategy(void)
+{
+       return rpki_config.rsync.strategy;
+}
+
 char *
 config_get_rsync_program(void)
 {
@@ -948,20 +1015,32 @@ config_get_rsync_program(void)
 struct string_array const *
 config_get_rsync_args(bool is_ta)
 {
-       switch (rpki_config.sync_strategy) {
-       case SYNC_ROOT:
+       switch (rpki_config.rsync.strategy) {
+       case RSYNC_ROOT:
                return &rpki_config.rsync.args.recursive;
-       case SYNC_ROOT_EXCEPT_TA:
+       case RSYNC_ROOT_EXCEPT_TA:
                return is_ta
                    ? &rpki_config.rsync.args.flat
                    : &rpki_config.rsync.args.recursive;
-       case SYNC_STRICT:
+       case RSYNC_STRICT:
                return &rpki_config.rsync.args.flat;
-       case SYNC_OFF:
+       default:
                break;
        }
 
-       pr_crit("Invalid sync strategy: '%u'", rpki_config.sync_strategy);
+       pr_crit("Invalid rsync strategy: '%u'", rpki_config.rsync.strategy);
+}
+
+bool
+config_get_rrdp_enabled(void)
+{
+       return rpki_config.rrdp.enabled;
+}
+
+unsigned int
+config_get_rrdp_priority(void)
+{
+       return rpki_config.rrdp.priority;
 }
 
 char const *
@@ -988,12 +1067,6 @@ config_get_http_ca_path(void)
        return rpki_config.http.ca_path;
 }
 
-bool
-config_get_http_disabled(void)
-{
-       return rpki_config.http.disabled;
-}
-
 char const *
 config_get_output_roa(void)
 {
@@ -1012,6 +1085,18 @@ config_get_asn1_decode_max_stack(void)
        return rpki_config.asn1_decode_max_stack;
 }
 
+void
+config_set_rsync_enabled(bool value)
+{
+       rpki_config.rsync.enabled = value;
+}
+
+void
+config_set_rrdp_enabled(bool value)
+{
+       rpki_config.rrdp.enabled = value;
+}
+
 void
 free_rpki_config(void)
 {
index 7d960f333b7acab49d02251b5eab5a3b09fa4f32..07926cd0380039c15190248d56fe2958657f06e7 100644 (file)
@@ -7,7 +7,7 @@
 #include "config/filename_format.h"
 #include "config/log_conf.h"
 #include "config/mode.h"
-#include "config/sync_strategy.h"
+#include "config/rsync_strategy.h"
 #include "config/string_array.h"
 #include "config/types.h"
 
@@ -27,26 +27,36 @@ char const *config_get_slurm(void);
 
 char const *config_get_tal(void);
 char const *config_get_local_repository(void);
-enum sync_strategy config_get_sync_strategy(void);
-bool config_get_rrdp_disabled(void);
 bool config_get_shuffle_tal_uris(void);
 unsigned int config_get_max_cert_depth(void);
 enum mode config_get_mode(void);
+bool config_get_work_offline(void);
 bool config_get_color_output(void);
 enum filename_format config_get_filename_format(void);
 char const *config_get_http_user_agent(void);
 unsigned int config_get_http_connect_timeout(void);
 unsigned int config_get_http_transfer_timeout(void);
 char const *config_get_http_ca_path(void);
-bool config_get_http_disabled(void);
 uint8_t config_get_log_level(void);
 enum log_output config_get_log_output(void);
+bool config_get_rsync_enabled(void);
+unsigned int config_get_rsync_priority(void);
+enum rsync_strategy config_get_rsync_strategy(void);
 char *config_get_rsync_program(void);
 struct string_array const *config_get_rsync_args(bool);
+bool config_get_rrdp_enabled(void);
+unsigned int config_get_rrdp_priority(void);
 char const *config_get_output_roa(void);
 char const *config_get_output_bgpsec(void);
 unsigned int config_get_asn1_decode_max_stack(void);
 
+/*
+ * Public, so that work-offline can set them, or (to be deprecated)
+ * sync-strategy when set to 'off'.
+ */
+void config_set_rsync_enabled(bool);
+void config_set_rrdp_enabled(bool);
+
 /* Needed public by the JSON module */
 void *get_rpki_config_field(struct option_field const *);
 struct option_field const *get_option_metadatas(void);
index 2c909d237460f5ad3120104f0987b5fc29465038..430459f5e7fc9863c8c494080dcfe22ab4587210 100644 (file)
@@ -7,16 +7,16 @@
 
 #define DEREFERENCE(void_value) (*((bool *) void_value))
 
-static void
+void
 print_bool(struct option_field const *field, void *value)
 {
        pr_info("%s: %s", field->name, DEREFERENCE(value) ? "true" : "false");
 }
 
-static int
+int
 parse_argv_bool(struct option_field const *field, char const *str, void *result)
 {
-       if (str == NULL) {
+       if (str == NULL || strlen(str) == 0) {
                DEREFERENCE(result) = true;
                return 0;
        }
@@ -34,7 +34,7 @@ parse_argv_bool(struct option_field const *field, char const *str, void *result)
        return pr_err("Cannot parse '%s' as a bool (true|false).", str);
 }
 
-static int
+int
 parse_json_bool(struct option_field const *opt, struct json_t *json,
     void *result)
 {
@@ -48,7 +48,7 @@ parse_json_bool(struct option_field const *opt, struct json_t *json,
 }
 
 const struct global_type gt_bool = {
-       .has_arg = no_argument,
+       .has_arg = optional_argument,
        .size = sizeof(bool),
        .print = print_bool,
        .parse.argv = parse_argv_bool,
index 8668be66d9e52a2306caa217433875647df5f406..25ccc785a65715bf0304129e3720c3e7b97f96ec 100644 (file)
@@ -5,4 +5,8 @@
 
 extern const struct global_type gt_bool;
 
+void print_bool(struct option_field const *, void *);
+int parse_argv_bool(struct option_field const *, char const *, void *);
+int parse_json_bool(struct option_field const *, struct json_t *, void *);
+
 #endif /* SRC_CONFIG_BOOLEAN_H_ */
diff --git a/src/config/rsync_strategy.c b/src/config/rsync_strategy.c
new file mode 100644 (file)
index 0000000..5ca6a9b
--- /dev/null
@@ -0,0 +1,85 @@
+#include "config/rsync_strategy.h"
+
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "log.h"
+#include "config/str.h"
+
+#define RSYNC_VALUE_STRICT             "strict"
+#define RSYNC_VALUE_ROOT               "root"
+#define RSYNC_VALUE_ROOT_EXCEPT_TA     "root-except-ta"
+
+#define DEREFERENCE(void_value) (*((enum rsync_strategy *) void_value))
+
+#ifdef ENABLE_STRICT_STRATEGY
+#define PRINT_STRICT_ARG_DOC "|" RSYNC_VALUE_STRICT
+#define HANDLE_RSYNC_STRICT DEREFERENCE(result) = RSYNC_STRICT;
+#else
+#define PRINT_STRICT_ARG_DOC
+#define HANDLE_RSYNC_STRICT                                            \
+       return pr_err("Unknown rsync synchronization strategy: '%s'. In order to use it, recompile using flag ENABLE_STRICT_STRATEGY.",\
+           str);
+#endif
+
+void
+print_rsync_strategy(struct option_field const *field, void *value)
+{
+       char const *str = "<unknown>";
+
+       switch (DEREFERENCE(value)) {
+       case RSYNC_STRICT:
+               str = RSYNC_VALUE_STRICT;
+               break;
+       case RSYNC_ROOT:
+               str = RSYNC_VALUE_ROOT;
+               break;
+       case RSYNC_ROOT_EXCEPT_TA:
+               str = RSYNC_VALUE_ROOT_EXCEPT_TA;
+               break;
+       default:
+               break;
+       }
+
+       pr_info("%s: %s", field->name, str);
+}
+
+int
+parse_argv_rsync_strategy(struct option_field const *field, char const *str,
+    void *result)
+{
+       if (strcmp(str, RSYNC_VALUE_STRICT) == 0)
+               HANDLE_RSYNC_STRICT
+       else if (strcmp(str, RSYNC_VALUE_ROOT) == 0)
+               DEREFERENCE(result) = RSYNC_ROOT;
+       else if (strcmp(str, RSYNC_VALUE_ROOT_EXCEPT_TA) == 0)
+               DEREFERENCE(result) = RSYNC_ROOT_EXCEPT_TA;
+       else
+               return pr_err("Unknown rsync synchronization strategy: '%s'",
+                   str);
+
+       return 0;
+}
+
+int
+parse_json_rsync_strategy(struct option_field const *opt, struct json_t *json,
+    void *result)
+{
+       char const *string;
+       int error;
+
+       error = parse_json_string(json, opt->name, &string);
+       return error ? error : parse_argv_rsync_strategy(opt, string, result);
+}
+
+const struct global_type gt_rsync_strategy = {
+       .has_arg = required_argument,
+       .size = sizeof(enum rsync_strategy),
+       .print = print_rsync_strategy,
+       .parse.argv = parse_argv_rsync_strategy,
+       .parse.json = parse_json_rsync_strategy,
+       .arg_doc = RSYNC_VALUE_ROOT
+           "|" RSYNC_VALUE_ROOT_EXCEPT_TA
+           PRINT_STRICT_ARG_DOC,
+};
diff --git a/src/config/rsync_strategy.h b/src/config/rsync_strategy.h
new file mode 100644 (file)
index 0000000..11683bd
--- /dev/null
@@ -0,0 +1,75 @@
+#ifndef SRC_CONFIG_RSYNC_STRATEGY_H_
+#define SRC_CONFIG_RSYNC_STRATEGY_H_
+
+#include "config/types.h"
+
+enum rsync_strategy {
+       /*
+        * FIXME (later) Deprecated. Still alive so that 'sync-strategy' and
+        * 'rsync.strategy' can live together.
+        *
+        * 'sync-strategy' type must handle this value to set 'rsync.enabled'
+        * as 'false'.
+        */
+       RSYNC_OFF,
+       /**
+        * Strictly correct download strategy.
+        *
+        * The validator will sync each repository publication point separately
+        * as requested by each caRepository contained in the CA certificates'
+        * SIA extensions.
+        *
+        * No risk of downloading unneeded files, but otherwise slow, as every
+        * different repository publication point requires a separate sync call.
+        *
+        * In order to enable this strategy, compile using the flag:
+        * ENABLE_STRICT_STRATEGY
+        */
+       RSYNC_STRICT,
+       /**
+        * Always download the likely root of the entire repository.
+        *
+        * For example, if we get the following caRepositories:
+        *
+        * - `rsync://a.b.c/d/e/f/g/h/i`
+        * - `rsync://a.b.c/d/e/f/g/h/j`
+        * - `rsync://a.b.c/d/e/f/k`
+        *
+        * This strategy will synchronize `rsync://a.b.c/d` while parsing the
+        * first caRepository, and then skip synchronization during the second
+        * and third ones. (Because they are already downloaded.)
+        *
+        * This strategy risks downloading unneeded files, and even failing due
+        * to lack of read permissions on stray subdirectories. On the flip
+        * side, if the repository holds no unnecessary subdirectories, then
+        * this strategy is the fastest one, since it generally only requires
+        * one sync call per domain, which often translates into one sync call
+        * per validation cycle.
+        *
+        * Currently, all of the official repositories are actually specifically
+        * structured to benefit this strategy.
+        */
+       RSYNC_ROOT,
+       /**
+        * Same as SYNC_ROOT, except the root certificate is synchronized
+        * separately.
+        * (Either because it's in a separate directory, or because we don't
+        * want to download its entire repository until we've verified its
+        * legitimacy and integrity.)
+        */
+       RSYNC_ROOT_EXCEPT_TA,
+};
+
+extern const struct global_type gt_rsync_strategy;
+
+/*
+ * FIXME (later) Public to live along with 'sync-strategy', return them to
+ * private whenever 'sync-strategy' is deleted.
+ */
+void print_rsync_strategy(struct option_field const *, void *);
+int parse_argv_rsync_strategy(struct option_field const *, char const *,
+    void *);
+int parse_json_rsync_strategy(struct option_field const *, struct json_t *,
+    void *);
+
+#endif /* SRC_CONFIG_RSYNC_STRATEGY_H_ */
index 697d7fde8e1a7f344f73dea976366c700a99a928..4ea69c3ef274214100bc9118d27163790f0db22f 100644 (file)
@@ -4,22 +4,29 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "config.h"
 #include "log.h"
 #include "config/str.h"
+#include "config/rsync_strategy.h"
 
-#define SYNC_VALUE_OFF                 "off"
-#define SYNC_VALUE_STRICT              "strict"
-#define SYNC_VALUE_ROOT                        "root"
-#define SYNC_VALUE_ROOT_EXCEPT_TA      "root-except-ta"
+/*
+ * Yeap, all of this is duplicated, better remove it with the whole source file
+ * whenever sync-strategy isn't supported anymore.
+ */
 
-#define DEREFERENCE(void_value) (*((enum sync_strategy *) void_value))
+#define RSYNC_VALUE_OFF                        "off"
+#define RSYNC_VALUE_STRICT             "strict"
+#define RSYNC_VALUE_ROOT               "root"
+#define RSYNC_VALUE_ROOT_EXCEPT_TA     "root-except-ta"
+
+#define DEREFERENCE(void_value) (*((enum rsync_strategy *) void_value))
 
 #ifdef ENABLE_STRICT_STRATEGY
-#define PRINT_STRICT_ARG_DOC "|" SYNC_VALUE_STRICT
-#define HANDLE_SYNC_STRICT DEREFERENCE(result) = SYNC_STRICT;
+#define PRINT_STRICT_ARG_DOC "|" RSYNC_VALUE_STRICT
+#define HANDLE_RSYNC_STRICT DEREFERENCE(result) = RSYNC_STRICT;
 #else
 #define PRINT_STRICT_ARG_DOC
-#define HANDLE_SYNC_STRICT                                             \
+#define HANDLE_RSYNC_STRICT                                            \
        return pr_err("Unknown synchronization strategy: '%s'. In order to use it, recompile using flag ENABLE_STRICT_STRATEGY.",\
            str);
 #endif
 static void
 print_sync_strategy(struct option_field const *field, void *value)
 {
-       char const *str = "<unknown>";
-
-       switch (DEREFERENCE(value)) {
-       case SYNC_OFF:
-               str = SYNC_VALUE_OFF;
-               break;
-       case SYNC_STRICT:
-               str = SYNC_VALUE_STRICT;
-               break;
-       case SYNC_ROOT:
-               str = SYNC_VALUE_ROOT;
-               break;
-       case SYNC_ROOT_EXCEPT_TA:
-               str = SYNC_VALUE_ROOT_EXCEPT_TA;
-               break;
+       if (DEREFERENCE(value) == RSYNC_OFF) {
+               pr_info("%s: %s", field->name, RSYNC_VALUE_OFF);
+               return;
        }
 
-       pr_info("%s: %s", field->name, str);
+       print_rsync_strategy(field, value);
 }
 
 static int
 parse_argv_sync_strategy(struct option_field const *field, char const *str,
     void *result)
 {
-       if (strcmp(str, SYNC_VALUE_OFF) == 0)
-               DEREFERENCE(result) = SYNC_OFF;
-       else if (strcmp(str, SYNC_VALUE_STRICT) == 0)
-               HANDLE_SYNC_STRICT
-       else if (strcmp(str, SYNC_VALUE_ROOT) == 0)
-               DEREFERENCE(result) = SYNC_ROOT;
-       else if (strcmp(str, SYNC_VALUE_ROOT_EXCEPT_TA) == 0)
-               DEREFERENCE(result) = SYNC_ROOT_EXCEPT_TA;
-       else
-               return pr_err("Unknown synchronization strategy: '%s'", str);
+       pr_warn("'sync-strategy' will be deprecated.");
+       pr_warn("Use 'rsync.strategy' instead; or 'rsync.enabled=false' if you wish to use 'off' strategy.");
+
+       if (strcmp(str, RSYNC_VALUE_OFF) == 0) {
+               DEREFERENCE(result) = RSYNC_OFF;
+               config_set_rsync_enabled(false);
+               return 0;
+       }
 
-       return 0;
+       return parse_argv_rsync_strategy(field, str, result);
 }
 
 static int
@@ -78,12 +71,12 @@ parse_json_sync_strategy(struct option_field const *opt, struct json_t *json,
 
 const struct global_type gt_sync_strategy = {
        .has_arg = required_argument,
-       .size = sizeof(enum sync_strategy),
+       .size = sizeof(enum rsync_strategy),
        .print = print_sync_strategy,
        .parse.argv = parse_argv_sync_strategy,
        .parse.json = parse_json_sync_strategy,
-       .arg_doc = SYNC_VALUE_OFF
-           PRINT_STRICT_ARG_DOC
-           "|" SYNC_VALUE_ROOT
-           "|" SYNC_VALUE_ROOT_EXCEPT_TA,
+       .arg_doc = RSYNC_VALUE_OFF
+           "|" RSYNC_VALUE_ROOT
+           "|" RSYNC_VALUE_ROOT_EXCEPT_TA
+           PRINT_STRICT_ARG_DOC,
 };
index 2ee8b35f295a3036f9e1090e26342a965d6666f4..0f8c776718a7f0bfaf32e9bec3be9320f857b3a9 100644 (file)
@@ -3,64 +3,6 @@
 
 #include "config/types.h"
 
-/**
- * Note: The only repository synchronization protocol implemented so far is
- * RSYNC. Whenever you see "sync", think "rsync."
- */
-enum sync_strategy {
-       /**
-        * Synchronization is turned off.
-        * The validator will work on an already downloaded repository.
-        */
-       SYNC_OFF,
-       /**
-        * Strictly correct download strategy.
-        *
-        * The validator will sync each repository publication point separately
-        * as requested by each caRepository contained in the CA certificates'
-        * SIA extensions.
-        *
-        * No risk of downloading unneeded files, but otherwise slow, as every
-        * different repository publication point requires a separate sync call.
-        *
-        * In order to enable this strategy, compile using the flag:
-        * ENABLE_STRICT_STRATEGY
-        */
-       SYNC_STRICT,
-       /**
-        * Always download the likely root of the entire repository.
-        *
-        * For example, if we get the following caRepositories:
-        *
-        * - `rsync://a.b.c/d/e/f/g/h/i`
-        * - `rsync://a.b.c/d/e/f/g/h/j`
-        * - `rsync://a.b.c/d/e/f/k`
-        *
-        * This strategy will synchronize `rsync://a.b.c/d` while parsing the
-        * first caRepository, and then skip synchronization during the second
-        * and third ones. (Because they are already downloaded.)
-        *
-        * This strategy risks downloading unneeded files, and even failing due
-        * to lack of read permissions on stray subdirectories. On the flip
-        * side, if the repository holds no unnecessary subdirectories, then
-        * this strategy is the fastest one, since it generally only requires
-        * one sync call per domain, which often translates into one sync call
-        * per validation cycle.
-        *
-        * Currently, all of the official repositories are actually specifically
-        * structured to benefit this strategy.
-        */
-       SYNC_ROOT,
-       /**
-        * Same as SYNC_ROOT, except the root certificate is synchronized
-        * separately.
-        * (Either because it's in a separate directory, or because we don't
-        * want to download its entire repository until we've verified its
-        * legitimacy and integrity.)
-        */
-       SYNC_ROOT_EXCEPT_TA,
-};
-
 extern const struct global_type gt_sync_strategy;
 
 #endif /* SRC_CONFIG_SYNC_STRATEGY_H_ */
diff --git a/src/config/work_offline.c b/src/config/work_offline.c
new file mode 100644 (file)
index 0000000..8488e23
--- /dev/null
@@ -0,0 +1,49 @@
+#include "config/work_offline.h"
+
+#include <getopt.h>
+#include <stdbool.h>
+
+#include "config.h"
+#include "config/boolean.h"
+
+#define DEREFERENCE(void_value) (*((bool *) void_value))
+
+static int
+parse_argv_offline(struct option_field const *field, char const *str, void *result)
+{
+       int error;
+
+       error = parse_argv_bool(field, str, result);
+       if (error)
+               return error;
+
+       config_set_rsync_enabled(!DEREFERENCE(result));
+       config_set_rrdp_enabled(!DEREFERENCE(result));
+
+       return 0;
+}
+
+static int
+parse_json_offline(struct option_field const *opt, struct json_t *json,
+    void *result)
+{
+       int error;
+
+       error = parse_json_bool(opt, json, result);
+       if (error)
+               return error;
+
+       config_set_rsync_enabled(!DEREFERENCE(result));
+       config_set_rrdp_enabled(!DEREFERENCE(result));
+
+       return 0;
+}
+
+const struct global_type gt_work_offline = {
+       .has_arg = optional_argument,
+       .size = sizeof(bool),
+       .print = print_bool,
+       .parse.argv = parse_argv_offline,
+       .parse.json = parse_json_offline,
+       .arg_doc = "true|false",
+};
diff --git a/src/config/work_offline.h b/src/config/work_offline.h
new file mode 100644 (file)
index 0000000..3815f0f
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef SRC_CONFIG_WORK_OFFLINE_H_
+#define SRC_CONFIG_WORK_OFFLINE_H_
+
+extern const struct global_type gt_work_offline;
+
+#endif /* SRC_CONFIG_WORK_OFFLINE_H_ */
index 02cff97f14069d7e2b66803b4c1a0855eceb6c3b..adafa976f65fcf3a5113c98ec966330c5c75e163 100644 (file)
@@ -135,7 +135,7 @@ __http_download_file(struct rpki_uri *uri, http_write_cb cb,
        FILE *out;
        int error;
 
-       if (config_get_http_disabled()) {
+       if (config_get_work_offline()) {
                response_code = 0; /* Not 200 code, but also not an error */
                return 0;
        }
index aedf53702a8471d34bef14e6340a6d0052115d22..bff0d2addd42ba6f3683537ed610346be44cb55c 100644 (file)
@@ -1904,21 +1904,26 @@ use_access_method(struct sia_ca_uris *sia_uris,
 
        /*
         * RSYNC will always be present (at least for now, see
-        * rfc6487#section-4.8.8.1)
+        * rfc6487#section-4.8.8.1). If rsync is disabled, the cb will take
+        * care of that.
         */
-       if (sia_uris->rpkiNotify.uri == NULL || config_get_rrdp_disabled())
+       if (sia_uris->rpkiNotify.uri == NULL || !config_get_rrdp_enabled())
                return rsync_cb(sia_uris);
 
-       /* Get the preferred */
-       if (sia_uris->caRepository.position > sia_uris->rpkiNotify.position) {
-               cb_primary = rrdp_cb;
-               cb_secondary = rsync_cb;
-               primary_rrdp = true;
-       } else {
-               cb_primary = rsync_cb;
-               cb_secondary = rrdp_cb;
-               primary_rrdp = false;
-       }
+       /* RSYNC disabled, and RRDP is present, use it */
+       if (!config_get_rsync_enabled())
+               return rrdp_cb(sia_uris);
+
+       /* Use CA's or configured priority? */
+       if (config_get_rsync_priority() == config_get_rrdp_priority())
+               primary_rrdp = sia_uris->caRepository.position
+                   > sia_uris->rpkiNotify.position;
+       else
+               primary_rrdp = config_get_rsync_priority()
+                   < config_get_rrdp_priority();
+
+       cb_primary = primary_rrdp ? rrdp_cb : rsync_cb;
+       cb_secondary = primary_rrdp ? rsync_cb : rrdp_cb;
 
        /* Try with the preferred; in case of error, try with the next one */
        error = cb_primary(sia_uris);
index 5031bb26d58840aa5f6dc11436536a1c9e958312..ef29a42fd7c199d78d58c740d00c4aaba61821d2 100644 (file)
@@ -3,6 +3,7 @@
 #include "rrdp/db/db_rrdp_uris.h"
 #include "rrdp/rrdp_objects.h"
 #include "rrdp/rrdp_parser.h"
+#include "config.h"
 #include "log.h"
 #include "thread_var.h"
 #include "visited_uris.h"
@@ -73,6 +74,9 @@ rrdp_load(struct rpki_uri *uri)
        int error;
        bool requested;
 
+       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);
index 9ba58c7ea73a98da4eb7d03cff0c1c8c6c8d180d..c524dc9d16ae7f347620118e75cd9a3f4a2bbad0 100644 (file)
@@ -68,7 +68,7 @@ is_descendant(struct rpki_uri *ancestor, struct rpki_uri *descendant)
        string_tokenizer_init(&descendant_tokenizer, uri_get_global(descendant),
            uri_get_global_len(descendant), '/');
 
-       if (config_get_sync_strategy() == SYNC_STRICT)
+       if (config_get_rsync_strategy() == RSYNC_STRICT)
                return strcmp(uri_get_global(ancestor),
                    uri_get_global(descendant)) == 0;
 
@@ -154,20 +154,20 @@ static int
 get_rsync_uri(struct rpki_uri *requested_uri, bool is_ta,
     struct rpki_uri **rsync_uri)
 {
-       switch (config_get_sync_strategy()) {
-       case SYNC_ROOT:
+       switch (config_get_rsync_strategy()) {
+       case RSYNC_ROOT:
                return handle_root_strategy(requested_uri, rsync_uri);
-       case SYNC_ROOT_EXCEPT_TA:
+       case RSYNC_ROOT_EXCEPT_TA:
                return is_ta
                    ? handle_strict_strategy(requested_uri, rsync_uri)
                    : handle_root_strategy(requested_uri, rsync_uri);
-       case SYNC_STRICT:
+       case RSYNC_STRICT:
                return handle_strict_strategy(requested_uri, rsync_uri);
-       case SYNC_OFF:
+       default:
                break;
        }
 
-       pr_crit("Invalid sync strategy: %u", config_get_sync_strategy());
+       pr_crit("Invalid rsync strategy: %u", config_get_rsync_strategy());
 }
 
 static void
@@ -297,14 +297,14 @@ download_files(struct rpki_uri *requested_uri, bool is_ta, bool force)
         * Note:
         * @requested_uri is the URI we were asked to RSYNC.
         * @rsync_uri is the URL we're actually going to RSYNC.
-        * (They can differ, depending on config_get_sync_strategy().)
+        * (They can differ, depending on config_get_rsync_strategy().)
         */
        struct validation *state;
        struct uri_list *visited_uris;
        struct rpki_uri *rsync_uri;
        int error;
 
-       if (config_get_sync_strategy() == SYNC_OFF)
+       if (!config_get_rsync_enabled())
                return 0;
 
        state = state_retrieve();
index 6148c75693ce8d58830c344844ebb5d576610dab..5249df72c7a032b879ad9af33df810d7c26f3daa 100644 (file)
@@ -163,7 +163,7 @@ visited_uris_get_root(struct visited_uris *uris, char **result)
                return pr_enomem();
 
        strncpy(tmp, elem->uri, size);
-       tmp[size + 1] = '\0';
+       tmp[size] = '\0';
 
        *result = tmp;
        return 0;
index 448f234280685bbaeb21d823c335e70a00d909ae..aa40c5a5970f66d0f6acfb3dc3b4e8085eee8b3e 100644 (file)
@@ -64,18 +64,42 @@ config_get_local_repository(void)
        return "repository/";
 }
 
-enum sync_strategy
-config_get_sync_strategy(void)
+enum rsync_strategy
+config_get_rsync_strategy(void)
 {
-       return SYNC_ROOT;
+       return RSYNC_ROOT;
 }
 
 bool
-config_get_rrdp_disabled(void)
+config_get_rsync_enabled(void)
 {
        return true;
 }
 
+unsigned int
+config_get_rsync_priority(void)
+{
+       return 50;
+}
+
+bool
+config_get_rrdp_enabled(void)
+{
+       return false;
+}
+
+unsigned int
+config_get_rrdp_priority(void)
+{
+       return 50;
+}
+
+bool
+config_get_work_offline(void)
+{
+       return false;
+}
+
 bool
 config_get_color_output(void)
 {
@@ -158,7 +182,7 @@ void print_stack_trace(void)
 char const *
 config_get_http_user_agent(void)
 {
-       return "Test/0.1";
+       return "fort-test/0.1";
 }
 
 unsigned int
@@ -177,9 +201,3 @@ config_get_http_ca_path(void)
 {
        return NULL;
 }
-
-bool
-config_get_http_disabled(void)
-{
-       return true;
-}