]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Update manual, unit tests, and add some fixes.
authorpcarana <pc.moreno2099@gmail.com>
Tue, 11 Jun 2019 23:08:45 +0000 (18:08 -0500)
committerpcarana <pc.moreno2099@gmail.com>
Tue, 11 Jun 2019 23:08:45 +0000 (18:08 -0500)
- 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).

25 files changed:
configure.ac
docs/_config.yml
docs/doc/installation.md
docs/doc/usage.md
man/fort.8
man/rtr_server.8 [deleted file]
src/config.c
src/config.h
src/object/certificate.c
src/rpp.c
src/rtr/db/vrps.c
src/rtr/pdu.c
src/rtr/primitive_reader.c
src/rtr/rtr.c
src/slurm/slurm_db.c
src/slurm/slurm_parser.c
src/slurm/slurm_parser.h
test/Makefile.am
test/impersonator.c
test/rtr/db/rtr_db_impersonator.c
test/rtr/db/vrps_test.c
test/rtr/pdu_handler_test.c
test/rtr/pdu_test.c
test/rtr/primitive_reader_test.c
test/tal_test.c

index f3263aa766f94e0b06b6473b2855854c9f5e3f91..68d13f0fbec65a0d6c1e348f852804f8a34f991d 100644 (file)
@@ -3,7 +3,7 @@
 
 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])
 
index fd35565f85cb0019777cbca04a48b716b05b084a..f4761bc06b299d9e7d11f19049777aa6dcde530a 100644 (file)
@@ -7,5 +7,5 @@ defaults:
     values:
       layout: "default"
 
-fort-latest-version: 0.0.1
+fort-latest-version: 0.0.1-beta
 libcmscodec-latest-version: beta2
index 176a9ca54286bcee9898c511e9bc5d64f4ca215c..939db34ca3d14cdf31e6ed78e0e0bdcfbc03dc5d 100644 (file)
@@ -37,7 +37,7 @@ The dependencies are
 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
 
@@ -46,7 +46,7 @@ I haven't actually tried this in all the Debian-based distributions. Tested in U
 {% 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
index a69ea0cbc6853ab9994ef2fe86c3086ecbba1ec6..ddf05ee006915c88f8245e2333fbe115a990ef78 100644 (file)
@@ -23,7 +23,7 @@ command: fort
                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)
@@ -53,7 +53,7 @@ command: fort
         [--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>]
@@ -92,9 +92,9 @@ Usage: {{ page.command }}
         [--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 %}
 
@@ -114,8 +114,8 @@ Usage: {{ page.command }}
         [--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`
@@ -127,7 +127,7 @@ Prints program version.
 
 {% highlight bash %}
 $ {{ page.command }} --version
-0.0.1
+0.0.1-beta
 {% endhighlight %}
 
 ### `--tal`
@@ -238,15 +238,14 @@ Maximum allowable RPKI tree height. Meant to protect Fort from iterating infinit
 
 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`
 
@@ -338,13 +337,13 @@ Suppose a certificate was downloaded from `rsync://rpki.example.com/foo/bar/baz.
 - `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 %}
 
@@ -370,12 +369,13 @@ The configuration options are mostly the same as the ones from the `argv` interf
 
 <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,
@@ -407,7 +407,11 @@ The configuration options are mostly the same as the ones from the `argv` interf
                        "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>
 
index c5c946b8909d52ec9e13d05c67cc20abdf6b570a..42f8748eae0501029a81fd09334bd5edd50ce152 100644 (file)
-.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.
@@ -74,7 +226,7 @@ A validator following the `strict` strategy would download `bar`, download
 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.
@@ -92,7 +244,7 @@ is the fastest synchronization strategy. At time of writing, this is true for
 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.
@@ -105,57 +257,304 @@ root certificate.
 .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
diff --git a/man/rtr_server.8 b/man/rtr_server.8
deleted file mode 100644 (file)
index f67128f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Blah blah WIP
index f9f17c47c16313c6988291cec35298193d615ee4..8b64b099707c07eeae377a14fc36ecaca9f24113 100644 (file)
@@ -48,8 +48,8 @@ struct rpki_config {
        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. */
@@ -198,10 +198,10 @@ static const struct option_field options[] = {
        /* Server fields */
        {
                .id = 5000,
-               .name = "server.enabled",
+               .name = "server.disabled",
                .type = &gt_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",
@@ -342,7 +342,7 @@ handle_usage(struct option_field const *field, char *arg)
 static int
 handle_version(struct option_field const *field, char *arg)
 {
-       printf("0.0.1\n");
+       printf("0.0.1-beta\n");
        exit(0);
 }
 
@@ -453,7 +453,7 @@ set_default_values(void)
         * 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)
@@ -629,9 +629,9 @@ get_option_metadatas(void)
 }
 
 bool
-config_get_server_enabled(void)
+config_get_server_disabled(void)
 {
-       return rpki_config.server.enabled;
+       return rpki_config.server.disabled;
 }
 
 char const *
index f9d41e3c0beabb6263f10ad666de7d3320705b61..dd28cb2e957311cf99c84894e1906a8e7e1983b0 100644 (file)
@@ -14,7 +14,7 @@ int handle_flags_config(int , char **);
 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);
index fc7020538045265673dcdb4ab5c03677a1533a58..77f1c3c368247643996adff33154ee07d7af3dc2 100644 (file)
@@ -9,7 +9,6 @@
 #include "config.h"
 #include "extension.h"
 #include "log.h"
-#include "manifest.h"
 #include "nid.h"
 #include "str.h"
 #include "thread_var.h"
@@ -17,6 +16,7 @@
 #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. */
index 09d7764a9bada79116c733ce97775c0347752fc2..50160bbed5d72b74e766ddf94a044ff0456bcacf 100644 (file)
--- a/src/rpp.c
+++ b/src/rpp.c
@@ -18,7 +18,6 @@ struct rpp {
        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;
 
@@ -45,7 +44,7 @@ rpp_create(void)
                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);
@@ -72,7 +71,7 @@ rpp_refput(struct rpp *pp)
        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);
@@ -108,18 +107,17 @@ int
 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
@@ -152,7 +150,7 @@ rpp_crl(struct rpp *pp)
 {
        if (pp == NULL)
                return NULL;
-       if (!pp->crl_set)
+       if (pp->crl == NULL)
                return NULL;
        if (pp->crl_stack != NULL)
                return pp->crl_stack;
index 897e07f459b1b964fbdd79088355ca008f264800..53c374d767ba98e5b7b3eb8f2f7ab7609abe4696 100644 (file)
@@ -128,8 +128,6 @@ __perform_standalone_validation(struct roa_table **result)
        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;
@@ -301,11 +299,17 @@ vrps_update(bool *changed)
 
        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;
 }
index ca63af506361e171d6ee4499e75f094295e5ecbe..ba031ad147e7073aeb374cf5cf587c518bc1ad79 100644 (file)
@@ -100,6 +100,12 @@ pdu_load(int fd, struct rtr_request *request,
        }
 
        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;
index e05b35ad68ba3013a8603b7e857ed6a82a127d9b..f2073bbbf04b191ce8d7e27062f6e7bfabd56b95 100644 (file)
@@ -60,17 +60,18 @@ pdu_reader_init(struct pdu_reader *reader, int fd, unsigned char *buffer,
        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++;
@@ -83,7 +84,7 @@ int
 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])     );
@@ -97,7 +98,7 @@ int
 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)
@@ -242,7 +243,7 @@ int
 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;
index ffa74293efd1b3826fab788fad23f26010e5d8db..81d3f4faffa61d3434ab722ea3fe6389ba0e4590 100644 (file)
@@ -352,7 +352,7 @@ join_thread(pthread_t tid, void *arg)
 
 /*
  * 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.
  *
@@ -373,7 +373,7 @@ rtr_listen(void)
        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.",
index 6d0b0f696ee2e5b7a2a4c576db09b6f4217c0c54..7109705d5fd80a8ceb75d9060c281ebfb526cb5a 100644 (file)
@@ -195,7 +195,7 @@ static void
 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
@@ -206,7 +206,7 @@ clean_slurm_bgpsec(struct slurm_bgpsec *bgpsec)
        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
index 7a20e8ba52e9c468147834f39d45f76bee8ccf91..ea6b3cd200c7c9eb11e3dd3d3a8c12ef8793c5f5 100644 (file)
@@ -84,7 +84,7 @@ set_asn(json_t *object, bool is_assertion, uint32_t *result, uint8_t *flag,
 }
 
 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;
@@ -416,7 +416,7 @@ load_single_prefix(json_t *object, bool is_assertion)
        return 0;
 
 release_comment:
-       free((void *)result.comment);
+       free(result.comment);
        return error;
 }
 
@@ -536,7 +536,7 @@ load_single_bgpsec(json_t *object, bool is_assertion)
        return 0;
 
 release_comment:
-       free((void *)result.comment);
+       free(result.comment);
 release_router_key:
        free(result.router_public_key);
 release_ski:
index cb64f035d55e159cc9c7e724acb5f933aba93dcf..6be52e2c76ff3a88f6c34333cd381de285be1ba9 100644 (file)
@@ -17,7 +17,7 @@
 struct slurm_prefix {
        uint8_t         data_flag;
        struct vrp      vrp;
-       char const      *comment;
+       char            *comment;
 };
 
 struct slurm_bgpsec {
@@ -27,7 +27,7 @@ struct slurm_bgpsec {
        size_t          ski_len;
        unsigned char   *router_public_key;
        size_t          router_public_key_len;
-       char const      *comment;
+       char            *comment;
 };
 
 
index 9cff02c8caed05855038f9bc98ab99d8c2ed2271..d86011c0967ce9134b9db105e9c117420addae48 100644 (file)
@@ -25,11 +25,11 @@ check_PROGRAMS += line_file.test
 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
@@ -50,15 +50,8 @@ roa_table_test_LDADD = ${MY_LDADD}
 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}
@@ -66,17 +59,11 @@ 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
index af5ceec2e6fc6bcbb5e480b90341a876e024dd5c..a38a1bd9536a0c99ee1dd449e66ac4ea1acc5ea0 100644 (file)
@@ -34,6 +34,24 @@ v6addr2str2(struct in6_addr const *addr)
        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)
 {
@@ -78,15 +96,15 @@ config_get_slurm(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
index 61901702d5dde25089318e7068f43978b3791271..5f3e14b218313bc679bd22065305abcce1804437 100644 (file)
@@ -1,6 +1,8 @@
 #include <check.h>
 #include "object/tal.h"
 
+#include "address.c"
+
 static int iteration = 0;
 
 static void
index eb3de6ebebd0009d6ecfe848dba866a427ee363a..ab43ef22196f42b4e3f7903cdedd68d960b786bc 100644 (file)
@@ -2,7 +2,6 @@
 #include <stdbool.h>
 #include <stdlib.h>
 
-#include "address.c"
 #include "crypto/base64.c"
 #include "common.c"
 #include "file.c"
index 39a1459c82d9990c720d4c2454d92d95cea922c5..1b77f00fc5db20007085882e570018071fe03666 100644 (file)
@@ -1,8 +1,8 @@
 #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"
@@ -334,7 +338,7 @@ START_TEST(test_bad_session_id)
        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();
@@ -355,6 +359,58 @@ START_TEST(test_bad_session_id)
 }
 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;
@@ -368,6 +424,7 @@ Suite *pdu_suite(void)
 
        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);
index 19474952a9d0601ade919062163cc8b278d10e9b..849fcfbcd21ddf9f7d368174b4a0be04151a8494 100644 (file)
@@ -2,32 +2,76 @@
 #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
@@ -35,21 +79,26 @@ assert_pdu_header(struct pdu_header *header)
 {
        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);
@@ -156,7 +205,7 @@ START_TEST(test_error_report_from_stream)
        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,
@@ -167,14 +216,34 @@ START_TEST(test_error_report_from_stream)
        };
        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);
@@ -187,20 +256,20 @@ START_TEST(test_error_report_from_stream)
         * 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);
 }
index 8d84f38ac86ee5763307fc04d726e6375df683ab..c60d789bf13a05ec4060ce92604079b5b6b028a1 100644 (file)
@@ -5,7 +5,9 @@
 #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;
 }
@@ -56,34 +67,31 @@ test_read_string_fail(unsigned char *input, size_t length, int expected)
 
 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,
@@ -94,8 +102,8 @@ END_TEST
 
 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
 
@@ -116,21 +124,11 @@ writer_thread_cb(void *param_void)
        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);
@@ -190,6 +188,8 @@ test_massive_string(uint32_t return_length, uint32_t full_string_length)
        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;
 
@@ -216,9 +216,16 @@ test_massive_string(uint32_t return_length, uint32_t full_string_length)
                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. */
@@ -227,6 +234,7 @@ test_massive_string(uint32_t return_length, uint32_t full_string_length)
        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) {
@@ -245,55 +253,45 @@ START_TEST(read_string_massive)
        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
@@ -310,12 +308,10 @@ Suite *read_string_suite(void)
        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()");
index 299256f9eda270479ddb6509197560255847c5f2..39a2de3f324d6ee4c5e00ad89bcf22c9233beb73 100644 (file)
@@ -5,6 +5,75 @@
 #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;