This folder contains the following examples:
- `config.json`: configuration file mostly with the default values used by the validator. Can be set as value of [`--configuration-file`](https://nicmx.github.io/FORT-validator/usage.html#--configuration-file).
- `demo.slurm`: valid SLURM file mostly with the same values as in [RFC 8416 section 3.5](https://tools.ietf.org/html/rfc8416#section-3.5). Can be set as value of [`--slurm`](https://nicmx.github.io/FORT-validator/usage.html#--slurm).
-- `tal/`: directory that contains almost all RIRs TALs, [read more](tal/).
-# TALs
+Please ignore this folder. It only exists in the hopes that `fort_setup.sh` continues working until it's retired. The script is deprecated at the moment.
-Most of the Trust Anchor Locators of the RIRs are included here for convenience. (But maybe you should get your own, for security.)
+The TALs contained here are pretty much all old and obsolete. If you need to download the current TALs, run `fort --init-tals --tal <TAL directory>` instead.
-**Almost every TAL includes an HTTPS URI to fetch the trust anchor certificates, FORT validator utilizes such URIs by default.**
-
-The only TAL that's not included is ARIN's, because you need to agree to their [RPA](https://www.arin.net/resources/manage/rpki/tal/).
-
-In order to ease the ARIN TAL download, there's a script that does that for you: [fort_setup.sh](../../fort_setup.sh). Read more about it at web docs section [Compilation and Installation](https://nicmx.github.io/FORT-validator/installation.html).
# - Using the values of the configuration file (uses the args '--tal' and
# '--local-repository').
+echo "WARNING: this script (fort_setup.sh) is deprecated, and will be deleted soon."
+echo "I don't even know if it works properly."
+echo "If you want to download the TALs, use the fort binary's --init-tals option."
+echo "See https://nicmx.github.io/FORT-validator/usage.html#--init-tals"
+echo "===================================="
+
exit_on_err()
{
if ! [ $1 ] ; then
/* Time period that must lapse to warn about a stale repository */
unsigned int stale_repository_period;
- /* Download the TALs into --tal? */
+ /* Download the normal TALs into --tal? */
bool init_tals;
-
- /* HTTPS URLS from where the TALS will be fetched */
- struct init_locations init_tal_locations;
+ /* Download AS0 TALs into --tal? */
+ bool init_tal0s;
+ /* Deprecated; currently does nothing. */
+ unsigned int init_tal_locations;
/* Thread pools for specific tasks */
struct {
.name = "init-tals",
.type = >_bool,
.offset = offsetof(struct rpki_config, init_tals),
- .doc = "Fetch the RIR's TAL files into the specified path at --tal",
+ .doc = "Fetch the currently-known TAL files into --tal",
.availability = AVAILABILITY_GETOPT,
- },
- {
+ }, {
+ .id = 11002,
+ .name = "init-as0-tals",
+ .type = >_bool,
+ .offset = offsetof(struct rpki_config, init_tal0s),
+ .doc = "Fetch the currently-known AS0 TAL files into --tal",
+ .availability = AVAILABILITY_GETOPT,
+ }, {
.id = 11001,
.name = "init-locations",
.type = >_init_tals_locations,
.offset = offsetof(struct rpki_config, init_tal_locations),
- .doc = "Locations from where the TAL files will be downloaded, and its optional accept message",
+ .doc = "Deprecated. Does nothing as of Fort 1.5.1.",
.availability = AVAILABILITY_JSON,
},
"$LOCAL",
};
- static char const *init_locations_no_msg[] = {
- "https://raw.githubusercontent.com/NICMx/FORT-validator/master/examples/tal/lacnic.tal",
- "https://raw.githubusercontent.com/NICMx/FORT-validator/master/examples/tal/ripe.tal",
- "https://raw.githubusercontent.com/NICMx/FORT-validator/master/examples/tal/afrinic.tal",
- "https://raw.githubusercontent.com/NICMx/FORT-validator/master/examples/tal/apnic.tal",
- };
-
- static char const *init_locations_w_msg[] = {
- "https://www.arin.net/resources/manage/rpki/arin.tal",
- "Please download and read ARIN Relying Party Agreement (RPA) from https://www.arin.net/resources/manage/rpki/rpa.pdf. Once you've read it and if you agree ARIN RPA, type 'yes' to proceed with ARIN's TAL download:",
- };
-
int error;
/*
rpki_config.stale_repository_period = 43200; /* 12 hours */
rpki_config.init_tals = false;
- error = init_locations_init(&rpki_config.init_tal_locations,
- init_locations_no_msg, ARRAY_LEN(init_locations_no_msg),
- init_locations_w_msg, ARRAY_LEN(init_locations_w_msg));
- if (error)
- goto revert_init_locations;
+ rpki_config.init_tal_locations = 0;
/* Common scenario is to connect 1 router or a couple of them */
rpki_config.thread_pool.server.max = 20;
rpki_config.thread_pool.validation.max = 5;
return 0;
-revert_init_locations:
- free(rpki_config.validation_log.tag);
+
revert_validation_log_tag:
free(rpki_config.http.user_agent);
revert_flat_array:
goto end;
/* If present, nothing else is done */
- if (rpki_config.init_tals) {
- error = init_tals_exec(&rpki_config.init_tal_locations,
- rpki_config.tal);
+ if (rpki_config.init_tals || rpki_config.init_tal0s) {
+ if (rpki_config.init_tals)
+ error = download_tals();
+ if (!error && rpki_config.init_tal0s)
+ error = download_tal0s();
free(long_opts);
free(short_opts);
exit(error);
#include "config/init_tals.h"
-#include <getopt.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/queue.h>
-#include "log.h"
-
-#define JSON_MEMBER_URL "url"
-#define JSON_MEMBER_MESSAGE "accept-message"
-
-static int
-init_location_create(char const *url, struct init_location **result)
-{
- struct init_location *tmp;
-
- tmp = malloc(sizeof(struct init_location));
- if (tmp == NULL)
- return pr_enomem();
-
- tmp->url = strdup(url);
- if (tmp->url == NULL) {
- free(tmp);
- return pr_enomem();
- }
-
- tmp->accept_message = NULL;
-
- *result = tmp;
- return 0;
-}
-
-static void
-init_location_destroy(struct init_location *location)
-{
- if (location->accept_message != NULL)
- free(location->accept_message);
- free(location->url);
- free(location);
-}
-
-void
-init_locations_cleanup(struct init_locations *locations)
-{
- struct init_location *tmp;
-
- while (!SLIST_EMPTY(locations)) {
- tmp = locations->slh_first;
- SLIST_REMOVE_HEAD(locations, next);
- init_location_destroy(tmp);
- }
-}
-
-void
-__init_locations_cleanup(void *arg)
-{
- init_locations_cleanup(arg);
-}
-
-static int
-init_locations_add_n_msg(struct init_locations *locations, char const *url)
-{
- struct init_location *tmp;
- int error;
-
- tmp = NULL;
- error = init_location_create(url, &tmp);
- if (error)
- return error;
-
- SLIST_INSERT_HEAD(locations, tmp, next);
- return 0;
-}
-
-static int
-init_locations_add_w_msg(struct init_locations *locations, char const *url,
- char const *message)
-{
- struct init_location *tmp;
- int error;
-
- tmp = NULL;
- error = init_location_create(url, &tmp);
- if (error)
- return error;
-
- tmp->accept_message = strdup(message);
- if (tmp->accept_message == NULL) {
- init_location_destroy(tmp);
- return pr_enomem();
- }
-
- SLIST_INSERT_HEAD(locations, tmp, next);
- return 0;
-}
-
-int
-init_locations_init(struct init_locations *locations,
- char const *const *non_message, size_t non_message_len,
- char const *const *with_message, size_t with_message_len)
-{
- size_t i;
- int error;
-
- SLIST_INIT(locations);
-
- for (i = 0; i < non_message_len; i++) {
- error = init_locations_add_n_msg(locations, non_message[i]);
- if (error)
- goto cleanup;
- }
-
- for (i = 0; i < with_message_len; i+=2) {
- error = init_locations_add_w_msg(locations, with_message[i],
- with_message[i + 1]);
- if (error)
- goto cleanup;
- }
-
- return 0;
-cleanup:
- init_locations_cleanup(locations);
- return error;
-}
-
-int
-init_locations_foreach(struct init_locations *locations,
- init_locations_foreach_cb cb, void *arg)
-{
- struct init_location *ptr;
- int error;
-
- SLIST_FOREACH(ptr, locations, next) {
- error = cb(ptr->url, ptr->accept_message, arg);
- if (error)
- return error;
- }
-
- return 0;
-}
-
-static int
-parse_location(char const *name, size_t pos, json_t *json, char const **url,
- char const **message)
-{
- json_t *member;
-
- member = json_object_get(json, JSON_MEMBER_URL);
- if (member == NULL)
- return pr_op_err("'%s' array element #%zu requires the member '%s'.",
- name, pos, JSON_MEMBER_URL);
-
- if (!json_is_string(member))
- return pr_op_err("'%s' array element #%zu '%s' member must be a string",
- name, pos, JSON_MEMBER_URL);
-
- *url = json_string_value(member);
-
- /* Optional */
- member = json_object_get(json, JSON_MEMBER_MESSAGE);
- if (member == NULL) {
- *message = NULL;
- return 0;
- }
-
- if (!json_is_string(member))
- return pr_op_err("'%s' array element #%zu '%s' member must be a string",
- name, pos, JSON_MEMBER_MESSAGE);
-
- *message = json_string_value(member);
-
- return 0;
-}
-
static int
init_tals_parse_json(struct option_field const *opt, json_t *json, void *result)
{
- struct init_locations *ptr;
- json_t *elem;
- size_t len;
- size_t i;
- char const *url;
- char const *message;
- int error;
-
- if (!json_is_array(json)) {
- return pr_op_err("The '%s' element is not a JSON array",
- opt->name);
- }
-
- len = json_array_size(json);
-
- if (len == 0) {
- /* Cleanup default value */
- init_locations_cleanup(result);
- return 0;
- }
-
- ptr = result;
-
- /* Remove the previous value (usually the default). */
- init_locations_cleanup(ptr);
-
- for (i = 0; i < len; i++) {
- elem = json_array_get(json, i);
- if (!json_is_object(elem))
- return pr_op_err("'%s' array element #%zu is not an object",
- opt->name, i);
-
- url = NULL;
- message = NULL;
- error = parse_location(opt->name, i, elem, &url, &message);
- if (error)
- goto cleanup;
-
- if (message == NULL)
- error = init_locations_add_n_msg(ptr, url);
- else
- error = init_locations_add_w_msg(ptr, url, message);
-
- if (error)
- goto cleanup;
- }
+ /* This is deprecated. Please delete it in the future. */
return 0;
-cleanup:
- init_locations_cleanup(ptr);
- return error;
}
const struct global_type gt_init_tals_locations = {
.print = NULL,
.parse.json = init_tals_parse_json,
- .free = __init_locations_cleanup,
};
#ifndef SRC_CONFIG_INIT_TALS_H_
#define SRC_CONFIG_INIT_TALS_H_
-#include <stddef.h>
-#include <sys/queue.h>
#include "config/types.h"
-/* Struct where each URL and its optional message are stored */
-struct init_location {
- char *url;
- char *accept_message;
- SLIST_ENTRY(init_location) next;
-};
-
-SLIST_HEAD(init_locations, init_location);
-
extern const struct global_type gt_init_tals_locations;
-typedef int (*init_locations_foreach_cb)(char const *, char const *, void *);
-int init_locations_foreach(struct init_locations *, init_locations_foreach_cb,
- void *);
-
-int init_locations_init(struct init_locations *, char const *const *, size_t,
- char const *const *, size_t);
-void init_locations_cleanup(struct init_locations *);
-
#endif /* SRC_CONFIG_INIT_TALS_H_ */
#include "log.h"
#include "http/http.h"
-/*
- * Quite simple: expect 'yes' from stdin (ignore case)
- */
-static int
-read_stdin(char const *file)
+static bool
+download_arin_tal(void)
{
char c;
+ printf("Attention: ARIN requires you to agree to their Relying Party Agreement (RPA) before you can download and use their TAL.\n"
+ "Please download and read https://www.arin.net/resources/manage/rpki/rpa.pdf\n"
+ "If you agree to the terms, type 'yes' and hit Enter: ");
+
c = getchar();
if (c != 'y' && c != 'Y')
- goto err;
+ goto cancel;
c = getchar();
if (c != 'e' && c != 'E')
- goto err;
+ goto cancel;
c = getchar();
if (c != 's' && c != 'S')
- goto err;
+ goto cancel;
if (feof(stdin) || (c = getchar()) == '\n')
- return 0;
-err:
- fprintf(stdout,
- "\nWarning: The conditions weren't accepted, the TAL '%s' won't be downloaded.\n",
- file);
- return EINVAL;
+ return true;
+
+ /* Fall through */
+cancel:
+ printf("Skipping ARIN's TAL.\n\n");
+ return false;
}
static int
-fetch_url(char const *url, char const *accept_message, void *arg)
+fetch_url(char const *url)
{
char const *prefix = "https://";
- char const *dest_dir = arg;
+ char const *dest_dir;
char *dest_file;
char *dest;
size_t prefix_len;
prefix_len = strlen(prefix);
url_len = strlen(url);
+ dest_dir = config_get_tal();
dest_dir_len = strlen(dest_dir);
if (url_len <= prefix_len ||
if (*dest_file == '\0')
return pr_op_err("HTTPS URL '%s' must be a file location", url);
- /* Each location must be an HTTPS URI */
- do {
- if (accept_message == NULL)
- break;
-
- fprintf(stdout, "%s\n", accept_message);
- error = read_stdin(dest_file);
- /* On error, let the other TALs to be downloaded */
- if (error)
- return 0;
- } while (0);
-
extra_slash = (dest_dir[dest_dir_len - 1] == '/') ? 0 : 1;
dest = malloc(dest_dir_len + extra_slash + strlen(dest_file) + 1);
return error;
}
- fprintf(stdout, "Successfully fetched '%s'!\n", dest);
+ fprintf(stdout, "Successfully fetched '%s'!\n\n", dest);
free(dest);
return 0;
}
int
-init_tals_exec(struct init_locations *source, char const *dest)
+download_tals(void)
{
- return init_locations_foreach(source, fetch_url, (void *)dest);
+ int error;
+
+ /*
+ * https://afrinic.net/resource-certification/tal
+ * https://www.apnic.net/community/security/resource-certification/tal-archive/
+ * https://www.arin.net/resources/manage/rpki/tal/
+ * https://www.lacnic.net/4984/2/lacnic/rpki-rpki-trust-anchor
+ * https://www.ripe.net/manage-ips-and-asns/resource-management/rpki/ripe-ncc-rpki-trust-anchor-structure
+ */
+
+ error = fetch_url("https://rpki.afrinic.net/tal/afrinic.tal");
+ if (error)
+ return error;
+ error = fetch_url("https://tal.apnic.net/apnic.tal");
+ if (error)
+ return error;
+ if (download_arin_tal())
+ error = fetch_url("https://www.arin.net/resources/manage/rpki/arin.tal");
+ error = fetch_url("https://www.lacnic.net/innovaportal/file/4983/1/lacnic.tal");
+ if (error)
+ return error;
+ error = fetch_url("https://tal.rpki.ripe.net/ripe-ncc.tal");
+ if (error)
+ return error;
+
+ return error;
+}
+
+int
+download_tal0s(void)
+{
+ int error;
+
+ error = fetch_url("https://tal.apnic.net/apnic-as0.tal");
+ if (error)
+ return error;
+
+ return fetch_url("https://www.lacnic.net/innovaportal/file/4983/1/lacnic-as0.tal");
}
#ifndef SRC_INIT_H_
#define SRC_INIT_H_
-#include "config/init_tals.h"
-
-int init_tals_exec(struct init_locations *, char const *);
+int download_tals(void);
+int download_tal0s(void);
#endif /* SRC_INIT_H_ */