-Display a warning when a directory doesn't have files with the desired extension (used at TAL and SLURM configuration).
-Set the minimum allowed value of 'maximum-certificate-depth' to 5 to allow a normal operation.
-Validate ROA output file path at initialization instead of doing it when the whole validation process has terminated.
-Add a note to indicate 64-bit OS support.
-Print the real address where the RTR server will be bounded to.
-If there's an error loading the SLURM data, show the element that has the error.
-Fix X509_VERIFY_PARAM memory leak.
-Update doc reference to UINT_MAX definition.
-Fix bug: when a TAL couldn't be loaded its references where trying to be released, but such references didn't existed.
2. [jansson](https://github.com/akheron/jansson)
3. [rsync](http://rsync.samba.org/)
+The validator is currently supported in *64-bit* OS. A 32-bit OS may face the [Year 2038 problem](https://en.wikipedia.org/wiki/Year_2038_problem) when handling dates at certificates.
+
After all the dependencies are installed, run:
```
2. libcrypto (Either [LibreSSL](http://www.libressl.org/) or [OpenSSL](https://www.openssl.org/))
3. [rsync](http://rsync.samba.org/)
+Fort is currently supported in *64-bit* OS. A 32-bit OS may face the [Year 2038 problem](https://en.wikipedia.org/wiki/Year_2038_problem) when handling dates at certificates, and currently there's no work around for this.
+
## Option 1: Installing the Debian package
> TODO Upload to Debian, add more archs
- **Type:** Integer
- **Availability:** `argv` and JSON
- **Default:** 32
+- **Range:** 5--([`UINT_MAX`](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html)--1)
Maximum allowable RPKI tree height. Meant to protect Fort from iterating infinitely due to certificate chain loops.
- **Type:** Integer
- **Availability:** `argv` and JSON
- **Default:** 3600
-- **Range:** 60--[`UINT_MAX`](http://pubs.opengroup.org/onlinepubs/9699919799/)
+- **Range:** 60--[`UINT_MAX`](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html)
Number of seconds the server will sleep between validation cycles.
The configuration options are mostly the same as the ones from the `argv` interface. (See the "Availability" metadata of each field.) Here's a full configuration file example:
<pre><code>{
- "<a href="#--tal">tal</a>": "/tmp/tal/test.tal",
- "<a href="#--local-repository">local-repository</a>": "/tmp/repository",
+ "<a href="#--tal">tal</a>": "/tmp/fort/tal/test.tal",
+ "<a href="#--local-repository">local-repository</a>": "/tmp/fort/repository",
"<a href="#--sync-strategy">sync-strategy</a>": "root",
"<a href="#--shuffle-uris">shuffle-uris</a>": true,
- "<a href="#--slurm">slurm</a>": "/tmp/test.slurm",
+ "<a href="#--slurm">slurm</a>": "/tmp/fort/test.slurm",
"<a href="#--mode">mode</a>": "server",
"server": {
],
"output": {
- "<a href="#--outputroa">roa</a>": "/tmp/fort_roas.csv"
+ "<a href="#--outputroa">roa</a>": "/tmp/fort/roas.csv"
}
}
</code></pre>
{
"local-repository": "a",
"sync-strategy": "root",
- "maximum-certificate-depth": 1
+ "maximum-certificate-depth": 5
}
$ cat b.json
{
"sync-strategy": "strict"
- "maximum-certificate-depth": 2
+ "maximum-certificate-depth": 6
}
$ cat c.json
{
- "maximum-certificate-depth": 4
+ "maximum-certificate-depth": 8
}
$ {{ page.command }} \
--configuration-file="a.json" \
--configuration-file="b.json" \
--configuration-file="c.json"
-$ # local-repository is "a", sync-strategy is "strict" and maximum-certificate-depth is 4
+$ # local-repository is "a", sync-strategy is "strict" and maximum-certificate-depth is 8
{% endhighlight %}
### rsync.program
.P
Because rsync uses delta encoding, you’re advised to keep this cache around. It
significantly speeds up subsequent validation cycles.
+.P
+By default, the path is \fI/tmp/fort/repository\fR.
.RE
.P
Maximum allowable certificate chain length. Meant to protect FORT from
iterating infinitely due to certificate chain loops.
.P
-By default, it has a value of \fI32\fR.
+By default, it has a value of \fI32\fR. The minimum allowed value is 5.
.P
(Required to prevent loops and "other degenerate forms of the logical RPKI
hierarchy." (RFC 6481))
.nf
{
- "tal": "/tmp/tal/",
- "local-repository": "/tmp/repository",
+ "tal": "/tmp/fort/tal/",
+ "local-repository": "/tmp/fort/repository",
"sync-strategy": "root",
"shuffle-uris": true,
"maximum-certificate-depth": 32,
}
],
"output": {
- "roa": "/tmp/roas.csv"
+ "roa": "/tmp/fort/roas.csv"
}
}
.fi
static int
process_file(char const *dir_name, char const *file_name, char const *file_ext,
- process_file_cb cb, void *arg)
+ int *fcount, process_file_cb cb, void *arg)
{
char *ext, *fullpath, *tmp;
int error;
return 0;
}
+ (*fcount)++; /* Increment the found count */
+
/* Get the full file path */
tmp = strdup(dir_name);
if (tmp == NULL)
{
DIR *dir_loc;
struct dirent *dir_ent;
- int error;
+ int found, error;
dir_loc = opendir(location);
if (dir_loc == NULL) {
}
errno = 0;
+ found = 0;
while ((dir_ent = readdir(dir_loc)) != NULL) {
- error = process_file(location, dir_ent->d_name, file_ext, cb,
- arg);
+ error = process_file(location, dir_ent->d_name, file_ext,
+ &found, cb, arg);
if (error) {
pr_err("The error was at file %s", dir_ent->d_name);
goto close_dir;
pr_err("Error reading dir %s", location);
error = -errno;
}
+ if (!error && found == 0)
+ pr_warn("Location '%s' doesn't have files with extension '%s'",
+ location, file_ext);
close_dir:
closedir(dir_loc);
end:
#include "common.h"
#include "configure_ac.h"
+#include "file.h"
#include "json_handler.h"
#include "log.h"
#include "config/boolean.h"
.offset = offsetof(struct rpki_config,
maximum_certificate_depth),
.doc = "Maximum allowable certificate chain length",
- .min = 1,
+ .min = 5,
/**
* It cannot be UINT_MAX, because then the actual number will
* overflow and will never be bigger than this.
return error;
}
+static bool
+valid_output_file(char const *path)
+{
+ return strcmp(path, "-") == 0 || file_valid(path);
+}
+
static int
validate_config(void)
{
+ if (rpki_config.output.roa != NULL &&
+ !valid_output_file(rpki_config.output.roa))
+ return pr_err("Invalid output.roa file.");
+
return (rpki_config.tal != NULL)
? 0
: pr_err("The TAL file/directory (--tal) is mandatory.");
{
free(fc->buffer);
}
+
+/*
+ * Validate @file_name, if it doesn't exist, this function will create it and
+ * close it.
+ */
+bool
+file_valid(char const *file_name)
+{
+ FILE *tmp;
+ struct stat stat;
+ int error;
+
+ if (file_name == NULL)
+ return false;
+
+ error = file_write(file_name, &tmp, &stat);
+ if (error)
+ return false;
+
+ file_close(tmp);
+ return true;
+}
#ifndef SRC_FILE_H_
#define SRC_FILE_H_
+#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <sys/stat.h>
int file_load(char const *, struct file_contents *);
void file_free(struct file_contents *);
+bool file_valid(char const *);
+
#endif /* SRC_FILE_H_ */
error = pr_err("None of the URIs of the TAL '%s' yielded a successful traversal.",
tal_file);
-end: tal_destroy(tal);
+ tal_destroy(tal);
+end:
fnstack_pop();
return error;
}
memset(&hints, 0 , sizeof(hints));
hints.ai_family = AF_UNSPEC;
/* hints.ai_socktype = SOCK_DGRAM; */
+ hints.ai_flags |= AI_CANONNAME;
hints.ai_flags |= AI_PASSIVE;
hostname = config_get_server_address();
if (error) {
if (error == -EEXIST)
pr_err(
- "The prefix %s element #%d, is duplicated or covered by another %s; SLURM loading will be stopped",
+ "The prefix %s element \"%s\", is duplicated or covered by another %s; SLURM loading will be stopped",
(is_assertion ? "assertion" : "filter"),
- index + 1,
+ json_dumps(element, 0),
(is_assertion ? "assertion" : "filter"));
else
pr_err(
- "Error at prefix %s, element #%d, SLURM loading will be stopped",
+ "Error at prefix %s, element \"%s\", SLURM loading will be stopped",
(is_assertion ? "assertions" : "filters"),
- index + 1);
+ json_dumps(element, 0));
return error;
}
if (error) {
if (error == -EEXIST)
pr_err(
- "The bgpsec %s element #%d, is duplicated or covered by another %s; SLURM loading will be stopped",
+ "The bgpsec %s element \"%s\", is duplicated or covered by another %s; SLURM loading will be stopped",
(is_assertion ? "assertion" : "filter"),
- index + 1,
+ json_dumps(element, 0),
(is_assertion ? "assertion" : "filter"));
else
pr_err(
- "Error at bgpsec %s, element #%d, SLURM loading will be stopped",
+ "Error at bgpsec %s, element \"%s\", SLURM loading will be stopped",
(is_assertion ? "assertions" : "filters"),
- index + 1);
+ json_dumps(element, 0));
return error;
}
struct validation {
struct tal *tal;
- /** https://www.openssl.org/docs/man1.1.1/man3/X509_STORE_load_locations.html */
- X509_STORE *store;
+ struct x509_data {
+ /** https://www.openssl.org/docs/man1.1.1/man3/X509_STORE_load_locations.html */
+ X509_STORE *store;
+ X509_VERIFY_PARAM *params;
+ } x509_data;
struct cert_stack *certstack;
result->tal = tal;
- result->store = X509_STORE_new();
- if (!result->store) {
+ result->x509_data.store = X509_STORE_new();
+ if (!result->x509_data.store) {
error = crypto_err("X509_STORE_new() returned NULL");
goto abort1;
}
}
X509_VERIFY_PARAM_set_flags(params, X509_V_FLAG_CRL_CHECK);
- X509_STORE_set1_param(result->store, params);
- X509_STORE_set_verify_cb(result->store, cb);
+ X509_STORE_set1_param(result->x509_data.store, params);
+ X509_STORE_set_verify_cb(result->x509_data.store, cb);
error = certstack_create(&result->certstack);
if (error)
- goto abort2;
+ goto abort3;
result->pubkey_state = PKS_UNTESTED;
result->validation_handler = *validation_handler;
+ result->x509_data.params = params; /* Ownership transfered */
*out = result;
return 0;
-
+abort3:
+ X509_VERIFY_PARAM_free(params);
abort2:
- X509_STORE_free(result->store);
+ X509_STORE_free(result->x509_data.store);
abort1:
free(result);
return error;
void
validation_destroy(struct validation *state)
{
- X509_STORE_free(state->store);
+ X509_VERIFY_PARAM_free(state->x509_data.params);
+ X509_STORE_free(state->x509_data.store);
certstack_destroy(state->certstack);
free(state);
}
X509_STORE *
validation_store(struct validation *state)
{
- return state->store;
+ return state->x509_data.store;
}
struct cert_stack *