]> git.ipfire.org Git - thirdparty/FORT-validator.git/log
thirdparty/FORT-validator.git
6 months agoIndex each cache node separately
Alberto Leiva Popper [Mon, 20 Jan 2025 17:37:58 +0000 (11:37 -0600)] 
Index each cache node separately

Background:

- Fort shouldn't lose the cache index when a signal interrupts it.
- Writing the index during the signal handler is not possible,
  because of the async-signal-safe requirement.
- Writing the index outside of the signal handler is seemingly not
  viable, because of the infelicities between the signal and
  multithreading APIs in C.

I haven't completely discarded the "dropping multithreading" option,
but since it seems disproportionate, I've been rethinking the index.

This commit scatters the index across several files, to minimize lost
information during a stopping signal. This will exacerbate the inode
problem, but that's temporary.

Reverts e0880f8eac3d35e576a2c1a2cb588424ab4b3e1b.

6 months agoTentatively add new logging level: "clutter"
Alberto Leiva Popper [Wed, 8 Jan 2025 19:57:02 +0000 (13:57 -0600)] 
Tentatively add new logging level: "clutter"

It's below "debug." Meant to hide several debugging messages that
inflate the log but haven't been useful for many years.

It's hardcoded to disabled for now, and I've half a mind to commit to
this.

7 months agoClear the cache after a crash
Alberto Leiva Popper [Fri, 6 Dec 2024 19:41:05 +0000 (16:41 -0300)] 
Clear the cache after a crash

There are many ways in which a mismatching cache index can cause erratic
behavior that's hard to detect. Since the index is written at the end of
the validation cycle, crashing at any point between a cache refresh and
the index write results in a misindexed cache.

Deleting the index after loading it seems to be a reliable way to force
Fort to reset the cache after a crash.

Terminating signals are still a problem, though.

7 months agoGeneral index.json review
Alberto Leiva Popper [Thu, 5 Dec 2024 15:24:01 +0000 (12:24 -0300)] 
General index.json review

Not much; just moving things around for peace of mind.

7 months agoIndex sequences properly
Alberto Leiva Popper [Thu, 5 Dec 2024 15:13:52 +0000 (12:13 -0300)] 
Index sequences properly

Postponed task from some previous refactor; the object was only
partially being serialized.

Fixes XXX-style TODO.

7 months agoFix random errors
Alberto Leiva Popper [Thu, 5 Dec 2024 12:44:56 +0000 (09:44 -0300)] 
Fix random errors

Not much to say. Testing some slightly dirtier inputs; these pipelines
were crashing or returning incorrectly.

8 months agoAlways pick most recent known manifest
Alberto Leiva Popper [Tue, 3 Dec 2024 19:58:10 +0000 (16:58 -0300)] 
Always pick most recent known manifest

Strict version.

8 months agoAlways pick most recent known manifest
Alberto Leiva Popper [Mon, 2 Dec 2024 21:11:45 +0000 (18:11 -0300)] 
Always pick most recent known manifest

Non-strict version.

Fixes new (still unnumbered) CVE.

8 months agoMakefile maintenance
Alberto Leiva Popper [Mon, 2 Dec 2024 17:15:39 +0000 (14:15 -0300)] 
Makefile maintenance

Triggered by fixing compilation in MacOS.

- Rename extension.h to ext.h; the former collides with Extension.h.
- Move _DEFAULT_SOURCE to the source; it's not widespread enough for
  Makefile.am.
- Add _DARWIN_C_SOURCE, needed by MacOS for timegm() and mkdtemp().
- Add -flto to unit test AM_CFLAGS. This minimizes superflous #includes
  and mocks needed, and will hopefully make them consistent across
  platforms.
- Delete _BSD_SOURCE; it seems orphaned. (Though see below.)

Works on Linux and Mac. Might have broken the BSDs; I can't test them
ATM.

8 months agoCache cleanup review
Alberto Leiva Popper [Thu, 14 Nov 2024 19:54:14 +0000 (13:54 -0600)] 
Cache cleanup review

Fixes several XXXs.

- Separate node->mtim into attempt_ts and success_ts.
  Because they're really two different timestamps; The former is meant
  for node expiration, the latter for HTTP IMS.
- Move removal of orphaned fallbacks to remove_abandoned().
  Because orphaned refreshes need the same logic.
- Added the (randomly missing) expiration threshold for orphans.

It's still missing the implementation of remove_orphaned_files(),
but I'm still weighting options, as it seems it's going to be an
expensive operation that's rarely going to do anything.

8 months agoSeparate rsync fallbacks from RRDP fallbacks
Alberto Leiva Popper [Wed, 13 Nov 2024 22:25:19 +0000 (16:25 -0600)] 
Separate rsync fallbacks from RRDP fallbacks

Both used to be indexed by caRepository, inducing possible collision.
RRDP fallbacks are now indexed by rkiNotify+caRepository, ensuring
they're caged separately.

8 months agoCommit TAs into cache fallback on success
Alberto Leiva Popper [Mon, 11 Nov 2024 21:06:14 +0000 (15:06 -0600)] 
Commit TAs into cache fallback on success

Forgot these during c7be17b62db6262e0bc9e33b7b9ad049b8563453.

8 months agoAdd thread safety to the new cache
Alberto Leiva Popper [Sat, 9 Nov 2024 01:00:05 +0000 (19:00 -0600)] 
Add thread safety to the new cache

The thread that handles the first task that needs repository A
refreshes A.

While the refresh happens, threads handling other tasks that also need
A postpone said tasks.

Such postponed tasks wake up when the refresh completes.

8 months agoRewrite the core loop and its threading
Alberto Leiva Popper [Tue, 5 Nov 2024 23:16:49 +0000 (17:16 -0600)] 
Rewrite the core loop and its threading

Decouples threads from TALs; threads claim RPPs now.

Aside from scaling better, this unclogs the way to several future
improvements.

9 months agoMove the rsync spawner to a separate process
Alberto Leiva Popper [Sat, 19 Oct 2024 00:18:00 +0000 (18:18 -0600)] 
Move the rsync spawner to a separate process

The fork()s (needed to spawn rsyncs) duplicate Fort's process.

Which is messy in a multithreaded program. Quoting the Linux man page:

> * The child process is created with a single thread—the one that
>   called fork(). The entire virtual address space of the parent is
>   replicated in the child, including the states of mutexes, condition
>   variables, and other pthreads objects. (...)
> * After a fork() in a multithreaded program, the child can safely call
>   only async-signal-safe functions (...) until such time as it calls
>   execve(2).

As far as I can tell, since the forked child was, in fact, careful to
only invoke async-signal-safe functions, this wasn't really a bug.
Still, it wasn't quality architecture either.

Moving the rsync spawner to a dedicated subprocess should stop the forks
from threatening to clash with the multithreading completely.

Relies on the new core loop design, so this won't work properly until
that's implemented.

9 months agoMove the rsync arg builder to the child pipeline
Alberto Leiva Popper [Thu, 17 Oct 2024 23:29:59 +0000 (17:29 -0600)] 
Move the rsync arg builder to the child pipeline

This was (annoyingly) outside because it used to allocate.
(The child is only allowed to call async-signal-safe functions.)

But

a) It doesn't allocate anymore.
b) The async-signal-safe constraint is going to die in a few refactors.

Incidentally deletes the argument echoer, since the arguments are not
variable anymore.

9 months agoRemove rsync & HTTP retries
Alberto Leiva Popper [Thu, 17 Oct 2024 16:44:23 +0000 (10:44 -0600)] 
Remove rsync & HTTP retries

Glad to ditch these. They'll be made redundant by the new threading.

9 months agoAtomize output files
Alberto Leiva Popper [Wed, 16 Oct 2024 19:43:42 +0000 (13:43 -0600)] 
Atomize output files

I feel like I need to relearn signals every time I have to interact with
them. Best get this done while the iron's hot.

1. The ROA file is first written as `<cache>/.roa`.
   The RK file is first written as `<cache>/.rk`.
2. When the validation run is done, `.roa` is renamed to `--output.roa`,
   and `.rk` becomes `--output.bgpsec`.
3. Most terminating signals unlink `.roa` and `.rk`.

Fixes #124.

9 months agoAdd lockfile to the cache
Alberto Leiva Popper [Wed, 16 Oct 2024 19:43:34 +0000 (13:43 -0600)] 
Add lockfile to the cache

To prevent other (well-behaved) instances from accidentally reading and
writing the same directory simultaneously.

Fixes #149.

9 months agoMove the signal code out of the logging module
Alberto Leiva Popper [Wed, 16 Oct 2024 19:28:09 +0000 (13:28 -0600)] 
Move the signal code out of the logging module

The sigaction() code was in logging because it was originally conceived
by the SIGSEGV stack trace printing hack. The SIGPIPE ignorer was also
incidentally moved there at some point, but it has never had anything
to do with logging.

And I'm going to catch more signals in the upcoming commits, so this
really needs to be formalized into its own module.

9 months agoMirror the previous commit on the read pipeline
Alberto Leiva Popper [Tue, 15 Oct 2024 17:24:09 +0000 (11:24 -0600)] 
Mirror the previous commit on the read pipeline

9 months agocache index: Allow NULL dlerr, mtim, session_id and serial
Alberto Leiva Popper [Mon, 14 Oct 2024 23:41:31 +0000 (17:41 -0600)] 
cache index: Allow NULL dlerr, mtim, session_id and serial

NULL dlerr can mean "no error", mtim isn't always set,
and session_id/serial do not exist in fallback.

9 months agoJoin cache.json and TAL metafiles into index.json
Alberto Leiva Popper [Mon, 14 Oct 2024 23:27:41 +0000 (17:27 -0600)] 
Join cache.json and TAL metafiles into index.json

Per design 5, there's only one metafile now, and it's named
"index.json".

cache.json was just a single field that could be sensibly moved to the
index.

9 months agoMove stuff between cache_setup() and cache_prepare()
Alberto Leiva Popper [Mon, 14 Oct 2024 23:07:49 +0000 (17:07 -0600)] 
Move stuff between cache_setup() and cache_prepare()

The former is intended for stuff that needs to be done once,
the latter sets up a single validation cycle.

9 months agoDo `rm -r cache/*` instead of `rm -r cache` on reset
Alberto Leiva Popper [Mon, 14 Oct 2024 22:33:59 +0000 (16:33 -0600)] 
Do `rm -r cache/*` instead of `rm -r cache` on reset

Skips a pointless warning on the logs when dropping an incompatible
cache:

> Cannot delete .: Invalid argument

9 months agoAttempt to mkdir the cache before cd'ing into it
Alberto Leiva Popper [Mon, 14 Oct 2024 22:20:45 +0000 (16:20 -0600)] 
Attempt to mkdir the cache before cd'ing into it

Probably not very useful outside of testing environments because of
permissions.

9 months agoMove write_simple_file() to file.c
Alberto Leiva Popper [Mon, 14 Oct 2024 21:25:33 +0000 (15:25 -0600)] 
Move write_simple_file() to file.c

Was too similar to file_write_full(), so merged.

9 months agoRemove mkdir_p()
Alberto Leiva Popper [Tue, 8 Oct 2024 23:14:56 +0000 (17:14 -0600)] 
Remove mkdir_p()

It induced too many redundant mkdir() and stat() system calls.

It's now best to use mkdir() directly, since the cache structure no
longer involves long and pointless directory chains.

Incidentally fixes a missing mkdir("cache/fallback"), which was
preventing the cache from backing up any valid RPPs.

9 months agoRemove the path builder
Alberto Leiva Popper [Tue, 8 Oct 2024 21:11:24 +0000 (15:11 -0600)] 
Remove the path builder

This has become overkill since design 5 and chdir() trivialized cache
pathing.

9 months agocd to cache directory instead of prefixing every path
Alberto Leiva Popper [Mon, 7 Oct 2024 22:00:35 +0000 (16:00 -0600)] 
cd to cache directory instead of prefixing every path

Reduces busywork, memory usage and allows the cache to be moved.

9 months agoUnify test suite function names
Alberto Leiva Popper [Mon, 7 Oct 2024 22:00:14 +0000 (16:00 -0600)] 
Unify test suite function names

It seems I always forget to update these during copy-pastes,
so most of them were misnamed.

9 months agoNew cache design
Alberto Leiva Popper [Mon, 7 Oct 2024 21:58:23 +0000 (15:58 -0600)] 
New cache design

For #82.

It seems I'm finally done making dramatic wide-reaching changes to the
codebase. There's still plenty to add and test, but I would like to
start pushing atomic commits from now on.

This is a squashed version of development brach "issue82". It includes
a few merges with main.

```
cache/
    rsync/              # rsync refresh
        0/              # rsync module: rsync://a.b.c/mod1
            rpp1/       # Repository Publication Point 1
                d.mft
                d.crl
                d1.roa
            rpp2/
                e.mft
                e.crl
            ta.cer      # Trust Anchor
        1/              # rsync module: rsync://a.b.c/mod2
            ...
        2/              # rsync module: rsync://x.y.z/mod1
            ...
    https/              # HTTPS refresh
        0               # https://a.b.c/repo/ta.cer
        1               # https://x.y.z/repo/ta.cer
    rrdp/               # RRDP refresh
        0/              # https://m.n.o/notification.xml
            0           # rsync://m.n.o/mod1/rpp1/a.mft
            1           # rsync://m.n.o/mod1/rpp1/b.crl
            2           # rsync://m.n.o/mod1/rpp2/c.mft
            3           # rsync://m.n.o/mod1/rpp2/d.cer
        1/              # https://p.q.r/notification.xml
            ...
    fallback/           # Committed RPPs
        0/              # Fallback of rsync://a.b.c/mod1/rpp1
            0           # Hard link: cache/rsync/0/rpp1/d.mft
            1           # Hard link: cache/rsync/0/rpp1/d.crl
            2           # rsync://a.b.c/mod1/rpp1/d2.roa
                        # (Unique because of refresh)
        1               # Hard link: cache/https/0
        2/              # Fallback of m.n.o's rsync://m.n.o/mod1/rpp1
            0           # Hard link: cache/rrdp/0/0
            1           # Hard link: cache/rrdp/0/1
    index.json          # URL/path mappings and some metadata
```

- `cache/rsync`, `cache/https` and `cache/rrdp` contain "refreshes"
  (the exact latest files according to the servers). RRDP withdraws are
  honored, and rsyncs run without --compare-dest.
- "Refresh" files marked as valid are backed up in `cache/fallback`
  at the end of each validation cycle.
- Validation first tests fallback+refresh. (If a file exists in both,
  refresh wins.) If that fails, it retries with fallback only.
- The index is not a tree; everything is caged in numbered directories
  and indexed by exact URL, to prevent file overriding by URL hacking.

There's also a `cache/tmp` directory, where Fort temporarily dumps
notifications, snapshots and deltas. This directory will be removed
once #127 is fixed.

13 months agoRename "rpki_uri" into "cache_mapping"
Alberto Leiva Popper [Thu, 6 Jun 2024 21:54:57 +0000 (15:54 -0600)] 
Rename "rpki_uri" into "cache_mapping"

Helps visualize where I'm headed.

13 months agoRemove TAL isolation from the cache
Alberto Leiva Popper [Thu, 6 Jun 2024 21:53:12 +0000 (15:53 -0600)] 
Remove TAL isolation from the cache

It doesn't match the new design.

13 months agoMerge branch 'main' into issue82
Alberto Leiva Popper [Wed, 5 Jun 2024 18:53:38 +0000 (12:53 -0600)] 
Merge branch 'main' into issue82

14 months agoFix relax_ng_log_str_err() signature for old libxml2 versions
Alberto Leiva Popper [Mon, 3 Jun 2024 22:48:15 +0000 (16:48 -0600)] 
Fix relax_ng_log_str_err() signature for old libxml2 versions

Pull request #137 fixes relax_ng_log_str_err()'s argument list for
libxml2 2.12 and above, but breaks it for libxml2 2.11 and below.

14 months agoSimplify XML reader error handler 137/head
Lucio Sauer [Sun, 2 Jun 2024 23:28:35 +0000 (01:28 +0200)] 
Simplify XML reader error handler

No need to check if ptr[strlen(ptr) - 1] is '\n' because because C
strings always end with a null-byte.

14 months agoFix build failure with GCC 14 due to -Wincompatible-pointer-types
Lucio Sauer [Sun, 2 Jun 2024 23:26:31 +0000 (01:26 +0200)] 
Fix build failure with GCC 14 due to -Wincompatible-pointer-types

Reported downstream at https://bugs.gentoo.org/928331

14 months agoUpdate APNIC TALs
Alberto Leiva Popper [Thu, 30 May 2024 18:11:27 +0000 (12:11 -0600)] 
Update APNIC TALs

Their "current" TALs are not the ideal ones. Switch to the ones that
feature HTTP.

Spawned by #133.

14 months agoUpdate Docker
Alberto Leiva Popper [Sat, 25 May 2024 16:15:10 +0000 (10:15 -0600)] 
Update Docker

14 months agoFinal protocolary updates for release 1.6.2 1.6.2
Alberto Leiva Popper [Fri, 24 May 2024 20:19:48 +0000 (14:19 -0600)] 
Final protocolary updates for release 1.6.2

14 months agoFix unit tests
Alberto Leiva Popper [Fri, 24 May 2024 18:59:15 +0000 (12:59 -0600)] 
Fix unit tests

14 months agoRestore the "now you can connect your routers" WRN
Alberto Leiva Popper [Fri, 24 May 2024 18:46:41 +0000 (12:46 -0600)] 
Restore the "now you can connect your routers" WRN

Requested by #133. Temporal fix.

14 months agoFix most of the -Wnon-pointer-null violations
Alberto Leiva Popper [Thu, 23 May 2024 22:16:15 +0000 (16:16 -0600)] 
Fix most of the -Wnon-pointer-null violations

The cgcc review no longer needs -Wno-non-pointer-null.

14 months agoMirror 1165270e73508b9fb3dfdc0294a5926d56679c75 in other d2i's
Alberto Leiva Popper [Thu, 23 May 2024 22:15:37 +0000 (16:15 -0600)] 
Mirror 1165270e73508b9fb3dfdc0294a5926d56679c75 in other d2i's

Also, fix memory leak in signed_data.c.

14 months agoAdd documentation for --mode=print
Alberto Leiva Popper [Thu, 23 May 2024 20:28:58 +0000 (14:28 -0600)] 
Add documentation for --mode=print

14 months agoChange --server.address default
Alberto Leiva Popper [Thu, 23 May 2024 19:05:32 +0000 (13:05 -0600)] 
Change --server.address default

The old default had been causing mayhem on Linux since
202e0fe34dc3c8dcb1a0ad12faa7f4d5a7c91b2d.

The new default is OS-sensitive, and binds the socket to all available
IPv4 and IPv6 addresses.

14 months agoStop using BIO_read_ex()
Alberto Leiva Popper [Wed, 22 May 2024 01:50:57 +0000 (19:50 -0600)] 
Stop using BIO_read_ex()

It's not LibreSSL-compatible.

14 months agoStraighten up #includes
Alberto Leiva Popper [Wed, 22 May 2024 01:25:33 +0000 (19:25 -0600)] 
Straighten up #includes

Also, remove cyclical #includes, to further automate this.

14 months agoAdd roadmap to the site
Alberto Leiva Popper [Fri, 17 May 2024 19:04:22 +0000 (13:04 -0600)] 
Add roadmap to the site

Still not referenced by the index; needs discussion still.

14 months agoMerge branch 'carlosm3011-main'
Alberto Leiva Popper [Thu, 16 May 2024 23:09:15 +0000 (17:09 -0600)] 
Merge branch 'carlosm3011-main'

14 months agoMerge some duplicate code
Alberto Leiva Popper [Thu, 16 May 2024 18:42:31 +0000 (12:42 -0600)] 
Merge some duplicate code

New rule: BIOs no longer allowed in ASN1 JSON functions outside of
libcrypto_util.c.

14 months agoFIX TODO: not validating @alg
Alberto Leiva Popper [Thu, 16 May 2024 18:42:12 +0000 (12:42 -0600)] 
FIX TODO: not validating @alg

False alarm; the getter was just redundant. @alg was beind validated at
validate_certificate_public_key_algorithm().

14 months agoFix TODO: Use extension_metadata.destructor more
Alberto Leiva Popper [Wed, 15 May 2024 23:23:46 +0000 (17:23 -0600)] 
Fix TODO: Use extension_metadata.destructor more

This frees the extension callbacks from having to decode and free the
extensions themselves.

14 months agoFix TODO: Choose a X509V3_EXT_print() flag
Alberto Leiva Popper [Wed, 15 May 2024 23:22:41 +0000 (17:22 -0600)] 
Fix TODO: Choose a X509V3_EXT_print() flag

X509V3_EXT_print() was being summoned to print extensions unrelated to
RPKI. The TODO wanted me to pick a suitable flag for extensions unknown
even to libcrypto.

For reference, this is how X509V3_EXT_print() prints an AIA, as a known
extension:

    CA Issuers - URI:rsync://rpki.ripe.net/repository/aca/KpSo3VVK5wEHIJnHC2QHVV3d5mk.cer

This is how X509V3_EXT_print() prints the same AIA, as an unknown
extension, X509V3_EXT_PARSE_UNKNOWN enabled:

        0:d=0  hl=2 l=  82 cons: SEQUENCE
        2:d=1  hl=2 l=  80 cons: SEQUENCE
        4:d=2  hl=2 l=   8 prim: OBJECT            :CA Issuers
       14:d=2  hl=2 l=  68 prim: cont [ 6 ]

This is how X509V3_EXT_print() prints the same AIA, as an unknown
extension, X509V3_EXT_DUMP_UNKNOWN enabled:

    0000 - 30 52 30 50 06 08 2b 06-01 05 05 07 30 02 86 44   0R0P..+.....0..D
    0010 - 72 73 79 6e 63 3a 2f 2f-72 70 6b 69 2e 72 69 70   rsync://rpki.rip
    0020 - 65 2e 6e 65 74 2f 72 65-70 6f 73 69 74 6f 72 79   e.net/repository
    0030 - 2f 61 63 61 2f 4b 70 53-6f 33 56 56 4b 35 77 45   /aca/KpSo3VVK5wE
    0040 - 48 49 4a 6e 48 43 32 51-48 56 56 33 64 35 6d 6b   HIJnHC2QHVV3d5mk
    0050 - 2e 63 65 72                                       .cer

Eh. These are good and all, but they mess up the JSON, so I decided to
dump these as octet strings instead:

        3052305006082b0601050507300286447273796e633a2f2f72706b692e726970
        652e6e65742f7265706f7369746f72792f6163612f4b70536f3356564b357745
        48494a6e484332514856563364356d6b2e636572

14 months agoMerge some duplicate code
Alberto Leiva Popper [Wed, 15 May 2024 21:08:56 +0000 (15:08 -0600)] 
Merge some duplicate code

14 months agoPrivatize the asn_codec_ctx_t into the ASN.1 code
Alberto Leiva Popper [Wed, 15 May 2024 18:05:11 +0000 (12:05 -0600)] 
Privatize the asn_codec_ctx_t into the ASN.1 code

Fort has `--asn1-decode-max-stack`, a global configuration option for
the maximum stack usage. So there's no need to pass this as an argument.

14 months agoRemove the DER validator
Alberto Leiva Popper [Wed, 15 May 2024 01:11:19 +0000 (19:11 -0600)] 
Remove the DER validator

rfc6488#3.1.l states we need to check "the signed object is DER
encoded." But that's not what this code was doing.

First, the validation was only kicking in specifically during the
decoding of the ContentInfo, which is just the outermost layer of the
signed object.

Second, the validation was incorrect. This seems to be the intended
algorithm in pseudocode:

boolean is_der_encoded(original_bytes):
der_bytes = der_encode(ber_decode(original_bytes));
return (original_bytes equal der_bytes);

This is what the code was actually doing:

boolean is_der_encoded(original_bytes):
der_bytes = der_encode(ber_decode(original_bytes));
return (original_bytes.length equals der_bytes.length);

These two quirks made the validation mostly a no-op.

There's also the issue that this implementation seems inefficient,
especially since Fort doesn't need to DER-encode anywhere else. By
checking the encoding while parsing, I would save a lot of memory
in addition to being able to delete that mess of encoding functions.

But I'm going to have to push that to the future. This is growing more
ambitious than I can afford during a release review, and given that the
code wasn't really doing anything productive in the first place, I'm not
losing much by simply axing it for now.

14 months agoGeneral pre-release review and testing
Alberto Leiva Popper [Tue, 14 May 2024 23:51:59 +0000 (17:51 -0600)] 
General pre-release review and testing

- Employ libssl's OID parsing rather than implement it from scratch.
- Rename `struct signed_object_args` to `struct ee_cert`, since it's
  just a bunch of EE certificate data.
- Remove `struct signed_data`, because it wasn't actually contributing
  anything.

14 months agoSpread error messages in --mode=print's failure paths
Alberto Leiva Popper [Fri, 10 May 2024 23:44:36 +0000 (17:44 -0600)] 
Spread error messages in --mode=print's failure paths

They're probably not very helpful themselves, but the stack traces
might serve as an admittedly inelegant way to infer the xpath to the
problem.

Otherwise, this could only be fixed by switching to a different JSON
library. But that's a problem for another decade.

14 months agoAutomatically download if file is an rsync URL
Alberto Leiva Popper [Fri, 10 May 2024 21:05:30 +0000 (15:05 -0600)] 
Automatically download if file is an rsync URL

rsync cannot download into standard output... which means rsync'd files
cannot be elegantly piped as standard output to --mode=print. So either
the rsync has to be done manually by the user... or --mode=print has to
do it internally by itself.

And looking at the code that resulted... I now wish I had gone with the
former option. Because of the long overdue cache refactors, the user
needs to include --tal for this rsync to be compatible with the cache.
This sucks.

As a workaround, Fort will rsync into /tmp if --tal and/or --local-cache
aren't supplied:

$ fort --mode=print \
--validation-log.enabled \
--validation-log.level debug \
rsync://a.b.c/d/CRL.crl
...
May 10 13:32:44 DBG [Validation]: Executing rsync:
May 10 13:32:44 DBG [Validation]:     rsync
May 10 13:32:44 DBG [Validation]:     ...
May 10 13:32:44 DBG [Validation]:     rsync://a.b.c/d/CRL.crl
May 10 13:32:44 DBG [Validation]:     /tmp/fort-Q7tMhz/CRL.crl
...
{
"tbsCertList": {
"version": 1,
...

14 months agoPatch TODO: Stop accessing GENERAL_NAME attributes directly
Alberto Leiva Popper [Thu, 9 May 2024 23:49:10 +0000 (17:49 -0600)] 
Patch TODO: Stop accessing GENERAL_NAME attributes directly

14 months agoPatch TODO: Always release decoded BER, even on error
Alberto Leiva Popper [Thu, 9 May 2024 23:48:42 +0000 (17:48 -0600)] 
Patch TODO: Always release decoded BER, even on error

14 months agoReindent
Alberto Leiva Popper [Thu, 9 May 2024 23:44:03 +0000 (17:44 -0600)] 
Reindent

Reduce 80 column limit violations in the ASN1 code.

14 months agoPatch bad array indexing
Alberto Leiva Popper [Thu, 9 May 2024 18:25:32 +0000 (12:25 -0600)] 
Patch bad array indexing

14 months agoReview jsonification
Alberto Leiva Popper [Thu, 9 May 2024 18:18:22 +0000 (12:18 -0600)] 
Review jsonification

They want Fort to jsonify more faithfully to the ASN1 grammar,
rather than human-friendlier.

A --human-readable flag wouldn't go amiss, but I should probably waint
until someone requests it.

14 months agoAdd sequence BIO
Alberto Leiva Popper [Wed, 8 May 2024 16:48:09 +0000 (10:48 -0600)] 
Add sequence BIO

It's a BIO that concatenates two other BIOs when reading.
Needed so the file parser can read the file header twice, without using
rewind(3).

(Which can't be used while piping, as it turns out.)

This allows printing a subfile from a delta or snapshot:

$ xmlstarlet sel -t -v "//_:publish[2]" delta.xml |
base64 --decode |
fort --mode=print

14 months agoPatch memory leaks and bad memory accesses
Alberto Leiva Popper [Wed, 8 May 2024 15:42:53 +0000 (09:42 -0600)] 
Patch memory leaks and bad memory accesses

14 months agoAllow --mode=print to read file from stdin
Alberto Leiva Popper [Mon, 6 May 2024 22:10:14 +0000 (16:10 -0600)] 
Allow --mode=print to read file from stdin

Either works:

$ fort --mode=print   < cert.cer
$ fort --mode=print - < cert.cer

Progress for #122.

14 months agoFix compilation in OpenSSL < 3 and LibreSSL
Alberto Leiva Popper [Mon, 6 May 2024 21:54:16 +0000 (15:54 -0600)] 
Fix compilation in OpenSSL < 3 and LibreSSL

14 months agoPurge early output files writability validations
Alberto Leiva Popper [Mon, 6 May 2024 19:24:22 +0000 (13:24 -0600)] 
Purge early output files writability validations

Fort used to clear the --output.roa and --output.bgpsec files to make
sure they were writable, during early validations.

So this is why the files spent so much time being empty! This was not
acceptable. It didn't even guarantee the files would still remain
writable by the time Fort needed to properly populate them.

Adjacent progress for #124.

14 months agoRemove file mode hardcode from file_write
Alberto Leiva Popper [Mon, 6 May 2024 19:19:18 +0000 (13:19 -0600)] 
Remove file mode hardcode from file_write

This function was always including the binary flag ("b") during
fopen(2), which seems to be inappropriate for the --output.roa and
--output.bgpsec files.

Well, the Unixes don't do anything with this flag, so this is more of a
semantic fine-tune than a bugfix.

15 months agoAdd --file-type
Alberto Leiva Popper [Tue, 30 Apr 2024 21:43:41 +0000 (15:43 -0600)] 
Add --file-type

Allows the user to bypass the file type guesser. For example, to force
the ROA parser:

$ fort --mode=print --file-type roa abcd.bin

Progress for #122.

15 months agoImprove the file type detector for --mode=print
Alberto Leiva Popper [Mon, 29 Apr 2024 21:52:45 +0000 (15:52 -0600)] 
Improve the file type detector for --mode=print

Guesses the file type from the ASN1 shape.

Progress for #122.

15 months agoAdd CRLs and their extensions to --mode=print
Alberto Leiva Popper [Mon, 29 Apr 2024 20:56:22 +0000 (14:56 -0600)] 
Add CRLs and their extensions to --mode=print

Progress for #122.

15 months agoAdd certificate extensions to --mode=print
Alberto Leiva Popper [Thu, 25 Apr 2024 00:00:58 +0000 (18:00 -0600)] 
Add certificate extensions to --mode=print

Hmm. I think this bumps the minimum required LibreSSL to v3.5.0.

Progress for #122.

15 months agoAdd certificates to --mode=print
Alberto Leiva Popper [Sun, 21 Apr 2024 19:27:25 +0000 (13:27 -0600)] 
Add certificates to --mode=print

This includes .cer files, as well as "certificates" signed object
fields.

Known caveat: The .SignedData.certificates[*].tbsCertificate.extensions
are pretty ugly still.

Progress for #122.

15 months agoAdd --mode=print
Alberto Leiva Popper [Sun, 21 Apr 2024 19:15:07 +0000 (13:15 -0600)] 
Add --mode=print

Prints an RPKI file in standard output. Only the asn1c signed objects
(ROAs, Manifests and Ghostbusters) are implemented right now.

In particular, it doesn't jsonify certificates nor CRLs yet, which
includes the "certificate" field of the signed objects.

Progress for #122.

15 months agoASN.1: Remove random_fills
Alberto Leiva Popper [Sun, 21 Apr 2024 19:14:02 +0000 (13:14 -0600)] 
ASN.1: Remove random_fills

Unused code. Don't know what it's for.

15 months agoASN.1: Remove C++ glue
Alberto Leiva Popper [Sun, 21 Apr 2024 19:13:40 +0000 (13:13 -0600)] 
ASN.1: Remove C++ glue

I might regret this one day.

15 months agoASN.1: Remove the XER decoder
Alberto Leiva Popper [Sun, 21 Apr 2024 19:12:59 +0000 (13:12 -0600)] 
ASN.1: Remove the XER decoder

Unused code. Been wanting to do this for years.

15 months agoASN.1: Remove the OER and PER encoders and decoders
Alberto Leiva Popper [Sun, 21 Apr 2024 19:11:45 +0000 (13:11 -0600)] 
ASN.1: Remove the OER and PER encoders and decoders

Unused code. Been wanting to do this for years.

15 months agoagregada rtrlib en la imagen de docker 111/head
Carlos Martinez [Thu, 18 Apr 2024 11:28:42 +0000 (11:28 +0000)] 
agregada rtrlib en la imagen de docker

16 months agoFix date parsing from TAL cachefiles
Alberto Leiva Popper [Fri, 15 Mar 2024 22:44:07 +0000 (16:44 -0600)] 
Fix date parsing from TAL cachefiles

The code was writing dates in Zulu format, which was fine. But then, to
read them back, it was loading them with mktime(), which is a local
timezone function. The effects of this bug depend on the time zone.
Files would expire from the cache up to 12 hours too early (UTC+) or
late (UTC-), or be updated up to 12 hours late (UTC-). (There's no such
thing as "updating too early" in this context, since Fort cannot refresh
before the present.)

I fixed this by swapping mktime() for timegm(), which is not great,
because the latter is still a nonstandard function. But it'll have to
do, because the other options are worse.

Below is my thought process on timegm() and the other options:

==================================================

Problem:

1. I want to store timestamps as human-readable strings.
2. Converting a timestamp to Zulu string is trivial: time_t ->
   gmtime_r() -> struct tm (GMT) -> strftime() -> char*.
3. But converting a string to timestamp relies on timegm(), which is
   nonstandard: char* -> strptime() -> struct tm (GMT) -> timegm() ->
   time_t.

Brainstorm:

1. Store the dates in local time.

Hideous option, but not ENTIRELY insane.

Storing in local time will render the dates up to 24 hours off, I think.
But this only happens when the cache changes timezone, which isn't
really often.

But it's still pretty clumsy, and also not future-proof, as new date
fields would have to be constrained by the same limitation.

2/10 at best.

2. Ditch time_t, use struct tm in UTC for everything.

So I would rely on gmtime_r() only to get out of time_t, and never need
timegm() for anything.

Comparing field by field would be a pain, but it's interesting to note
that Fort is actually already doing it somewhere: tm_cmp(). I guess I
have to admire the audaciousness of past me.

What mainly scares me is that mktime() seems to be the only standard
function that is contractually obligated to normalize the tm, which
means I would have to keep mktime()ing every time I need to compare
them.

And mktime() is... a local time function. Probably wouldn't actually
work.

4/10. I hate this API.

3. Bite the bullet: Go modern POSIX; assume time_t is integer seconds
   since the 1970 epoch.

I'm fantasizing about an early environment assertion that checks the
gmtime_r() for a known time_t, that shows people the door if the
implementation isn't sane. Would work even in POSIX-adjacent systems
like most Linuxes.

This would have other benefits, like the ability to ditch difftime(),
and perform arithmetic operations on time_t's.

All the officially supported platforms get this aspect of POSIX right,
so what's stopping me?

Well, it would mean I would have to store the date as a seconds-since-
epoch integer, which is not as human-friendly and defeats the whole
point of the JSON format.

And yet... this feels so right, I might end up doing it even regardless
of the JSON data type and timegm().

But not today. 7/10.

4. Bite the bullet: Use timegm().

Interesting. timegm() might be added to C23:

> Changes integrated into the latest working draft of C23 are listed
> below.
> (...)
> - Add timegm() function in <time.h> to convert time structure into
> calendar time value - similar to function in glibc and musl libraries.

https://en.wikipedia.org/wiki/C23_(C_standard_revision)

So this has some probability of not needing future tweaking. Also, it's
very clean. (Except for the feature test macros.)

8/10.

16 months agoReject HTTP redirects to different origins draft-spaghetti-sidrops-rrdp-same-origin
Alberto Leiva Popper [Mon, 11 Mar 2024 20:22:38 +0000 (14:22 -0600)] 
Reject HTTP redirects to different origins

Prevents malicious RRDP servers from wasting other servers' bandwidth.

Second half of draft-spaghetti-sidrops-rrdp-same-origin-00.

Thanks to Job Snijders for reporting this.

16 months agoForce RRDP files to be hosted by the same origin
Alberto Leiva Popper [Mon, 11 Mar 2024 20:22:26 +0000 (14:22 -0600)] 
Force RRDP files to be hosted by the same origin

Reject RRDP snapshot and deltas if they're not hosted in the same origin
as the notification. Prevents malicious notifications from wasting other
servers' bandwidth.

First half of draft-spaghetti-sidrops-rrdp-same-origin-00.

Thanks to Job Snijders for reporting this.

16 months agoMisc. RRDP Review draft-spaghetti-sidrops-rrdp-desynchronization
Alberto Leiva Popper [Mon, 11 Mar 2024 20:22:09 +0000 (14:22 -0600)] 
Misc. RRDP Review

Resove FIXMEs, add some comments and unit tests.

17 months agoFinally, implement draft-spaghetti-sidrops-rrdp-desynchronization-00
Alberto Leiva Popper [Mon, 4 Mar 2024 01:50:05 +0000 (19:50 -0600)] 
Finally, implement draft-spaghetti-sidrops-rrdp-desynchronization-00

- Remember old delta hashes.
- If one of the delta hashes changes in the notification, the session
  needs to be re-snapshot'd, even if the session ID and serial seem
  consistent.

17 months agoAdd delta threshold configuration option
Alberto Leiva Popper [Mon, 4 Mar 2024 01:49:59 +0000 (19:49 -0600)] 
Add delta threshold configuration option

This was in the tweakables wishlist. Previously hardcoded as 64.

It had to skip the line because it's needed by the upcoming session
desync commit.

17 months agoNormalize both URLs and local paths
Alberto Leiva Popper [Mon, 4 Mar 2024 01:49:20 +0000 (19:49 -0600)] 
Normalize both URLs and local paths

("Normalization" = collapsing `.` and `..`)

Before, only local paths were being normalized. This was because, by
some twisted logic, I was under the impression that `https://a.b.c/d`
and `https://a.b.c/d/.` are technically supposed to be different
identifiers. My recent visit to RFC3986 disproved this.

But regardless of what the standards say, it doesn't make sense to treat
those URLs differently in the context of RP validation. They will be
cached into the same directory.

Not that this aspect of the code used to be incorrect, to the best of
my knowledge. Fort needs normalization for proper pre-download
identification (which in turn is needed to prevent a file from being
downloaded twice during the same iteration). Old code used to identify
by local path, and the upcoming session desync commit will need to index
by remote path. Hence the need for this change.

17 months agoAdd several values to uri_type
Alberto Leiva Popper [Fri, 1 Mar 2024 21:25:54 +0000 (15:25 -0600)] 
Add several values to uri_type

In the upcoming commits, the cache is going to need to start managing
the notifications differently from the other downloadables, including
snapshots and deltas.

The logic used to differentiate the different objects from each other
was getting convoluted, and had been naturally converging into the URI
object since the 1.6.0 refactors, IIRC.

So stop beating around the bush and commit to this design. Store the
type in the URI object, and add several values to the uri_type enum.

17 months agoConvert RRDP XML strings to char *
Alberto Leiva Popper [Sat, 24 Feb 2024 01:20:02 +0000 (19:20 -0600)] 
Convert RRDP XML strings to char *

To prevent extra allocations and copies, strings in the RRDP module used
to be stored as `xmlChar *`s. This optimization doesn't hold water now
that I'm planning to also convert them to JSON.

17 months agoRRDP XML strings review
Alberto Leiva Popper [Sat, 24 Feb 2024 01:19:49 +0000 (19:19 -0600)] 
RRDP XML strings review

Not much to report on this one. It seemed the code was casting string
types back and forth too carelessly, but it turns out its assumptions
are agreeable.

In particular, I got scared by what appeared to be a missing printable
ASCII validation. But no; libxml2 takes care of it, thanks to the XML
grammar.

So what was really missing was a comment explaining the logic, so I
don't have to dig it up again. And some unit tests to preserve the
guarantees.

There are other validations I'm not so sure about, but I decided to
leave them out of the scope of this commit.

17 months agoRewrite the base64 decoder
Alberto Leiva Popper [Sat, 24 Feb 2024 01:19:34 +0000 (19:19 -0600)] 
Rewrite the base64 decoder

The old decoding was done using libcrypto's BIO API, even though the
code didn't need to perform any stream chaining. (Which seems to be the
whole point.)

Trying to figure out why it wasn't properly erroring on invalid base64,
I eventually realized I could dramatically simplify everything by
shifting the API layer. I'm now using `EVP_DecodeUpdate()` and friends.
It's so much cleaner and more correct now; it's incredible.

This had a cascade effect. The complexity of the base64.h API also
collapsed, which resulted in massive refactors on the callers.

Also adds some unit tests for base64 and TAL.

17 months agoModernize the hash module
Alberto Leiva Popper [Sat, 24 Feb 2024 01:19:18 +0000 (19:19 -0600)] 
Modernize the hash module

It seems nowadays libcrypto wants us to

- perform "explicit [algorithm] fetching,"
- cache algorithms to improve performance,
- and stop hardcoding algorithms in the code (which largely doesn't
  really apply in our RFC-bound situation).

https://www.openssl.org/docs/man3.0/man7/crypto.html#ALGORITHM-FETCHING

So fetch explicitely, cache algorithms and try to keep hardcoding at a
minimum.

Also, the code was seemingly unaware that hash size depends on
algorithm, so this was often validated weakly.

17 months agoFix bad usage of strtol()
Alberto Leiva Popper [Sat, 24 Feb 2024 01:18:55 +0000 (19:18 -0600)] 
Fix bad usage of strtol()

Someone didn't RTFM.

1. Error code wasn't being catched.
2. Second argument was NULL, so the caller had no way of knowing
   whether the string was fully consumed.
2. The code wasn't making sure the input was a clean hex string.
3. The input string wasn't NULL-terminated.

In the end, I ditched strtol(). It's too dangerous and cluttered for
this purpose.

17 months agoMerge branch 'job-main'
Alberto Leiva Popper [Fri, 23 Feb 2024 16:11:41 +0000 (10:11 -0600)] 
Merge branch 'job-main'

17 months agoUpdate comment 109/head
Job Snijders [Fri, 23 Feb 2024 12:59:54 +0000 (12:59 +0000)] 
Update comment

At this point in time I'm not aware of specific differences between
LibreSSL and OpenSSL in relationship to RFC 6487.

17 months agoUpdate comment
Job Snijders [Fri, 23 Feb 2024 12:51:35 +0000 (12:51 +0000)] 
Update comment

17 months agoWarn if server.address has more than one wildcard
Alberto Leiva Popper [Thu, 8 Feb 2024 21:58:25 +0000 (15:58 -0600)] 
Warn if server.address has more than one wildcard

Consider the following three definitions of server.address:

[a] "address": [ "0.0.0.0" ]
[b] "address": [ "::" ]
[c] "address": [ "0.0.0.0", "::" ]

We expect [a] to bind the socket to any IPv4 address,
[b] to bind the socket to any IPv6 address,
and [c] to bind the socket to any IPv4 and IPv6 address.

Right? The BSDs work that way.

But Linux doesn't. For Linux,

[a] binds to any IPv4 address,
[b] binds to any IPv4 and IPv6 address,
and [c] is an error.

But I don't want to override the behavior because some admins are
probably used to it:

linux$ nc -6lknv :: 7890
Listening on :: 7890
Connection received on ::1 52814
Hello from IPv6!
Connection received on ::ffff:127.0.0.1 55456
Hello from IPv4!

Instead, let's print a warning.

Thanks to Benjamim Pinheiro for reporting this quirk.