Re: rpki-client: add ASPA profile-10 support

2022-08-13 Thread Theo Buehler
On Sat, Aug 13, 2022 at 01:06:38AM +, Job Snijders wrote:
> Dear all,
> 
> The below changeset extends rpki-client(8) to validate and emit
> Autonomous System Provider Authorizations (ASPAs) in JSON format for
> consumption in other routing stacks.
> 
> The ASPA CMS protected content type is specified here:
> https://datatracker.ietf.org/doc/html/draft-ietf-sidrops-aspa-profile
> 
> How to verify BGP UPDATES using ASPA objects is described here:
> https://datatracker.ietf.org/doc/html/draft-ietf-sidrops-aspa-verification
> (Note: aspa-profile and aspa-verification really are two different beasts)
> 
> A test suite to generate conforming and non-conforming ASPA objects is
> available at: https://github.com/benmaddison/rpki-aspa-test-data
> Another testbed was outlined here:
> https://mailarchive.ietf.org/arch/msg/sidrops/DvRqMbOXkhiBDdUCTJU89L4q6LY
> 
> The rpki-client(8) '-j' (/var/db/rpki-client/json) output is formatted
> such that transformation into draft-ietf-sidrops-8210bis § 5.12
> RPKI-To-Router PDUs should be easy. However, for future direct
> disk-to-bgpd(8) dissemination of ASPA objects; we probably can come up
> with something more efficient :-)

This brings me to one very basic question for which I couldn't find an
answer in the above links: how will ASPAs usually be distributed?

> Example output from "rpki-client -f":
> 
> File: 
> rpki.example.net/rpki/TA/ca-case-multi-afi-true/2338bd30cba1ff30fe3cf930824f39b45569d458de356729cb0121400ee3616a.asa
> Hash identifier: P+IG54iYS6VLlZmnIacSks0bZwHxItkIHPt5YjI4y58=
> Subject key identifier: 
> CB:B8:19:D8:E0:FD:8E:0E:10:83:D6:11:6B:2C:CD:92:28:8F:F8:C9
> Certificate serial: 01
> Authority key identifier: 
> 3C:E8:78:93:CE:9C:7F:41:53:0D:D0:E8:BB:CA:B0:03:7F:69:43:74
> Authority info access: 
> rsync://rpki.example.net/rpki/TA/ca-case-multi-afi-true.cer
> Customer AS: 65004
> Provider Set:
> 1: AS: 65005
> 2: AS: 65006 (IPv4 only)
> 3: AS: 65007 (IPv6 only)
> Validation: OK
> 
> OK? Feedback?

Could you please rebase your diff on top of -current so that you won't
undo recent pledge and unveil changes to main.c?

This looks pretty good already. I have many comments inline that should
all be easy to address. Two points up front so they don't get lost in
the noise:

1) what will need more work are aspa_insert_vaps() and insert_vap().

Looking up the same two struct vap (depending on the AFI) using
RB_INSERT(), walking the array of providers, and reallocating()
over and over again is not ideal.

Probably aspa_insert_vaps() should fill two arrays (one for each AFI) of
size providersz with the respective providerASes up front. Then we can
shrink them to their actual sizes and hang them off the two vap for this
customer AS. If there is more than one ASPA for that customer AS, then
this gets a bit trickier, but this is fine as it should rarely happen.
Another approach would be to use some linked list gymnastics.

I'm fine with keeping things mostly as they are for now and address this
in tree.

2) bikeshed material: the use of AFI_BOTH = 3 as part of enum afi.

This is a bit of an ugly hack: according to IANA, AFI number 3 is NSAP.
We use enum afi to check the on-the-wire AFIs, so this squatting is not
ideal.

Since AFI_BOTH isn't really used anyway, I think it would be acceptable
to treat 0 implicitly as AFI_BOTH: don't set aspa_p.afi to AFI_BOTH in
aspa_parse_providers() and replace "case AFI_BOTH:" with "default:" in
aspa_insert_vaps() as you already do in aspa_print(). This matches the
semantics in the draft: if the afi isn't explicitly set to IPv4 or IPv6,
it applies to both.

> 
> Kind regards,
> 
> Job
> 
> Index: Makefile
> ===
> RCS file: /cvs/src/usr.sbin/rpki-client/Makefile,v
> retrieving revision 1.25
> diff -u -p -r1.25 Makefile
> --- Makefile  9 May 2022 17:02:34 -   1.25
> +++ Makefile  13 Aug 2022 00:24:24 -
> @@ -1,8 +1,8 @@
>  #$OpenBSD: Makefile,v 1.25 2022/05/09 17:02:34 job Exp $
>  
>  PROG=rpki-client
> -SRCS=as.c cert.c cms.c crl.c encoding.c filemode.c gbr.c http.c io.c 
> ip.c \
> - log.c main.c mft.c mkdir.c output.c output-bgpd.c output-bird.c \
> +SRCS=as.c aspa.c cert.c cms.c crl.c encoding.c filemode.c gbr.c 
> http.c io.c \
> + ip.c log.c main.c mft.c mkdir.c output.c output-bgpd.c output-bird.c \
>   output-csv.c output-json.c parser.c print.c repo.c roa.c rrdp.c \
>   rrdp_delta.c rrdp_notification.c rrdp_snapshot.c rrdp_util.c \
>   rsc.c rsync.c tal.c validate.c x509.c
> Index: aspa.c
> ===
> RCS file: aspa.c
> diff -N aspa.c
> --- /dev/null 1 Jan 1970 00:00:00 -
> +++ aspa.c13 Aug 2022 00:24:24 -
> @@ -0,0 +1,447 @@
> +/*   $OpenBSD: aspa.c,v 1.16 2022/05/11 21:19:06 job Exp $ */
> +/*
> + * Copyright (c) 2022 Job Snijders 

You've copied and adapted 

rpki-client: add ASPA profile-10 support

2022-08-12 Thread Job Snijders
Dear all,

The below changeset extends rpki-client(8) to validate and emit
Autonomous System Provider Authorizations (ASPAs) in JSON format for
consumption in other routing stacks.

The ASPA CMS protected content type is specified here:
https://datatracker.ietf.org/doc/html/draft-ietf-sidrops-aspa-profile

How to verify BGP UPDATES using ASPA objects is described here:
https://datatracker.ietf.org/doc/html/draft-ietf-sidrops-aspa-verification
(Note: aspa-profile and aspa-verification really are two different beasts)

A test suite to generate conforming and non-conforming ASPA objects is
available at: https://github.com/benmaddison/rpki-aspa-test-data
Another testbed was outlined here:
https://mailarchive.ietf.org/arch/msg/sidrops/DvRqMbOXkhiBDdUCTJU89L4q6LY

The rpki-client(8) '-j' (/var/db/rpki-client/json) output is formatted
such that transformation into draft-ietf-sidrops-8210bis § 5.12
RPKI-To-Router PDUs should be easy. However, for future direct
disk-to-bgpd(8) dissemination of ASPA objects; we probably can come up
with something more efficient :-)

Example output from "rpki-client -f":

File: 
rpki.example.net/rpki/TA/ca-case-multi-afi-true/2338bd30cba1ff30fe3cf930824f39b45569d458de356729cb0121400ee3616a.asa
Hash identifier: P+IG54iYS6VLlZmnIacSks0bZwHxItkIHPt5YjI4y58=
Subject key identifier: 
CB:B8:19:D8:E0:FD:8E:0E:10:83:D6:11:6B:2C:CD:92:28:8F:F8:C9
Certificate serial: 01
Authority key identifier: 
3C:E8:78:93:CE:9C:7F:41:53:0D:D0:E8:BB:CA:B0:03:7F:69:43:74
Authority info access: 
rsync://rpki.example.net/rpki/TA/ca-case-multi-afi-true.cer
Customer AS: 65004
Provider Set:
1: AS: 65005
2: AS: 65006 (IPv4 only)
3: AS: 65007 (IPv6 only)
Validation: OK

OK? Feedback?

Kind regards,

Job

Index: Makefile
===
RCS file: /cvs/src/usr.sbin/rpki-client/Makefile,v
retrieving revision 1.25
diff -u -p -r1.25 Makefile
--- Makefile9 May 2022 17:02:34 -   1.25
+++ Makefile13 Aug 2022 00:24:24 -
@@ -1,8 +1,8 @@
 #  $OpenBSD: Makefile,v 1.25 2022/05/09 17:02:34 job Exp $
 
 PROG=  rpki-client
-SRCS=  as.c cert.c cms.c crl.c encoding.c filemode.c gbr.c http.c io.c ip.c \
-   log.c main.c mft.c mkdir.c output.c output-bgpd.c output-bird.c \
+SRCS=  as.c aspa.c cert.c cms.c crl.c encoding.c filemode.c gbr.c http.c io.c \
+   ip.c log.c main.c mft.c mkdir.c output.c output-bgpd.c output-bird.c \
output-csv.c output-json.c parser.c print.c repo.c roa.c rrdp.c \
rrdp_delta.c rrdp_notification.c rrdp_snapshot.c rrdp_util.c \
rsc.c rsync.c tal.c validate.c x509.c
Index: aspa.c
===
RCS file: aspa.c
diff -N aspa.c
--- /dev/null   1 Jan 1970 00:00:00 -
+++ aspa.c  13 Aug 2022 00:24:24 -
@@ -0,0 +1,447 @@
+/* $OpenBSD: aspa.c,v 1.16 2022/05/11 21:19:06 job Exp $ */
+/*
+ * Copyright (c) 2022 Job Snijders 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "extern.h"
+
+/*
+ * Parse results and data of the ASPA object.
+ */
+struct parse {
+   const char   *fn; /* ASPA file name */
+   struct aspa  *res; /* results */
+};
+
+extern ASN1_OBJECT *aspa_oid;
+
+/*
+ * Types and templates for ASPA eContent draft-ietf-sidrops-aspa-profile-08
+ */
+
+typedef struct {
+   ASN1_INTEGER*providerASID;
+   ASN1_OCTET_STRING   *afiLimit;
+} ProviderAS;
+
+DECLARE_STACK_OF(ProviderAS);
+
+#ifndef DEFINE_STACK_OF
+#define sk_ProviderAS_num(sk)  SKM_sk_num(ProviderAS, (sk))
+#define sk_ProviderAS_value(sk, i) SKM_sk_value(ProviderAS, (sk), (i))
+#endif
+
+ASN1_SEQUENCE(ProviderAS) = {
+   ASN1_SIMPLE(ProviderAS, providerASID, ASN1_INTEGER),
+   ASN1_OPT(ProviderAS, afiLimit, ASN1_OCTET_STRING),
+} ASN1_SEQUENCE_END(ProviderAS);
+
+typedef struct {
+   ASN1_INTEGER*version;
+   ASN1_INTEGER*customerASID;
+   STACK_OF(ProviderAS)*providers;
+} ASProviderAttestation;
+
+ASN1_SEQUENCE(ASProviderAttestation) = {
+   ASN1_IMP_OPT(ASProviderAttestation,