rpki-client: Refactor sbgp_assysnum() and sbgp_addrblk()
authortb <tb@openbsd.org>
Mon, 25 Sep 2023 14:56:20 +0000 (14:56 +0000)
committertb <tb@openbsd.org>
Mon, 25 Sep 2023 14:56:20 +0000 (14:56 +0000)
An upcoming diff requires the ability to convert ASIdentifiers and
IpAddrBlocks into rpki-client's internal structures.  Accordingly,
split already existing code into dedicated parsing functions . The
original functions now only extract the extension-specific data from
the X509_EXTENSION.

input/ok claudio

usr.sbin/rpki-client/cert.c
usr.sbin/rpki-client/extern.h

index c123640..e4ad31a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cert.c,v 1.115 2023/09/12 09:33:30 job Exp $ */
+/*     $OpenBSD: cert.c,v 1.116 2023/09/25 14:56:20 tb Exp $ */
 /*
  * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
  * Copyright (c) 2021 Job Snijders <job@openbsd.org>
@@ -153,40 +153,26 @@ sbgp_as_inherit(const char *fn, struct cert_as *ases, size_t *asz)
        return append_as(fn, ases, asz, &as);
 }
 
-/*
- * Parse RFC 6487 4.8.11 X509v3 extension, with syntax documented in RFC
- * 3779 starting in section 3.2.
- * Returns zero on failure, non-zero on success.
- */
-static int
-sbgp_assysnum(struct parse *p, X509_EXTENSION *ext)
+int
+sbgp_parse_assysnum(const char *fn, const ASIdentifiers *asidentifiers,
+    struct cert_as **out_as, size_t *out_asz)
 {
-       ASIdentifiers           *asidentifiers = NULL;
        const ASIdOrRanges      *aors = NULL;
-       size_t                   asz;
-       int                      i, rc = 0;
+       struct cert_as          *as = NULL;
+       size_t                   asz, new_asz = 0;
+       int                      i;
 
-       if (!X509_EXTENSION_get_critical(ext)) {
-               warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
-                   "extension not critical", p->fn);
-               goto out;
-       }
-
-       if ((asidentifiers = X509V3_EXT_d2i(ext)) == NULL) {
-               warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
-                   "failed extension parse", p->fn);
-               goto out;
-       }
+       assert(*out_as == NULL && *out_asz == 0);
 
        if (asidentifiers->rdi != NULL) {
                warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
-                   "should not have RDI values", p->fn);
+                   "should not have RDI values", fn);
                goto out;
        }
 
        if (asidentifiers->asnum == NULL) {
                warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
-                   "no AS number resource set", p->fn);
+                   "no AS number resource set", fn);
                goto out;
        }
 
@@ -200,26 +186,25 @@ sbgp_assysnum(struct parse *p, X509_EXTENSION *ext)
                break;
        default:
                warnx("%s: RFC 3779 section 3.2.3.2: ASIdentifierChoice: "
-                   "unknown type %d", p->fn, asidentifiers->asnum->type);
+                   "unknown type %d", fn, asidentifiers->asnum->type);
                goto out;
        }
 
        if (asz == 0) {
-               warnx("%s: RFC 6487 section 4.8.11: empty asIdsOrRanges",
-                   p->fn);
+               warnx("%s: RFC 6487 section 4.8.11: empty asIdsOrRanges", fn);
                goto out;
        }
        if (asz >= MAX_AS_SIZE) {
                warnx("%s: too many AS number entries: limit %d",
-                   p->fn, MAX_AS_SIZE);
+                   fn, MAX_AS_SIZE);
                goto out;
        }
-       p->res->as = calloc(asz, sizeof(struct cert_as));
-       if (p->res->as == NULL)
+       as = calloc(asz, sizeof(struct cert_as));
+       if (as == NULL)
                err(1, NULL);
 
        if (aors == NULL) {
-               if (!sbgp_as_inherit(p->fn, p->res->as, &p->res->asz))
+               if (!sbgp_as_inherit(fn, as, &new_asz))
                        goto out;
        }
 
@@ -229,22 +214,58 @@ sbgp_assysnum(struct parse *p, X509_EXTENSION *ext)
                aor = sk_ASIdOrRange_value(aors, i);
                switch (aor->type) {
                case ASIdOrRange_id:
-                       if (!sbgp_as_id(p->fn, p->res->as, &p->res->asz,
-                           aor->u.id))
+                       if (!sbgp_as_id(fn, as, &new_asz, aor->u.id))
                                goto out;
                        break;
                case ASIdOrRange_range:
-                       if (!sbgp_as_range(p->fn, p->res->as, &p->res->asz,
-                           aor->u.range))
+                       if (!sbgp_as_range(fn, as, &new_asz, aor->u.range))
                                goto out;
                        break;
                default:
                        warnx("%s: RFC 3779 section 3.2.3.5: ASIdOrRange: "
-                           "unknown type %d", p->fn, aor->type);
+                           "unknown type %d", fn, aor->type);
                        goto out;
                }
        }
 
+       *out_as = as;
+       *out_asz = new_asz;
+
+       return 1;
+
+ out:
+       free(as);
+
+       return 0;
+}
+
+/*
+ * Parse RFC 6487 4.8.11 X509v3 extension, with syntax documented in RFC
+ * 3779 starting in section 3.2.
+ * Returns zero on failure, non-zero on success.
+ */
+static int
+sbgp_assysnum(struct parse *p, X509_EXTENSION *ext)
+{
+       ASIdentifiers           *asidentifiers = NULL;
+       int                      rc = 0;
+
+       if (!X509_EXTENSION_get_critical(ext)) {
+               warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
+                   "extension not critical", p->fn);
+               goto out;
+       }
+
+       if ((asidentifiers = X509V3_EXT_d2i(ext)) == NULL) {
+               warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
+                   "failed extension parse", p->fn);
+               goto out;
+       }
+
+       if (!sbgp_parse_assysnum(p->fn, asidentifiers,
+           &p->res->as, &p->res->asz))
+               goto out;
+
        rc = 1;
  out:
        ASIdentifiers_free(asidentifiers);
@@ -331,33 +352,19 @@ sbgp_addr_inherit(const char *fn, struct cert_ip *ips, size_t *ipsz,
        return append_ip(fn, ips, ipsz, &ip);
 }
 
-/*
- * Parse an sbgp-ipAddrBlock X509 extension, RFC 6487 4.8.10, with
- * syntax documented in RFC 3779 starting in section 2.2.
- * Returns zero on failure, non-zero on success.
- */
-static int
-sbgp_ipaddrblk(struct parse *p, X509_EXTENSION *ext)
+int
+sbgp_parse_ipaddrblk(const char *fn, const IPAddrBlocks *addrblk,
+    struct cert_ip **out_ips, size_t *out_ipsz)
 {
-       STACK_OF(IPAddressFamily)       *addrblk = NULL;
-       const IPAddressFamily           *af;
-       const IPAddressOrRanges         *aors;
-       const IPAddressOrRange          *aor;
-       enum afi                         afi;
-       size_t                           ipsz;
-       int                              i, j, rc = 0;
-
-       if (!X509_EXTENSION_get_critical(ext)) {
-               warnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: "
-                   "extension not critical", p->fn);
-               goto out;
-       }
+       const IPAddressFamily   *af;
+       const IPAddressOrRanges *aors;
+       const IPAddressOrRange  *aor;
+       enum afi                 afi;
+       struct cert_ip          *ips = NULL;
+       size_t                   ipsz, new_ipsz = 0;
+       int                      i, j;
 
-       if ((addrblk = X509V3_EXT_d2i(ext)) == NULL) {
-               warnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: "
-                   "failed extension parse", p->fn);
-               goto out;
-       }
+       assert(*out_ips == NULL && *out_ipsz == 0);
 
        for (i = 0; i < sk_IPAddressFamily_num(addrblk); i++) {
                af = sk_IPAddressFamily_value(addrblk, i);
@@ -365,38 +372,37 @@ sbgp_ipaddrblk(struct parse *p, X509_EXTENSION *ext)
                switch (af->ipAddressChoice->type) {
                case IPAddressChoice_inherit:
                        aors = NULL;
-                       ipsz = p->res->ipsz + 1;
+                       ipsz = new_ipsz + 1;
                        break;
                case IPAddressChoice_addressesOrRanges:
                        aors = af->ipAddressChoice->u.addressesOrRanges;
-                       ipsz = p->res->ipsz + sk_IPAddressOrRange_num(aors);
+                       ipsz = new_ipsz + sk_IPAddressOrRange_num(aors);
                        break;
                default:
                        warnx("%s: RFC 3779: IPAddressChoice: unknown type %d",
-                           p->fn, af->ipAddressChoice->type);
+                           fn, af->ipAddressChoice->type);
                        goto out;
                }
-               if (ipsz == p->res->ipsz) {
+               if (ipsz == new_ipsz) {
                        warnx("%s: RFC 6487 section 4.8.10: "
-                           "empty ipAddressesOrRanges", p->fn);
+                           "empty ipAddressesOrRanges", fn);
                        goto out;
                }
 
                if (ipsz >= MAX_IP_SIZE)
                        goto out;
-               p->res->ips = recallocarray(p->res->ips, p->res->ipsz, ipsz,
+               ips = recallocarray(ips, new_ipsz, ipsz,
                    sizeof(struct cert_ip));
-               if (p->res->ips == NULL)
+               if (ips == NULL)
                        err(1, NULL);
 
-               if (!ip_addr_afi_parse(p->fn, af->addressFamily, &afi)) {
-                       warnx("%s: RFC 3779: invalid AFI", p->fn);
+               if (!ip_addr_afi_parse(fn, af->addressFamily, &afi)) {
+                       warnx("%s: RFC 3779: invalid AFI", fn);
                        goto out;
                }
 
                if (aors == NULL) {
-                       if (!sbgp_addr_inherit(p->fn, p->res->ips,
-                           &p->res->ipsz, afi))
+                       if (!sbgp_addr_inherit(fn, ips, &new_ipsz, afi))
                                goto out;
                        continue;
                }
@@ -405,23 +411,60 @@ sbgp_ipaddrblk(struct parse *p, X509_EXTENSION *ext)
                        aor = sk_IPAddressOrRange_value(aors, j);
                        switch (aor->type) {
                        case IPAddressOrRange_addressPrefix:
-                               if (!sbgp_addr(p->fn, p->res->ips,
-                                   &p->res->ipsz, afi, aor->u.addressPrefix))
+                               if (!sbgp_addr(fn, ips, &new_ipsz, afi,
+                                   aor->u.addressPrefix))
                                        goto out;
                                break;
                        case IPAddressOrRange_addressRange:
-                               if (!sbgp_addr_range(p->fn, p->res->ips,
-                                   &p->res->ipsz, afi, aor->u.addressRange))
+                               if (!sbgp_addr_range(fn, ips, &new_ipsz, afi,
+                                   aor->u.addressRange))
                                        goto out;
                                break;
                        default:
                                warnx("%s: RFC 3779: IPAddressOrRange: "
-                                   "unknown type %d", p->fn, aor->type);
+                                   "unknown type %d", fn, aor->type);
                                goto out;
                        }
                }
        }
 
+       *out_ips = ips;
+       *out_ipsz = new_ipsz;
+
+       return 1;
+
+ out:
+       free(ips);
+
+       return 0;
+}
+
+/*
+ * Parse an sbgp-ipAddrBlock X509 extension, RFC 6487 4.8.10, with
+ * syntax documented in RFC 3779 starting in section 2.2.
+ * Returns zero on failure, non-zero on success.
+ */
+static int
+sbgp_ipaddrblk(struct parse *p, X509_EXTENSION *ext)
+{
+       STACK_OF(IPAddressFamily)       *addrblk = NULL;
+       int                              rc = 0;
+
+       if (!X509_EXTENSION_get_critical(ext)) {
+               warnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: "
+                   "extension not critical", p->fn);
+               goto out;
+       }
+
+       if ((addrblk = X509V3_EXT_d2i(ext)) == NULL) {
+               warnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: "
+                   "failed extension parse", p->fn);
+               goto out;
+       }
+
+       if (!sbgp_parse_ipaddrblk(p->fn, addrblk, &p->res->ips, &p->res->ipsz))
+               goto out;
+
        if (p->res->ipsz == 0) {
                warnx("%s: RFC 6487 section 4.8.10: empty ipAddrBlock", p->fn);
                goto out;
index 5497525..53ff444 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: extern.h,v 1.191 2023/09/25 11:08:45 tb Exp $ */
+/*     $OpenBSD: extern.h,v 1.192 2023/09/25 14:56:20 tb Exp $ */
 /*
  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -723,6 +723,9 @@ int          sbgp_addr(const char *, struct cert_ip *, size_t *,
 int             sbgp_addr_range(const char *, struct cert_ip *, size_t *,
                    enum afi, const IPAddressRange *);
 
+int             sbgp_parse_ipaddrblk(const char *, const IPAddrBlocks *,
+                   struct cert_ip **, size_t *);
+
 /* Work with RFC 3779 AS numbers, ranges. */
 
 int             as_id_parse(const ASN1_INTEGER *, uint32_t *);
@@ -736,6 +739,9 @@ int          sbgp_as_id(const char *, struct cert_as *, size_t *,
 int             sbgp_as_range(const char *, struct cert_as *, size_t *,
                    const ASRange *);
 
+int             sbgp_parse_assysnum(const char *, const ASIdentifiers *,
+                   struct cert_as **, size_t *);
+
 /* Parser-specific */
 void            entity_free(struct entity *);
 void            entity_read_req(struct ibuf *, struct entity *);