- Uncomment some unit tests and update them.
- Rename server.enabled flag to server.disabled, and update the flows affected by this update.
- Update version references to 0.0.1-beta.
- Update manual (man).
- Include automake as a Debian dependency.
- Validate PDU length received vs real bytes length received.
- Don't die if the PDU reader gets less bytes than what's expected.
- Remove 'crl_set' from rpp.c since the 'crl' is a pointer (the flag isn't necessary).
- Don't set SLURM comments as 'char const *', just as 'char *'.
- Print the ROAs to 'output.roa' after SLURM has been applied, or even when an error stopped validation (only the ROAs fetched to that point are printed).
AC_PREREQ([2.69])
# TODO change the bug report address
-AC_INIT([fort], [0.0.1], [ydahhrk@gmail.com])
+AC_INIT([fort], [0.0.1-beta], [ydahhrk@gmail.com])
AC_CONFIG_SRCDIR([src/main.c])
AM_INIT_AUTOMAKE([subdir-objects])
values:
layout: "default"
-fort-latest-version: 0.0.1
+fort-latest-version: 0.0.1-beta
libcmscodec-latest-version: beta2
3. libcrypto (Either [LibreSSL](http://www.libressl.org/) or [OpenSSL](https://www.openssl.org/))
4. [rsync](http://rsync.samba.org/)
-There's also [autoconf](https://www.gnu.org/software/autoconf/) and unzip (or [git](https://git-scm.com/)), but those are only needed for installation paperwork.
+There's also [autoconf](https://www.gnu.org/software/autoconf/), [automake](https://www.gnu.org/software/automake/) and unzip (or [git](https://git-scm.com/)), but those are only needed for installation paperwork.
## Debian-based distributions
{% highlight bash %}
########### normal dependencies ###########
# autoconf 2.69 or higher, please.
-sudo apt install autoconf build-essential libjansson-dev libssl-dev pkg-config rsync unzip
+sudo apt install autoconf automake build-essential libjansson-dev libssl-dev pkg-config rsync unzip
############### libcmscodec ###############
mkdir libcmscodec
4. [`root-except-ta`](#root-except-ta)
7. [`--shuffle-uris`](#--shuffle-uris)
8. [`--maximum-certificate-depth`](#--maximum-certificate-depth)
- 9. [`--server.enabled`](#--serverenabled)
+ 9. [`--server.disabled`](#--serverdisabled)
10. [`--server.address`](#--serveraddress)
11. [`--server.port`](#--serverport)
12. [`--server.backlog`](#--serverbacklog)
[--sync-strategy=off|strict|root|root-except-ta]
[--shuffle-uris]
[--maximum-certificate-depth=<unsigned integer>]
- [--server.enabled=true|false]
+ [--server.disabled]
[--server.address=<string>]
[--server.port=<string>]
[--server.backlog=<unsigned integer>]
[--version]
(Print program version)
...
- [--output-file-name-format=global-url|local-path|file-name]
+ [--log.file-name-format=global-url|local-path|file-name]
(File name variant to print during debug/error messages)
- [--roa-output-file=<file>]
+ [--output.roa=<file>]
(File where the valid ROAs will be dumped.)
{% endhighlight %}
[--usage]
[--version]
...
- [--output-file-name-format=global-url|local-path|file-name]
- [--roa-output-file=<file>]
+ [--log.file-name-format=global-url|local-path|file-name]
+ [--output.roa=<file>]
{% endhighlight %}
### `--version`
{% highlight bash %}
$ {{ page.command }} --version
-0.0.1
+0.0.1-beta
{% endhighlight %}
### `--tal`
Fort's tree traversal is actually iterative (not recursive), so there should be no risk of stack overflow, regardless of this value.
-### `--server.enabled`
+### `--server.disabled`
-- **Type:** Boolean
+- **Type:** None
- **Availability:** `argv` and JSON
-- **Default:** true
-Enable or disable the RTR server.
+Disable the RTR server.
-If set to `false`: the server is disabled, the rest of the `server.*` arguments are discarded, and Fort performs an in-place standalone RPKI validation.
+If the flag is set, the server is disabled, the rest of the `server.*` arguments are discarded, and Fort performs an in-place standalone RPKI validation.
### `--server.address`
- `file-name`: Will print the certificate's name as `baz.cer`.
{% highlight bash %}
-$ {{ page.command }} --output-file-name-format global-url --local-repository repository/ (...)
+$ {{ page.command }} --log.file-name-format global-url --local-repository repository/ (...)
ERR: rsync://rpki.example.com/foo/bar/baz.cer: Certificate validation failed: certificate has expired
-$ {{ page.command }} --output-file-name-format local-path --local-repository repository/ (...)
+$ {{ page.command }} --log.file-name-format local-path --local-repository repository/ (...)
ERR: repository/rpki.example.com/foo/bar/baz.cer: Certificate validation failed: certificate has expired
-$ {{ page.command }} --output-file-name-format file-name --local-repository repository/ (...)
+$ {{ page.command }} --log.file-name-format file-name --local-repository repository/ (...)
ERR: baz.cer: Certificate validation failed: certificate has expired
{% endhighlight %}
<pre><code>{
"<a href="#--tal">tal</a>": "/tmp/tal/test.tal",
- "<a href="#--local-repository">local-repository</a>": "tmp/repository",
+ "<a href="#--local-repository">local-repository</a>": "/tmp/repository",
"<a href="#--sync-strategy">sync-strategy</a>": "root",
"<a href="#--shuffle-uris">shuffle-uris</a>": true,
- "<a href="#--slurm">slurm</a>": "test.slurm",
+ "<a href="#--slurm">slurm</a>": "/tmp/test.slurm",
"server": {
+ "<a href="#--serverdisabled">disabled</a>": false,
"<a href="#--serveraddress">address</a>": "192.0.2.1",
"<a href="#--serverport">port</a>": "8323",
"<a href="#--serverbacklog">backlog</a>": 16,
"name": "Signed Object's hash algorithm has NULL object as parameters",
"action": "ignore"
}
- ]
+ ],
+
+ "output": {
+ "<a href="#--outputroa">roa</a>": "/tmp/fort_roas.csv"
+ }
}
</code></pre>
-.TH rpki-validator 8 2019-03-5 v0.0.1-beta "RPKI certificate path validator"
+.TH fort 8 "2019-06-07" "v0.0.1-beta" "FORT validator"
.SH NAME
-rpki-validator - Actually still unnamed officially.
+fort \- RPKI certificate path validator
+.SH SYNOPSIS
+.B fort
+[\fIOPTIONS\fR]
+
+.SH DESCRIPTION
+
+FORT is an RPKI validator and a RTR server (currently only RTR version 0
+is supported).
+In the RPKI context, FORT is also known as an RP (Relying Party).
+A simple resume of the actions performed by an RP can be read at RFC 6480
+section 6
+.RI "(" https://tools.ietf.org/html/rfc6480#section-6 ")."
+.P
+The RTR (RPKI to Router Protocol) is basically "a protocol to deliver validated
+prefix origin data to routers", see RFC 6810
+.RI "(" https://tools.ietf.org/html/rfc6810 ")."
+.P
+
+So, FORT performs RPKI validations starting from a single or set of TALs (Trust
+Anchor Locators), either in a recurrent or single (standalone) way.
+Additionally, it can talk to routers using the RTR protocol (currently version
+0) to provide them the VRPs (Validated ROA Payloads) resultant of the
+validation.
+
.SH OPTIONS
+.TP
+.B \-h, \-\-help
+.RS 4
+Print long usage message and exit.
+.RE
+.P
---help
+.B \-\-usage
.RS 4
-Print long usage message.
+Print short usage message and exit.
.RE
.P
---usage
+.B \-V, \-\-version
.RS 4
-Print short usage message.
+Print program version and exit.
.RE
.P
---version
+.BR \-f ", " \-\-configuration-file=\fIFILE\fR
+.RS 4
+Path to a JSON file from where additional configuration will be read.
+.P
+The configuration options are mostly the same as the ones presented in this
+manual. Each property is mapped as a member of the main JSON object, the
+members that contain a dot '.' must be set as objects (eg.
+"--server.address=127.0.0.1" will be set as "{ "server": { "address":
+"127.0.0.1" } }".
+.P
+An example configuration file can be seen in this manual at the \fBEXAMPLES\fR
+section.
+.P
+Some configuration options can't be set at the JSON configuration file:
+\fB--version\fR, \fB--help\fR, \fB--version\fR, and \fB--configuration-file\fR.
+.P
+Other configuration options can be configured exclusively at the JSON
+configuration file:
+.P
+.B rsync.program
+.RS 4
+Name of the program needed to invoke an rsync file transfer. The default value
+is "rsync".
+.RE
+.P
+.B rsync.arguments-recursive
+.RS 4
+Arguments needed by
+.B rsync.program
+to perform a recursive rsync. The arguments are specified as a JSON string
+array; its default value is:
+[ "--recursive", "--delete", "--times", "--contimeout=20", "$REMOTE", "$LOCAL" ]
+.P
+FORT will replace "$REMOTE" with the remote URL it needs to download, and
+"$LOCAL" with the target local directory where the file is supposed to be
+dropped.
+.P
+If \fBrsync.program\fR set is \fIrsync\fR (default value), see more about its
+arguments and behavior at \fIrsync(1)\fR.
+.RE
+.P
+.B rsync.arguments-flat
+.RS 4
+Arguments needed by
+.B rsync.program
+to perform a single-file rsync. The arguments are specified as a JSON string
+array; its default value is:
+[ "--times", "--contimeout=20", "$REMOTE", "$LOCAL" ]
+.P
+FORT will replace "$REMOTE" with the remote URL it needs to download, and
+"$LOCAL" with the target local directory where the file is supposed to be
+dropped.
+.P
+If \fBrsync.program\fR set is \fIrsync\fR (default value), see more about its
+arguments and behavior at \fIrsync(1)\fR.
+.RE
+.P
+.B incidences
.RS 4
-Print program version.
+A listing of actions to be performed by validation upon encountering certain
+common error conditions. This configuration is a means to modify FORTs
+validator behavior upon encountering profile violations that, from experience,
+are often overlooked.
+.P
+The incidences are configured inside the member "incidences" as a JSON array
+of objects, each with two members "name" and "action", eg:
+.P
+"incidences": [
+.RS 2
+{
+.RS 2
+"name": "Signed Object's hash algorithm has NULL object as parameters",
+.br
+"action": "warn"
+.RE
+}
+.RE
+]
+.P
+An incidence contains a \fBname\fR and an \fBaction\fR. The \fBname\fR is
+merely an identifier defined by FORT that states a particular error condition,
+and the \fBaction\fR is an enumeration that states the outcome of a violation
+of the corresponding incidence.
+.P
+The \fBaction\fR can have one of three values:
+.br
+.RS 4
+\fIerror\fR: Print error message in error log level, fail validation of the
+offending object (and all of its children).
+.br
+\fIwarn\fR: Print error message in warning log level, continue validation as if
+nothing happened.
+.br
+\fIignore\fR: Do not print error message, continue validation as if nothing
+happened.
+.RE
+.P
+By default, all the incidences have an action of \fIerror\fR. Currently there's
+only one registered incidence:
+\fISigned Object's hash algorithm has NULL object as parameters\fR.
+.P
+More information about incidences can be consulted at FORT's web docs.
+.RE
.RE
.P
---configuration-file=<file>
+.BR \-t ", " \-\-tal=(\fIFILE\fR|\fIDIRECTORY\fR)
.RS 4
-Path to a JSON file from which additional configuration will be read.
+Path to the TAL file or directory the validation will sprawl from.
+.P
+If a DIRECTORY is specified, the files with the extension '\fI.tal\fR' are
+utilized by fort as TAL.
+.P
+The TAL ("Trust Anchor Locator") is a text file that lists a few URLs which can
+be used to access the "Trust Anchor" (the root of a particular RPKI tree) and
+its public key. (See RFC 7730.)
.RE
.P
---local-repository=<directory>
+.BR \-r ", " \-\-local-repository=\fIDIRECTORY\fR
.RS 4
Path to a directory where the local cache of the repository will be stored
and/or read.
+.P
+Right now, FORT accesses RPKI repositories by way of \fIrsync\fR. During each
+validation cycle, FORT will literally invoke an rsync command (see
+\fBrsync.program\fR and \fBrsync.arguments-recursive\fR), which will download
+the files into \fB--local-repository\fR. FORT’s validation operates on the resulting
+copy.
+.P
+Because rsync uses delta encoding, you’re advised to keep this cache around. It
+significantly speeds up subsequent validation cycles.
.RE
.P
---sync-strategy=(off|strict|root|root-except-ta)
+.B \-\-sync-strategy=(\fIoff\fR|\fIstrict\fR|\fIroot\fR|\fIroot-except-ta\fR)
.RS 4
-RSYNC download strategy.
+\fIrsync\fR download strategy; states the way rsync URLs are approached during
+downloads. It can have one of four values:
+.IR off ", "
+.IR strict ", "
+.IB "root" "(default value)" \fR, \fR
+.IR root-except-ta "."
.P
-off
+.I off
.RS 4
-Skip all RSYNCs. (Validate the existing cache repository pointed by --local-repository.)
+Skip all RSYNCs. (Validate the existing cache repository pointed by
+--local-repository.)
.RE
.P
-strict
+.I strict
.RS 4
RSYNC every repository publication point separately. Only skip publication
points that have already been downloaded during the current validation cycle.
This is the slowest, but also the strictly correct sync strategy.
.RE
.P
-root
+.I root
.RS 4
For each publication point found, guess the root of its repository and RSYNC
that instead. Then skip any subsequent children of said root.
all the current official repositories.
.RE
.P
-root-except-ta
+.I root-except-ta
.RS 4
Synchronizes the root certificate (the one pointed by the TAL) in 'strict' mode,
and once it's validated, synchronizes the rest of the repository in 'root' mode.
.RE
.P
---maximum-certificate-depth=<unsigned integer>
+.B \-\-shuffle-uris
+.RS 4
+If enabled, FORT will access TAL URLs in random order. This is meant for load
+balancing. If disabled, FORT will access TAL URLs in sequential order.
+.P
+By default, the flag is disabled.
+.P
+This flag is only relevant if the TAL lists more than one URL. Regardless of
+this flag, FORT will stop iterating through the URLs as soon as it finds one
+that yields a successful traversal.
+.RE
+.P
+
+.B \-\-maximum-certificate-depth=\fIUNSIGNED_INTEGER\fR
.RS 4
-Maximum allowable certificate chain length.
+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.
.P
(Required to prevent loops and "other degenerate forms of the logical RPKI
hierarchy." (RFC 6481))
.RE
.P
---tal=<file>
+.B \-\-slurm=(\fIFILE\fR|\fIDIRECTORY\fR)
.RS 4
-Path to the TAL file the validation will sprawl from.
+Path to the SLURM FILE or SLURMs DIRECTORY.
.P
-The TAL ("Trust Anchor Locator") is a text file that lists a few URLs which can
-be used to access the "Trust Anchor" (the root of a particular RPKI tree) and
-its public key. (See RFC 7730.)
+In case a DIRECTORY is set, the files with extension '\fI.slurm\fR' will be the
+ones considered as SLURM files and FORT will use them.
+.P
+The SLURM definition is from RFC 8416. SLURM stands for "Simplified Local
+Internet Number Resource Management with the RPKI", basically is a document
+that can override (either as a filter or adding assertions) the global RPKI
+repository data fetched by FORT; potentially useful for network operators.
+.P
+A basic example of a SLURM file can be seen in this manual at the
+\fBEXAMPLES\fR section (it's almost the same as the one in RFC 8416).
+.P
+See more about SLURM configuration at FORT's web docs.
.RE
.P
---shuffle-uris
+.B \-\-server.disabled
.RS 4
-Shuffle URIs in the TAL before accessing them.
+Disable the RTR server implemented by FORT. If this flag is set, the rest of
+the configuration options "\fIserver.*\fR" are ignored and FORT performs an
+in-place standalone RPKI validation.
+.P
+By default, the RTR server is enabled.
.RE
.P
---color-output
+.B \-\-server.address=\fINODE\fR
.RS 4
-Print ANSI color codes.
+Hostname or numeric host address the RTR server will be bound to. Must resolve
+to (or be) a bindable IP address. IPv4 and IPv6 are supported.
+.P
+If this field is omitted, FORT will attempt to bind the server using the IP
+address \fIINADDR_ANY\fR (for an IPv4 address) or \fIIN6ADDR_ANY_INIT\fR (for
+an IPv6 address). See \fBgetaddrinfo(3)\fR.
+.RE
+.P
+
+.B \-\-server.port=\fISERVICE\fR
+.RS 4
+TCP port or service the server will be bound to.
+.P
+This is a string because a service alias can be used as a valid value. The
+alias are commonly located at \fI/etc/services\fR. See also
+\fBgetaddrinfo(3)\fR and \fBservices(5)\fR.
+.P
+The default port (323) is privileged. To improve security, either change or
+jail it.
+.RE
+.P
+
+.B \-\-server.backlog=\fIUNSIGNED_INTEGER\fR
+.RS 4
+RTR server’s listen queue length. It’s the second argument of the function
+\fIlisten\fR (see more at man \fBlisten(2)\fR). This provides a hint to the
+implementation which the implementation shall use to limit the number of
+outstanding connections in the socket’s listen queue.
+.P
+By default, it has a value of \fISOMAXCONN\fR.
.RE
.P
---output-file-name-format=(global-url|local-path|file-name)
+.B \-\-server.validation-interval=\fIUNSIGNED_INTEGER\fR
+.RS 4
+Number of seconds that FORT will sleep between validation cycles. The timer
+starts counting every time a validation is finished, not every time it begins.
+Therefore, the actual validation loop is longer than this number.
+.P
+By default, it has a value of \fI3600\fR.
+.RE
+.P
+
+.BR \-c ", " \-\-log.color-output
+.RS 4
+If enabled, the logging output will contain ANSI color codes. Meant for human
+consumption.
+.RE
+.P
+
+.B \-\-log.file-name-format=(\fIglobal-url\fR|\fIlocal-path\fR|\fIfile-name\fR)
.RS 4
Decides which version of file names should be printed during most debug/error
messages.
.P
-Suppose a certificate was downloaded from `rsync://rpki.example.com/foo/bar/baz.cer` into the local cache `repository/`:
+Suppose a certificate was downloaded from
+`rsync://rpki.example.com/foo/bar/baz.cer` into the local cache `repository/`:
+.P
+.I global-url
+.RS 4
+Will print the certificate's name as `rsync://rpki.example.com/foo/bar/baz.cer`.
+.RE
+.P
+.I local-path
+.RS 4
+Will print the certificate's name as
+`repository/rpki.example.com/foo/bar/baz.cer`.
+.RE
+.P
+.I file-name
+.RS 4
+Will print the certificate's name as `baz.cer`.
+.RE
+.P
+.RE
+
+.B \-\-output.roa=\fIFILE\fR
+.RS 4
+File where the ROAs will be printed in CSV format.
+.P
+When the \fIFILE\fR is specified, its content will be overwritten by the
+resulting ROAs of the validation (if FILE doesn't exists, it'll be created).
+.P
+In order to print the ROAs at console, use a hyphen as the \fIFILE\fR value, eg.
+.B \-\-output.roa=-
+.RE
+
+.SH EXAMPLES
+.B fort \-t /tmp/tal \-r /tmp/repository \-\-server.port 9323
+.RS 4
+Run FORT with all the default values, using a custom TALs directory, a
+custom repository directory as well, and binding the RTR server to port 9323.
+.RE
+.P
+
+.B fort \-t /tmp/tal \-r /tmp/repository \-\-server.disabled \-\-output.roa -
+.RS 4
+Run FORT as standalone and output ROAs CSV to the console.
+.RE
.P
-global-url
+
+.nf
+\fBfort \-t /tmp/tal \-r /tmp/repository \\
+ \-\-server.disabled \\
+ \-\-slurm /tmp/myslurm.slurm\fR
+.fi
.RS 4
-will print the certificate's name as `rsync://rpki.example.com/foo/bar/baz.cer`.
+Run FORT as standalone and using a SLURM file.
.RE
.P
-local-path
+
+.B fort --configuration-file conf.json
.RS 4
-will print the certificate's name as `repository/rpki.example.com/foo/bar/baz.cer`.
+Run FORT using the JSON configuration file \fIconf.json\fR.
.RE
.P
-file-name
+
+.nf
+\fBfort \-t /tmp/tal \-r /tmp/repository \\
+ \-\-server.address ::1 \-\-server.port 9323 \\
+ \-\-server.validation-interval 1800 \\
+ \-\-output.roa /tmp/roas.csv\fR
.RS 4
-will print the certificate's name as `baz.cer`.
+Run FORT with RTR server listening on IPv6 address \fI::1\fR, port 9323,
+validating every 30 minutes, and printing the ROAs CSV in a file.
.RE
.P
+
+.B Complete configuration file
+.RS 4
+This is an example of a valid JSON configuration file with all its members set
+to a specific value:
+.nf
+
+{
+ "tal": "/tmp/tal/",
+ "local-repository": "/tmp/repository",
+ "sync-strategy": "root",
+ "shuffle-uris": true,
+ "maximum-certificate-depth": 32,
+ "slurm": "test.slurm",
+ "server": {
+ "disabled": false,
+ "address": "192.0.2.1",
+ "port": "8323",
+ "backlog": 64,
+ "validation-interval": 3600
+ },
+ "log": {
+ "color-output": true,
+ "file-name-format": "local-path"
+ },
+ "rsync": {
+ "program": "rsync",
+ "arguments-recursive": [
+ "--recursive",
+ "--delete",
+ "--times",
+ "--contimeout=20",
+ "$REMOTE",
+ "$LOCAL"
+ ],
+ "arguments-flat": [
+ "--times",
+ "--contimeout=20",
+ "$REMOTE",
+ "$LOCAL"
+ ]
+ },
+ "incidences": [
+ {
+ "name": "Signed Object's hash algorithm has NULL object as parameters",
+ "action": "ignore"
+ }
+ ],
+ "output": {
+ "roa": "/tmp/roas.csv"
+ }
+}
+.ni
+.RE
+.P
+
+.B Dummy SLURM file
+.RS 4
+This is an example of a SLURM file with some prefix filters and
+assertions:
+.nf
+
+{
+ "slurmVersion": 1,
+ "validationOutputFilters": {
+ "prefixFilters": [
+ {
+ "prefix": "192.0.2.0/24",
+ "comment": "All VRPs encompassed by prefix"
+ },
+ {
+ "asn": 64496,
+ "comment": "All VRPs matching ASN"
+ },
+ {
+ "prefix": "198.51.100.0/24",
+ "asn": 64497,
+ "comment": "All VRPs encompassed by prefix, matching ASN"
+ }
+ ],
+ "bgpsecFilters": []
+ },
+ "locallyAddedAssertions": {
+ "prefixAssertions": [
+ {
+ "asn": 64496,
+ "prefix": "198.51.100.0/24",
+ "comment": "My other important route"
+ },
+ {
+ "asn": 64496,
+ "prefix": "2001:DB8::/32",
+ "maxPrefixLength": 48,
+ "comment": "My other important de-aggregated routes"
+ }
+ ],
+ "bgpsecAssertions": []
+ }
+}
+.RE
+.ni
+.P
+
+.\".SH COPYRIGHT
+.\" FORT-validator 2019
+.\" Licensed under the blah blah...
+
+.SH SEE ALSO
+.B Regular man pages
+.RS 4
+.IR getaddrinfo(3) ", " services(5) ", " listen(2) ", " rsync(1)
+.RE
+.B FORTs official documentation
+.RS 4
+More documentation about FORT validator can be consulted at github repository
+(https://github.com/NICMx/FORT-validator) and github website
+(https://nicmx.github.io/FORT-validator/)
.RE
\ No newline at end of file
+++ /dev/null
-Blah blah WIP
char *slurm;
struct {
- /** Enable/disable the RTR server. */
- bool enabled;
+ /** Disable the RTR server. */
+ bool disabled;
/** The bound listening address of the RTR server. */
char *address;
/** The bound listening port of the RTR server. */
/* Server fields */
{
.id = 5000,
- .name = "server.enabled",
+ .name = "server.disabled",
.type = >_bool,
- .offset = offsetof(struct rpki_config, server.enabled),
- .doc = "Enable or disable the RTR server.",
+ .offset = offsetof(struct rpki_config, server.disabled),
+ .doc = "Disable the RTR server.",
}, {
.id = 5001,
.name = "server.address",
static int
handle_version(struct option_field const *field, char *arg)
{
- printf("0.0.1\n");
+ printf("0.0.1-beta\n");
exit(0);
}
* duplicates.
*/
- rpki_config.server.enabled = true;
+ rpki_config.server.disabled = false;
rpki_config.server.address = NULL;
rpki_config.server.port = strdup("323");
if (rpki_config.server.port == NULL)
}
bool
-config_get_server_enabled(void)
+config_get_server_disabled(void)
{
- return rpki_config.server.enabled;
+ return rpki_config.server.disabled;
}
char const *
void free_rpki_config(void);
/* Getters */
-bool config_get_server_enabled(void);
+bool config_get_server_disabled(void);
char const *config_get_server_address(void);
char const *config_get_server_port(void);
int config_get_server_queue(void);
#include "config.h"
#include "extension.h"
#include "log.h"
-#include "manifest.h"
#include "nid.h"
#include "str.h"
#include "thread_var.h"
#include "asn1/oid.h"
#include "crypto/hash.h"
#include "object/name.h"
+#include "object/manifest.h"
#include "rsync/rsync.h"
/* Just to prevent some line breaking. */
struct uris certs; /* Certificates */
struct rpki_uri *crl; /* Certificate Revocation List */
- bool crl_set;
/* Initialized lazily. Access via rpp_crl(). */
STACK_OF(X509_CRL) *crl_stack;
return NULL;
uris_init(&result->certs);
- result->crl_set = false;
+ result->crl = NULL;
result->crl_stack = NULL;
uris_init(&result->roas);
uris_init(&result->ghostbusters);
pp->references--;
if (pp->references == 0) {
uris_cleanup(&pp->certs, __uri_refput);
- if (pp->crl_set)
+ if (pp->crl != NULL)
uri_refput(pp->crl);
if (pp->crl_stack != NULL)
sk_X509_CRL_pop_free(pp->crl_stack, X509_CRL_free);
rpp_add_crl(struct rpp *pp, struct rpki_uri *uri)
{
/* rfc6481#section-2.2 */
- if (pp->crl_set)
+ if (pp->crl)
return pr_err("Repository Publication Point has more than one CRL.");
pp->crl = uri;
- pp->crl_set = true;
return 0;
}
struct rpki_uri *
rpp_get_crl(struct rpp const *pp)
{
- return pp->crl_set ? pp->crl : NULL;
+ return pp->crl;
}
static int
{
if (pp == NULL)
return NULL;
- if (!pp->crl_set)
+ if (pp->crl == NULL)
return NULL;
if (pp->crl_stack != NULL)
return pp->crl_stack;
validation_handler.arg = roas;
error = perform_standalone_validation(&validation_handler);
- /* Print after validation to avoid duplicated info */
- output_print_roas(roas);
if (error) {
roa_table_destroy(roas);
return error;
if (old_base != NULL)
roa_table_destroy(old_base);
+
+ /* Print after validation to avoid duplicated info */
+ output_print_roas(new_base);
+
return 0;
revert_deltas:
deltas_refput(deltas);
revert_base:
+ /* Print info that was already validated */
+ output_print_roas(new_base);
roa_table_destroy(new_base);
return error;
}
}
error = meta->from_stream(&header, &reader, request->pdu);
+ if (reader.size != 0) {
+ error = RESPOND_ERROR(err_pdu_send_invalid_request(fd,
+ request,
+ "The PDU length sent doesn't match the real PDU length"));
+ goto revert_pdu;
+ }
if (error) {
RESPOND_ERROR(err_pdu_send_internal_error(fd));
goto revert_pdu;
return read_exact(fd, reader->buffer, size, allow_eof);
}
-__dead static void
+static int
insufficient_bytes(void)
{
- pr_crit("Attempted to read past the end of a PDU Reader.");
+ pr_debug("Attempted to read past the end of a PDU Reader.");
+ return -EINVAL;
}
int
read_int8(struct pdu_reader *reader, uint8_t *result)
{
if (reader->size < 1)
- insufficient_bytes();
+ return insufficient_bytes();
*result = reader->buffer[0];
reader->buffer++;
read_int16(struct pdu_reader *reader, uint16_t *result)
{
if (reader->size < 2)
- insufficient_bytes();
+ return insufficient_bytes();
*result = (((uint16_t)reader->buffer[0]) << 8)
| (((uint16_t)reader->buffer[1]) );
read_int32(struct pdu_reader *reader, uint32_t *result)
{
if (reader->size < 4)
- insufficient_bytes();
+ return insufficient_bytes();
*result = (((uint32_t)reader->buffer[0]) << 24)
| (((uint32_t)reader->buffer[1]) << 16)
read_bytes(struct pdu_reader *reader, unsigned char *result, size_t num)
{
if (reader->size < num)
- insufficient_bytes();
+ return insufficient_bytes();
memcpy(result, reader->buffer, num);
reader->buffer += num;
/*
* Starts the server, using the current thread to listen for RTR client
- * requests. If configuration parameter 'server.enabled' is false, then the
+ * requests. If configuration parameter 'server.disabled' is true, then the
* server runs "one time" (a.k.a. run the validation just once), it doesn't
* waits for clients requests.
*
if (error)
return error;
- if (!config_get_server_enabled()) {
+ if (config_get_server_disabled()) {
error = vrps_update(&changed);
if (error)
pr_err("Error %d while trying to update the ROA database.",
clean_slurm_prefix(struct slurm_prefix *prefix)
{
if ((prefix->data_flag & SLURM_COM_FLAG_COMMENT) > 0)
- free((void *)prefix->comment);
+ free(prefix->comment);
}
static void
if ((bgpsec->data_flag & SLURM_BGPS_FLAG_ROUTER_KEY) > 0)
free(bgpsec->router_public_key);
if ((bgpsec->data_flag & SLURM_COM_FLAG_COMMENT) > 0)
- free((void *)bgpsec->comment);
+ free(bgpsec->comment);
}
void
}
static int
-set_comment(json_t *object, char const **comment, uint8_t *flag,
+set_comment(json_t *object, char **comment, uint8_t *flag,
size_t *members_loaded)
{
char const *tmp;
return 0;
release_comment:
- free((void *)result.comment);
+ free(result.comment);
return error;
}
return 0;
release_comment:
- free((void *)result.comment);
+ free(result.comment);
release_router_key:
free(result.router_public_key);
release_ski:
struct slurm_prefix {
uint8_t data_flag;
struct vrp vrp;
- char const *comment;
+ char *comment;
};
struct slurm_bgpsec {
size_t ski_len;
unsigned char *router_public_key;
size_t router_public_key_len;
- char const *comment;
+ char *comment;
};
check_PROGRAMS += pdu_handler.test
check_PROGRAMS += rsync.test
check_PROGRAMS += roa_table.test
-#check_PROGRAMS += tal.test
+check_PROGRAMS += tal.test
check_PROGRAMS += vcard.test
check_PROGRAMS += vrps.test
-#check_PROGRAMS += rtr/pdu.test
-#check_PROGRAMS += rtr/primitive_reader.test
+check_PROGRAMS += rtr/pdu.test
+check_PROGRAMS += rtr/primitive_reader.test
TESTS = ${check_PROGRAMS}
address_test_SOURCES = address_test.c
rsync_test_SOURCES = rsync_test.c
rsync_test_LDADD = ${MY_LDADD}
-#tal_test_SOURCES = ${BASIC_MODULES}
-#tal_test_SOURCES += ../src/file.c
-#tal_test_SOURCES += ../src/crypto/base64.c
-#tal_test_SOURCES += ../src/random.c
-#tal_test_SOURCES += ../src/str.c
-#tal_test_SOURCES += ../src/uri.c
-#tal_test_SOURCES += ../src/line_file.c
-#tal_test_SOURCES += tal_test.c
-#tal_test_LDADD = ${MY_LDADD}
+tal_test_SOURCES = tal_test.c
+tal_test_LDADD = ${MY_LDADD}
vcard_test_SOURCES = vcard_test.c
vcard_test_LDADD = ${MY_LDADD}
vrps_test_SOURCES = rtr/db/vrps_test.c
vrps_test_LDADD = ${MY_LDADD} ${JANSSON_LIBS}
-#rtr_pdu_test_SOURCES = ${BASIC_MODULES}
-#rtr_pdu_test_SOURCES += rtr/pdu_test.c
-#rtr_pdu_test_SOURCES += rtr/stream.c
-#rtr_pdu_test_SOURCES += ../src/rtr/primitive_reader.c
-#rtr_pdu_test_SOURCES += ../src/rtr/pdu_handler.c
-#rtr_pdu_test_LDADD = ${MY_LDADD}
-
-#rtr_primitive_reader_test_SOURCES = ${BASIC_MODULES}
-#rtr_primitive_reader_test_SOURCES += rtr/primitive_reader_test.c
-#rtr_primitive_reader_test_SOURCES += rtr/stream.c
-#rtr_primitive_reader_test_LDADD = ${MY_LDADD}
+rtr_pdu_test_SOURCES = rtr/pdu_test.c
+rtr_pdu_test_LDADD = ${MY_LDADD}
+
+rtr_primitive_reader_test_SOURCES = rtr/primitive_reader_test.c
+rtr_primitive_reader_test_LDADD = ${MY_LDADD}
EXTRA_DIST = impersonator.c
EXTRA_DIST += rtr/db/rtr_db_impersonator.c
return inet_ntop(AF_INET6, addr, addr_buffer2, sizeof(addr_buffer2));
}
+char const *
+config_get_tal(void)
+{
+ return "tal/";
+}
+
+bool
+config_get_shuffle_tal_uris(void)
+{
+ return false;
+}
+
+unsigned int
+config_get_max_cert_depth(void)
+{
+ return 32;
+}
+
char const *
config_get_local_repository(void)
{
}
bool
-config_get_server_enabled(void)
+config_get_server_disabled(void)
{
- return false;
+ return true;
}
char const *
config_get_output_roa(void)
{
- return "-";
+ return NULL;
}
enum incidence_action
#include <check.h>
#include "object/tal.h"
+#include "address.c"
+
static int iteration = 0;
static void
#include <stdbool.h>
#include <stdlib.h>
-#include "address.c"
#include "crypto/base64.c"
#include "common.c"
#include "file.c"
#include <check.h>
#include <stdlib.h>
+#include <unistd.h>
#include <sys/queue.h>
-#include "address.c"
#include "common.c"
#include "file.c"
#include "impersonator.c"
#include "log.c"
#include "output_printer.c"
#include "crypto/base64.c"
+#include "rtr/pdu.c"
#include "rtr/pdu_handler.c"
+#include "rtr/primitive_reader.c"
+#include "rtr/primitive_writer.c"
#include "rtr/err_pdu.c"
+#include "rtr/stream.c"
#include "rtr/db/delta.c"
#include "rtr/db/roa_table.c"
#include "rtr/db/rtr_db_impersonator.c"
struct rtr_request request;
struct serial_query_pdu client_pdu;
- pr_info("-- Bad Session ID--");
+ pr_info("-- Bad Session ID --");
/* Prepare DB */
init_db_full();
}
END_TEST
+size_t
+serialize_serial_query_pdu(struct serial_query_pdu *pdu, unsigned char *buf)
+{
+ unsigned char *ptr;
+
+ ptr = buf;
+ ptr = write_int8(ptr, pdu->header.protocol_version);
+ ptr = write_int8(ptr, pdu->header.pdu_type);
+ ptr = write_int16(ptr, pdu->header.m.session_id);
+ ptr = write_int32(ptr, pdu->header.length);
+ ptr = write_int32(ptr, pdu->serial_number);
+
+ return ptr - buf;
+}
+
+START_TEST(test_bad_length)
+{
+#define BUF_SIZE 13 /* Max expected length */
+ struct rtr_request request;
+ struct serial_query_pdu client_pdu;
+ struct pdu_metadata const *meta;
+ unsigned char buf[BUF_SIZE];
+ int fd;
+
+ pr_info("-- Bad Length --");
+
+ /* Prepare DB */
+ init_db_full();
+
+ /* From serial 0: Init client request */
+ init_serial_query(&request, &client_pdu, 0);
+ /* Less than what's specified */
+ client_pdu.header.length--;
+
+ ck_assert_int_gt(serialize_serial_query_pdu(&client_pdu, buf), 0);
+ fd = buffer2fd(buf, BUF_SIZE);
+ ck_assert_int_ge(fd, 0);
+
+ /* Define expected server response */
+ expected_pdu_add(PDU_TYPE_ERROR_REPORT);
+
+ /* Run and validate, before handling */
+ ck_assert_int_eq(-EINVAL, pdu_load(fd, &request, &meta));
+ ck_assert_uint_eq(false, has_expected_pdus());
+
+ /* Clean up */
+ vrps_destroy();
+ close(fd);
+#undef BUF_SIZE
+}
+END_TEST
+
Suite *pdu_suite(void)
{
Suite *suite;
error = tcase_create("Unhappy path cases");
tcase_add_test(error, test_bad_session_id);
+ tcase_add_test(error, test_bad_length);
suite = suite_create("PDU Handler");
suite_add_tcase(suite, core);
#include <stdio.h>
#include <unistd.h>
-#include "stream.h"
+#include "log.c"
+#include "impersonator.c"
+#include "rtr/stream.c"
+#include "rtr/err_pdu.c"
#include "rtr/pdu.c"
+#include "rtr/primitive_reader.c"
+#include "rtr/db/rtr_db_impersonator.c"
/*
* Just a wrapper for `buffer2fd()`. Boilerplate one-liner.
*/
#define BUFFER2FD(buffer, cb, obj) { \
struct pdu_header header; \
+ struct pdu_reader reader; \
+ unsigned char read[sizeof(buffer)]; \
int fd, err; \
\
fd = buffer2fd(buffer, sizeof(buffer)); \
ck_assert_int_ge(fd, 0); \
- init_pdu_header(&header); \
- err = cb(&header, fd, obj); \
+ ck_assert_int_eq(pdu_reader_init(&reader, fd, read, \
+ sizeof(buffer), true), 0); \
close(fd); \
+ init_pdu_header(&header); \
+ err = cb(&header, &reader, obj); \
ck_assert_int_eq(err, 0); \
assert_pdu_header(&(obj)->header); \
}
+/* Impersonator functions */
+
+#define IMPERSONATE_HANDLER(name) \
+ int \
+ handle_## name ##_pdu(int fd, struct rtr_request const *req) { \
+ return 0; \
+ }
+
+uint16_t
+get_current_session_id(uint8_t rtr_version)
+{
+ return 12345;
+}
+
+IMPERSONATE_HANDLER(serial_notify)
+IMPERSONATE_HANDLER(serial_query)
+IMPERSONATE_HANDLER(reset_query)
+IMPERSONATE_HANDLER(cache_response)
+IMPERSONATE_HANDLER(ipv4_prefix)
+IMPERSONATE_HANDLER(ipv6_prefix)
+IMPERSONATE_HANDLER(end_of_data)
+IMPERSONATE_HANDLER(cache_reset)
+IMPERSONATE_HANDLER(router_key)
+IMPERSONATE_HANDLER(error_report)
+
+int
+send_error_report_pdu(int fd, uint16_t code, struct rtr_request const *request,
+ char *message)
+{
+ pr_info(" Server sent Error Report %u: '%s'", code, message);
+ return 0;
+}
+
+/* End of impersonator */
+
static void
init_pdu_header(struct pdu_header *header)
{
- header->protocol_version = 0;
+ header->protocol_version = RTR_V0;
header->pdu_type = 22;
- header->m.reserved = 12345;
- header->length = 0xFFAA9955;
+ header->m.reserved = get_current_session_id(RTR_V0);
+ header->length = 0x00000020;
}
static void
{
ck_assert_uint_eq(header->protocol_version, 0);
ck_assert_uint_eq(header->pdu_type, 22);
- ck_assert_uint_eq(header->m.reserved, 12345);
- ck_assert_uint_eq(header->length, 0xFFAA9955);
+ ck_assert_uint_eq(header->m.reserved, get_current_session_id(RTR_V0));
+ ck_assert_uint_eq(header->length, 0x00000020);
}
START_TEST(test_pdu_header_from_stream)
{
unsigned char input[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
+ unsigned char read[RTRPDU_HDR_LEN];
+ struct pdu_reader reader;
struct pdu_header header;
int fd;
int err;
fd = buffer2fd(input, sizeof(input));
ck_assert_int_ge(fd, 0);
- err = pdu_header_from_reader(fd, &header);
+ ck_assert_int_eq(pdu_reader_init(&reader, fd, read, RTRPDU_HDR_LEN,
+ true), 0);
close(fd);
+ /* Read the header into its buffer. */
+ err = pdu_header_from_reader(&reader, &header);
ck_assert_int_eq(err, 0);
ck_assert_uint_eq(header.protocol_version, 0);
unsigned char input[] = {
/* Sub-pdu length */
0, 0, 0, 12,
- /* Sub-pdu */
+ /* Sub-pdu w header*/
1, 0, 2, 3, 0, 0, 0, 12, 1, 2, 3, 4,
/* Error msg length */
0, 0, 0, 5,
};
struct error_report_pdu *pdu;
struct serial_notify_pdu *sub_pdu;
+ struct pdu_header sub_pdu_header;
+ struct pdu_reader reader;
+ unsigned char sub_pdu_read[12];
+ int fd, err;
pdu = malloc(sizeof(struct error_report_pdu));
if (!pdu)
ck_abort_msg("PDU allocation failure");
+ sub_pdu = malloc(sizeof(struct serial_notify_pdu));
+ if (!sub_pdu) {
+ ck_abort_msg("SUB PDU allocation failure");
+ free(pdu);
+ }
+
BUFFER2FD(input, error_report_from_stream, pdu);
- sub_pdu = pdu->erroneous_pdu;
+ /* Get the erroneous PDU as a serial notify */
+ fd = buffer2fd(pdu->erroneous_pdu, pdu->error_pdu_length);
+ ck_assert_int_ge(fd, 0);
+ ck_assert_int_eq(pdu_reader_init(&reader, fd, sub_pdu_read,
+ pdu->error_pdu_length, true), 0);
+ close(fd);
+
+ ck_assert_int_eq(pdu_header_from_reader(&reader, &sub_pdu_header), 0);
+ err = serial_notify_from_stream(&sub_pdu_header, &reader, sub_pdu);
+ ck_assert_int_eq(err, 0);
+
ck_assert_uint_eq(sub_pdu->header.protocol_version, 1);
ck_assert_uint_eq(sub_pdu->header.pdu_type, 0);
ck_assert_uint_eq(sub_pdu->header.m.reserved, 0x0203);
* Not sure how to fix it without making a huge mess.
*/
error_report_destroy(pdu);
+ free(sub_pdu);
}
END_TEST
START_TEST(test_interrupted)
{
unsigned char input[] = { 0, 1 };
- struct serial_notify_pdu pdu;
- struct pdu_header header;
+ struct pdu_reader reader;
+ unsigned char read[4];
int fd, err;
fd = buffer2fd(input, sizeof(input));
ck_assert_int_ge(fd, 0);
- init_pdu_header(&header);
- err = serial_notify_from_stream(&header, fd, &pdu);
+ err = pdu_reader_init(&reader, fd, read, 4, true);
close(fd);
ck_assert_int_eq(err, -EPIPE);
}
#include <stdlib.h>
#include <string.h>
-#include "stream.h"
+#include "impersonator.c"
+#include "log.c"
+#include "rtr/stream.c"
#include "rtr/primitive_reader.c"
/*
static int
__read_string(unsigned char *input, size_t size, rtr_char **result)
{
+ struct pdu_reader reader;
+ unsigned char read_bytes[size];
int fd;
int err;
+ uint32_t usize;
fd = buffer2fd(input, size);
if (fd < 0)
return fd;
- err = read_string(fd, result);
+ err = pdu_reader_init(&reader, fd, read_bytes, size, false);
+ if (err)
+ goto close;
+
+ usize = size & 0xFFFF;
+ err = read_string(&reader, usize, result);
+close:
close(fd);
return err;
}
START_TEST(read_string_ascii)
{
- unsigned char input[] = { 0, 0, 0, 4, 'a', 'b', 'c', 'd' };
+ unsigned char input[] = { 'a', 'b', 'c', 'd' };
test_read_string_success(input, sizeof(input), "abcd");
}
END_TEST
START_TEST(read_string_unicode)
{
- unsigned char input0[] = { 0, 0, 0, 7, 's', 'a', 'n', 'd', 0xc3, 0xad,
- 'a' };
+ unsigned char input0[] = { 's', 'a', 'n', 'd', 0xc3, 0xad, 'a' };
test_read_string_success(input0, sizeof(input0), "sandía");
- unsigned char input1[] = { 0, 0, 0, 12,
- 0xe1, 0x88, 0x90, 0xe1, 0x89, 0xa5, 0xe1, 0x88, 0x90, 0xe1, 0x89,
- 0xa5 };
+ unsigned char input1[] = { 0xe1, 0x88, 0x90, 0xe1, 0x89, 0xa5, 0xe1,
+ 0x88, 0x90, 0xe1, 0x89, 0xa5 };
test_read_string_success(input1, sizeof(input1), "ሐብሐብ");
- unsigned char input2[] = { 0, 0, 0, 12,
- 0xd8, 0xa7, 0xd9, 0x84, 0xd8, 0xa8, 0xd8, 0xb7, 0xd9, 0x8a, 0xd8,
- 0xae };
+ unsigned char input2[] = { 0xd8, 0xa7, 0xd9, 0x84, 0xd8, 0xa8, 0xd8,
+ 0xb7, 0xd9, 0x8a, 0xd8, 0xae };
test_read_string_success(input2, sizeof(input2), "البطيخ");
- unsigned char input3[] = { 0, 0, 0, 25,
+ unsigned char input3[] = {
0xd5, 0xb1, 0xd5, 0xb4, 0xd5, 0xa5, 0xd6, 0x80, 0xd5, 0xb8, 0xd6,
0x82, 0xd5, 0xaf, 0x20, 0xd0, 0xba, 0xd0, 0xb0, 0xd0, 0xb2, 0xd1,
0x83, 0xd0, 0xbd };
test_read_string_success(input3, sizeof(input3), "ձմերուկ кавун");
- unsigned char input4[] = { 0, 0, 0, 36,
+ unsigned char input4[] = {
0xe0, 0xa6, 0xa4, 0xe0, 0xa6, 0xb0, 0xe0, 0xa6, 0xae, 0xe0, 0xa7,
0x81, 0xe0, 0xa6, 0x9c, 0x20, 0xd0, 0xb4, 0xd0, 0xb8, 0xd0, 0xbd,
0xd1, 0x8f, 0x20, 0xe8, 0xa5, 0xbf, 0xe7, 0x93, 0x9c, 0x20, 0xf0,
START_TEST(read_string_empty)
{
- unsigned char input[] = { 0, 0, 0, 0 };
- test_read_string_success(input, sizeof(input), "");
+ unsigned char *input = { '\0' };
+ test_read_string_fail(input, sizeof(input), -EFAULT);
}
END_TEST
struct thread_param *param;
rtr_char *pattern;
size_t pattern_len;
- unsigned char header[4];
param = param_void;
pattern = WRITER_PATTERN;
pattern_len = strlen(pattern);
- /* Write the string length */
- header[0] = (param->msg_size >> 24) & 0xFF;
- header[1] = (param->msg_size >> 16) & 0xFF;
- header[2] = (param->msg_size >> 8) & 0xFF;
- header[3] = (param->msg_size >> 0) & 0xFF;
- param->err = write_exact(param->fd, header, sizeof(header));
- if (param->err)
- return param;
-
/* Write the string */
for (; param->msg_size > pattern_len; param->msg_size -= pattern_len) {
param->err = write_exact(param->fd, UCHAR(pattern), pattern_len);
int fd[2];
pthread_t writer_thread;
struct thread_param *arg;
+ struct pdu_reader reader;
+ unsigned char *read_bytes;
rtr_char *result_string;
int err, err2, err3;
free(arg);
ck_abort_msg("pthread_create() threw errcode %d", err);
}
- /* The writer thread owns @arg now; do not touch it until retrievel */
+ /* The writer thread owns @arg now; do not touch it until retrieved */
+ do {
+ read_bytes = malloc(full_string_length);
+ err = pdu_reader_init(&reader, fd[0], read_bytes,
+ full_string_length, false);
+ if (err)
+ break;
+ err = read_string(&reader, full_string_length, &result_string);
+ } while(0);
- err = read_string(fd[0], &result_string);
/* Need to free @result_string from now on */
err2 = pthread_join(writer_thread, (void **)&arg);
/* @arg is now retrieved. */
close(fd[0]);
close(fd[1]);
free(arg);
+ free(read_bytes);
/* Don't need to close @fd[0], @fd[1] nor free @arg from now on */
if (err || err2 || err3) {
test_massive_string(4000, 4000);
test_massive_string(4094, 4094);
test_massive_string(4095, 4095);
- test_massive_string(4095, 4096);
- test_massive_string(4095, 4097);
- test_massive_string(4095, 8000);
- test_massive_string(4095, 16000);
- test_massive_string(4095, 0xFFFFFFFF);
+ test_massive_string(4096, 4096);
+ test_massive_string(4097, 4097);
+ test_massive_string(8000, 8000);
+ test_massive_string(16000, 16000);
+ test_massive_string(786432000, 786432000); /* 750MB */
}
END_TEST
START_TEST(read_string_null)
{
- test_read_string_fail(NULL, 0, -EPIPE);
-}
-END_TEST
-
-START_TEST(read_string_truncated)
-{
- unsigned char input0[] = { 0, 0, 0, 7, 'a', 'b' };
- test_read_string_fail(input0, sizeof(input0), -EPIPE);
-
- unsigned char input1[] = { 0, 0 };
- test_read_string_fail(input1, sizeof(input1), -EPIPE);
+ test_read_string_success(NULL, 0, "");
}
END_TEST
START_TEST(read_string_unicode_mix)
{
/* One octet failure */
- unsigned char input0[] = { 0, 0, 0, 3, 'a', 0x80, 'z' };
+ unsigned char input0[] = { 'a', 0x80, 'z' };
test_read_string_success(input0, sizeof(input0), "a");
/* Two octets success */
- unsigned char input1[] = { 0, 0, 0, 4, 'a', 0xdf, 0x9a, 'z' };
+ unsigned char input1[] = { 'a', 0xdf, 0x9a, 'z' };
test_read_string_success(input1, sizeof(input1), "aߚz");
/* Two octets failure */
- unsigned char input2[] = { 0, 0, 0, 4, 'a', 0xdf, 0xda, 'z' };
+ unsigned char input2[] = { 'a', 0xdf, 0xda, 'z' };
test_read_string_success(input2, sizeof(input2), "a");
/* Three characters success */
- unsigned char input3[] = { 0, 0, 0, 5, 'a', 0xe2, 0x82, 0xac, 'z' };
+ unsigned char input3[] = { 'a', 0xe2, 0x82, 0xac, 'z' };
test_read_string_success(input3, sizeof(input3), "a€z");
/* Three characters failure */
- unsigned char input4[] = { 0, 0, 0, 5, 'a', 0xe2, 0x82, 0x2c, 'z' };
+ unsigned char input4[] = { 'a', 0xe2, 0x82, 0x2c, 'z' };
test_read_string_success(input4, sizeof(input4), "a");
/* Four characters success */
- unsigned char i5[] = { 0, 0, 0, 6, 'a', 0xf0, 0x90, 0x86, 0x97, 'z' };
+ unsigned char i5[] = { 'a', 0xf0, 0x90, 0x86, 0x97, 'z' };
test_read_string_success(i5, sizeof(i5), "a𐆗z");
/* Four characters failure */
- unsigned char i6[] = { 0, 0, 0, 6, 'a', 0xf0, 0x90, 0x90, 0x17, 'z' };
+ unsigned char i6[] = { 'a', 0xf0, 0x90, 0x90, 0x17, 'z' };
test_read_string_success(i6, sizeof(i6), "a");
}
END_TEST
limits = tcase_create("Limits");
tcase_add_test(limits, read_string_empty);
tcase_add_test(limits, read_string_massive);
- /* The 0xFFFFFFFF test lasts 1:02 minutes on my computer. */
- tcase_set_timeout(limits, 120);
+ tcase_set_timeout(limits, 60);
errors = tcase_create("Errors");
tcase_add_test(errors, read_string_null);
- tcase_add_test(errors, read_string_truncated);
tcase_add_test(errors, read_string_unicode_mix);
suite = suite_create("read_string()");
#include <stdlib.h>
#include "common.h"
+#include "file.c"
+#include "impersonator.c"
+#include "line_file.c"
+#include "log.c"
+#include "state.h"
+#include "str.c"
+#include "uri.c"
+#include "random.c"
+#include "crypto/base64.c"
+#include "rsync/rsync.c"
+
+/* Impersonate functions that won't be utilized by tests */
+
+int
+validation_prepare(struct validation **out, struct tal *tal,
+ struct validation_handler *validation_handler)
+{
+ return 0;
+}
+
+int
+certificate_traverse(struct rpp *rpp_parent, struct rpki_uri *cert_uri)
+{
+ return -EINVAL;
+}
+
+enum pubkey_state
+validation_pubkey_state(struct validation *state)
+{
+ return PKS_INVALID;
+}
+
+void
+validation_destroy(struct validation *state)
+{
+ /* Nothing to destroy */
+}
+
+int
+process_file_or_dir(char const *location, char const *file_ext,
+ process_file_cb cb, void *arg)
+{
+ return 0;
+}
+
+void
+fnstack_init(void)
+{
+ /* Empty */
+}
+
+void
+fnstack_cleanup(void)
+{
+ /* Empty */
+}
+
+void
+fnstack_pop(void)
+{
+ /* Empty */
+}
+
+void
+fnstack_push(char const *file)
+{
+ /* Empty */
+}
+
START_TEST(tal_load_normal)
{
struct tal *tal;