From: pcarana Date: Mon, 13 Jan 2020 19:58:47 +0000 (-0600) Subject: Add extra rsync and rrdp configurations (enabled and priority). X-Git-Tag: v1.2.0~27 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=6f4a3ee165db0038e62349a7c9043311294a87b2;p=thirdparty%2FFORT-validator.git Add extra rsync and rrdp configurations (enabled and priority). +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. --- diff --git a/src/Makefile.am b/src/Makefile.am index 953a6ae5..6a10b990 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 diff --git a/src/config.c b/src/config.c index b2d52794..c7859001 100644 --- a/src/config.c +++ b/src/config.c @@ -16,8 +16,10 @@ #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 = >_sync_strategy, .offset = offsetof(struct rpki_config, sync_strategy), - .doc = "RSYNC download strategy", - }, { - .id = 2000, - .name = "rrdp-disabled", - .type = >_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 = >_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 = >_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 = >_bool, + .offset = offsetof(struct rpki_config, rsync.enabled), + .doc = "Enables RSYNC execution", + }, { + .id = 3001, + .name = "rsync.priority", + .type = >_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 = >_rsync_strategy, + .offset = offsetof(struct rpki_config, rsync.strategy), + .doc = "RSYNC download strategy", + },{ + .id = 3003, .name = "rsync.program", .type = >_string, .offset = offsetof(struct rpki_config, rsync.program), @@ -335,14 +374,14 @@ static const struct option_field options[] = { .arg_doc = "", .availability = AVAILABILITY_JSON, }, { - .id = 3001, + .id = 3004, .name = "rsync.arguments-recursive", .type = >_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 = >_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 = >_bool, + .offset = offsetof(struct rpki_config, rrdp.enabled), + .doc = "Enables RRDP execution", + }, { + .id = 10001, + .name = "rrdp.priority", + .type = >_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 = "", }, - { - .id = 9004, - .name = "http.disabled", - .type = >_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) { diff --git a/src/config.h b/src/config.h index 7d960f33..07926cd0 100644 --- a/src/config.h +++ b/src/config.h @@ -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); diff --git a/src/config/boolean.c b/src/config/boolean.c index 2c909d23..430459f5 100644 --- a/src/config/boolean.c +++ b/src/config/boolean.c @@ -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, diff --git a/src/config/boolean.h b/src/config/boolean.h index 8668be66..25ccc785 100644 --- a/src/config/boolean.h +++ b/src/config/boolean.h @@ -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 index 00000000..5ca6a9bf --- /dev/null +++ b/src/config/rsync_strategy.c @@ -0,0 +1,85 @@ +#include "config/rsync_strategy.h" + +#include +#include +#include + +#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 = ""; + + 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 index 00000000..11683bdd --- /dev/null +++ b/src/config/rsync_strategy.h @@ -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_ */ diff --git a/src/config/sync_strategy.c b/src/config/sync_strategy.c index 697d7fde..4ea69c3e 100644 --- a/src/config/sync_strategy.c +++ b/src/config/sync_strategy.c @@ -4,22 +4,29 @@ #include #include +#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 @@ -27,42 +34,28 @@ static void print_sync_strategy(struct option_field const *field, void *value) { - char const *str = ""; - - 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, }; diff --git a/src/config/sync_strategy.h b/src/config/sync_strategy.h index 2ee8b35f..0f8c7767 100644 --- a/src/config/sync_strategy.h +++ b/src/config/sync_strategy.h @@ -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 index 00000000..8488e233 --- /dev/null +++ b/src/config/work_offline.c @@ -0,0 +1,49 @@ +#include "config/work_offline.h" + +#include +#include + +#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 index 00000000..3815f0fd --- /dev/null +++ b/src/config/work_offline.h @@ -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_ */ diff --git a/src/http/http.c b/src/http/http.c index 02cff97f..adafa976 100644 --- a/src/http/http.c +++ b/src/http/http.c @@ -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; } diff --git a/src/object/certificate.c b/src/object/certificate.c index aedf5370..bff0d2ad 100644 --- a/src/object/certificate.c +++ b/src/object/certificate.c @@ -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); diff --git a/src/rrdp/rrdp_loader.c b/src/rrdp/rrdp_loader.c index 5031bb26..ef29a42f 100644 --- a/src/rrdp/rrdp_loader.c +++ b/src/rrdp/rrdp_loader.c @@ -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); diff --git a/src/rsync/rsync.c b/src/rsync/rsync.c index 9ba58c7e..c524dc9d 100644 --- a/src/rsync/rsync.c +++ b/src/rsync/rsync.c @@ -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(); diff --git a/src/visited_uris.c b/src/visited_uris.c index 6148c756..5249df72 100644 --- a/src/visited_uris.c +++ b/src/visited_uris.c @@ -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; diff --git a/test/impersonator.c b/test/impersonator.c index 448f2342..aa40c5a5 100644 --- a/test/impersonator.c +++ b/test/impersonator.c @@ -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; -}