]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Implement RFC 8360
authorAlberto Leiva Popper <ydahhrk@gmail.com>
Tue, 12 Feb 2019 17:56:16 +0000 (11:56 -0600)
committerAlberto Leiva Popper <ydahhrk@gmail.com>
Tue, 12 Feb 2019 18:05:02 +0000 (12:05 -0600)
Not really tested, because it doesn't look like there are people using
this feature yet.

Also:
- refactor inet_ntop() usage so we don't have to clutter the stack with
  string buffers every time we want to print.
- Patch sometimes undefined behavior `0xFFFFFFFFu >> 32`.

25 files changed:
src/Makefile.am
src/address.c
src/address.h
src/asn1/signed_data.c
src/certificate_refs.c
src/common.c
src/common.h
src/extension.c
src/extension.h
src/log.c
src/log.h
src/main.c
src/nid.c [new file with mode: 0644]
src/nid.h [new file with mode: 0644]
src/object/certificate.c
src/object/certificate.h
src/object/crl.c
src/object/roa.c
src/resource.c
src/resource.h
src/resource/ip4.c
src/state.c
src/state.h
src/thread_var.c
src/thread_var.h

index 4ea82830f89699ffa5612289a2c0665c9e6d393e..5379704e651f646f041e27465c710c4167abeceb 100644 (file)
@@ -17,6 +17,7 @@ rpki_validator_SOURCES += extension.h extension.c
 rpki_validator_SOURCES += file.h file.c
 rpki_validator_SOURCES += line_file.h line_file.c
 rpki_validator_SOURCES += log.h log.c
+rpki_validator_SOURCES += nid.h nid.c
 rpki_validator_SOURCES += random.h random.c
 rpki_validator_SOURCES += resource.h resource.c
 rpki_validator_SOURCES += rpp.h rpp.c
index 0bcbe1ca6781dbe463998138bb9991e340217d1d..63da197154eddb16768ff83c5ed0dbcb7a1b75f2 100644 (file)
@@ -4,56 +4,65 @@
 #include <errno.h>
 #include <arpa/inet.h> /* inet_ntop */
 #include "log.h"
+#include "thread_var.h"
 
-static char const *
-addr2str4(struct in_addr *addr, char *buffer)
-{
-       return inet_ntop(AF_INET, addr, buffer, INET_ADDRSTRLEN);
-}
-
-static char const *
-addr2str6(struct in6_addr *addr, char *buffer)
+/*
+ * Returns a mask you can use to extract the suffix bits of a 32-bit unsigned
+ * number whose prefix lengths @prefix_len.
+ * For example: Suppose that your number is 192.0.2.0/24.
+ * u32_suffix_mask(24) returns 0.0.0.255.
+ *
+ * The result is in host byte order.
+ */
+uint32_t
+u32_suffix_mask(unsigned int prefix_len)
 {
-       return inet_ntop(AF_INET6, addr, buffer, INET6_ADDRSTRLEN);
+       /* `a >> 32` is undefined if `a` is 32 bits. */
+       return (prefix_len < 32) ? (0xFFFFFFFFu >> prefix_len) : 0;
 }
 
 /**
- * Returns a mask you can use to extract the suffix bits of an address whose
- * prefix lengths @prefix_len.
- * For example: Suppose that your address is 192.0.2.0/24.
- * addr4_suffix_mask(24) returns 0.0.0.255.
+ * Same as u32_suffix_mask(), except the result is in network byte order
+ * ("be", for "big endian").
  */
 uint32_t
-ipv4_suffix_mask(unsigned int prefix_len)
+be32_suffix_mask(unsigned int prefix_len)
 {
-       return htonl(0xFFFFFFFFu >> prefix_len);
+       return htonl(u32_suffix_mask(prefix_len));
 }
 
+/**
+ * Enables all the suffix bits of @result (assuming its prefix length is
+ * @prefix_len).
+ * @result's prefix bits will not be modified.
+ */
 void
 ipv6_suffix_mask(unsigned int prefix_len, struct in6_addr *result)
 {
        if (prefix_len < 32) {
-               result->s6_addr32[0] |= htonl(0xFFFFFFFFu >> prefix_len);
+               result->s6_addr32[0] |= be32_suffix_mask(prefix_len);
                result->s6_addr32[1] = 0xFFFFFFFFu;
                result->s6_addr32[2] = 0xFFFFFFFFu;
                result->s6_addr32[3] = 0xFFFFFFFFu;
        } else if (prefix_len < 64) {
-               result->s6_addr32[1] |= htonl(0xFFFFFFFFu >> (prefix_len - 32));
+               result->s6_addr32[1] |= be32_suffix_mask(prefix_len - 32);
                result->s6_addr32[2] = 0xFFFFFFFFu;
                result->s6_addr32[3] = 0xFFFFFFFFu;
        } else if (prefix_len < 96) {
-               result->s6_addr32[2] |= htonl(0xFFFFFFFFu >> (prefix_len - 64));
+               result->s6_addr32[2] |= be32_suffix_mask(prefix_len - 64);
                result->s6_addr32[3] = 0xFFFFFFFFu;
        } else {
-               result->s6_addr32[3] |= htonl(0xFFFFFFFFu >> (prefix_len - 96));
+               result->s6_addr32[3] |= be32_suffix_mask(prefix_len - 96);
        }
 }
 
+/**
+ * Translates an `IPAddress2_t` to its equivalent `struct ipv4_prefix`.
+ */
 int
 prefix4_decode(IPAddress2_t *str, struct ipv4_prefix *result)
 {
        int len;
-       char buffer[INET_ADDRSTRLEN];
 
        if (str->size > 4) {
                return pr_err("IPv4 address has too many octets. (%u)",
@@ -75,20 +84,22 @@ prefix4_decode(IPAddress2_t *str, struct ipv4_prefix *result)
 
        result->len = len;
 
-       if ((result->addr.s_addr & ipv4_suffix_mask(result->len)) != 0) {
-               return pr_err("IPv4 prefix %s/%u has enabled suffix bits.",
-                   addr2str4(&result->addr, buffer), result->len);
+       if ((result->addr.s_addr & be32_suffix_mask(result->len)) != 0) {
+               return pr_err("IPv4 prefix '%s/%u' has enabled suffix bits.",
+                   v4addr2str(&result->addr), result->len);
        }
 
        return 0;
 }
 
+/**
+ * Translates an `IPAddress2_t` to its equivalent `struct ipv6_prefix`.
+ */
 int
 prefix6_decode(IPAddress2_t *str, struct ipv6_prefix *result)
 {
        struct in6_addr suffix;
        int len;
-       char buffer[INET6_ADDRSTRLEN];
 
        if (str->size > 16) {
                return pr_err("IPv6 address has too many octets. (%u)",
@@ -116,8 +127,8 @@ prefix6_decode(IPAddress2_t *str, struct ipv6_prefix *result)
            || (result->addr.s6_addr32[1] & suffix.s6_addr32[1])
            || (result->addr.s6_addr32[2] & suffix.s6_addr32[2])
            || (result->addr.s6_addr32[3] & suffix.s6_addr32[3])) {
-               return pr_err("IPv6 prefix %s/%u has enabled suffix bits.",
-                   addr2str6(&result->addr, buffer), result->len);
+               return pr_err("IPv6 prefix '%s/%u' has enabled suffix bits.",
+                   v6addr2str(&result->addr), result->len);
        }
 
        return 0;
@@ -126,13 +137,9 @@ prefix6_decode(IPAddress2_t *str, struct ipv6_prefix *result)
 static int
 check_order4(struct ipv4_range *result)
 {
-       char buffer_min[INET_ADDRSTRLEN];
-       char buffer_max[INET_ADDRSTRLEN];
-
        if (ntohl(result->min.s_addr) > ntohl(result->max.s_addr)) {
-               return pr_err("The IPv4 range %s-%s is inverted.",
-                   addr2str4(&result->min, buffer_min),
-                   addr2str4(&result->max, buffer_max));
+               return pr_err("The IPv4 range '%s-%s' is inverted.",
+                   v4addr2str(&result->min), v4addr2str2(&result->max));
        }
 
        return 0;
@@ -149,8 +156,6 @@ check_encoding4(struct ipv4_range *range)
        const uint32_t MIN = ntohl(range->min.s_addr);
        const uint32_t MAX = ntohl(range->max.s_addr);
        uint32_t mask;
-       char buffer_min[INET_ADDRSTRLEN];
-       char buffer_max[INET_ADDRSTRLEN];
 
        for (mask = 0x80000000u; mask != 0; mask >>= 1)
                if ((MIN & mask) != (MAX & mask))
@@ -160,11 +165,13 @@ check_encoding4(struct ipv4_range *range)
                if (((MIN & mask) != 0) || ((MAX & mask) == 0))
                        return 0;
 
-       return pr_err("IPAddressRange %s-%s is a range, but should have been encoded as a prefix.",
-           addr2str4(&range->min, buffer_min),
-           addr2str4(&range->min, buffer_max));
+       return pr_err("IPAddressRange '%s-%s' is a range, but should have been encoded as a prefix.",
+           v4addr2str(&range->min), v4addr2str2(&range->max));
 }
 
+/**
+ * Translates an `IPAddressRange_t` to its equivalent `struct ipv4_range`.
+ */
 int
 range4_decode(IPAddressRange_t *input, struct ipv4_range *result)
 {
@@ -179,7 +186,7 @@ range4_decode(IPAddressRange_t *input, struct ipv4_range *result)
        error = prefix4_decode(&input->max, &prefix);
        if (error)
                return error;
-       result->max.s_addr = prefix.addr.s_addr | ipv4_suffix_mask(prefix.len);
+       result->max.s_addr = prefix.addr.s_addr | be32_suffix_mask(prefix.len);
 
        error = check_order4(result);
        if (error)
@@ -194,16 +201,14 @@ check_order6(struct ipv6_range *result)
        uint32_t min;
        uint32_t max;
        unsigned int quadrant;
-       char buffer_min[INET6_ADDRSTRLEN];
-       char buffer_max[INET6_ADDRSTRLEN];
 
        for (quadrant = 0; quadrant < 4; quadrant++) {
                min = ntohl(result->min.s6_addr32[quadrant]);
                max = ntohl(result->max.s6_addr32[quadrant]);
                if (min > max) {
-                       return pr_err("The IPv6 range %s-%s is inverted.",
-                           addr2str6(&result->min, buffer_min),
-                           addr2str6(&result->max, buffer_max));
+                       return pr_err("The IPv6 range '%s-%s' is inverted.",
+                           v6addr2str(&result->min),
+                           v6addr2str2(&result->max));
                } else if (min < max) {
                        return 0; /* result->min < result->max */
                }
@@ -215,15 +220,13 @@ check_order6(struct ipv6_range *result)
 static int
 pr_bad_encoding(struct ipv6_range *range)
 {
-       char buffer_min[INET6_ADDRSTRLEN];
-       char buffer_max[INET6_ADDRSTRLEN];
        return pr_err("IPAddressRange %s-%s is a range, but should have been encoded as a prefix.",
-           addr2str6(&range->min, buffer_min),
-           addr2str6(&range->max, buffer_max));
+           v6addr2str(&range->min), v6addr2str2(&range->max));
 }
 
 static int
-thingy(struct ipv6_range *range, unsigned int quadrant, uint32_t mask)
+__check_encoding6(struct ipv6_range *range, unsigned int quadrant,
+    uint32_t mask)
 {
        uint32_t min;
        uint32_t max;
@@ -253,12 +256,15 @@ check_encoding6(struct ipv6_range *range)
                max = ntohl(range->max.s6_addr32[quadrant]);
                for (mask = 0x80000000u; mask != 0; mask >>= 1)
                        if ((min & mask) != (max & mask))
-                               return thingy(range, quadrant, mask);
+                               return __check_encoding6(range, quadrant, mask);
        }
 
        return pr_bad_encoding(range);
 }
 
+/**
+ * Translates an `IPAddressRange_t` to its equivalent `struct ipv6_range`.
+ */
 int
 range6_decode(IPAddressRange_t *input, struct ipv6_range *result)
 {
index cb5803a187e08cc36070fdafefead2c2065ede47..5d8e24eb359b62dc3ecca3abe738440e8f4f8c38 100644 (file)
@@ -26,7 +26,8 @@ struct ipv6_range {
        struct in6_addr max;
 };
 
-uint32_t ipv4_suffix_mask(unsigned int);
+uint32_t u32_suffix_mask(unsigned int);
+uint32_t be32_suffix_mask(unsigned int);
 void ipv6_suffix_mask(unsigned int, struct in6_addr *);
 
 int prefix4_decode(IPAddress2_t *, struct ipv4_prefix *);
index d00c68f97122ce2a889a327a85a864105a50011b..5375d0ba1e0561cd14678aed8344bb64095661d5 100644 (file)
@@ -58,6 +58,7 @@ handle_sdata_certificate(ANY_t *any, struct signed_object_args *args,
        struct validation *state;
        const unsigned char *tmp;
        X509 *cert;
+       enum rpki_policy policy;
        int error;
 
        state = state_retrieve();
@@ -89,15 +90,19 @@ handle_sdata_certificate(ANY_t *any, struct signed_object_args *args,
        error = certificate_validate_rfc6487(cert, false);
        if (error)
                goto end2;
+       error = certificate_validate_extensions_ee(cert, sid, &args->refs,
+           &policy);
+       if (error)
+               goto end2;
 
        if (args->res != NULL) {
+               /* TODO validate resources even if the SO lacks them */
+               resources_set_policy(args->res, policy);
                error = certificate_get_resources(cert, args->res);
                if (error)
                        goto end2;
        }
 
-       error = certificate_validate_extensions_ee(cert, sid, &args->refs);
-
 end2:
        X509_free(cert);
 end1:
index 45c91cb422fe081c9a397a266a75a9557e9055cf..13db4d57dbe053e2a1bea17c06fa056d5d70b55b 100644 (file)
@@ -24,11 +24,11 @@ validate_cdp(struct certificate_refs *refs, struct rpp const *pp)
        struct rpki_uri const *pp_crl;
 
        if (refs->crldp == NULL)
-               return pr_err("Programming error: Certificate's CRL Distribution Point was not recorded.");
+               return pr_crit("Certificate's CRL Distribution Point was not recorded.");
 
        pp_crl = rpp_get_crl(pp);
        if (pp_crl == NULL)
-               return pr_err("Programming error: Manifest's CRL was not recorded.");
+               return pr_crit("Manifest's CRL was not recorded.");
 
        if (strcmp(refs->crldp, pp_crl->global) != 0) {
                return pr_err("Certificate's CRL Distribution Point ('%s') does not match manifest's CRL ('%s').",
@@ -45,14 +45,14 @@ validate_aia(struct certificate_refs *refs)
        struct rpki_uri const *parent;
 
        if (refs->caIssuers == NULL)
-               return pr_err("Programming error: Certificate's AIA was not recorded.");
+               return pr_crit("Certificate's AIA was not recorded.");
 
        state = state_retrieve();
        if (state == NULL)
                return -EINVAL;
        parent = validation_peek_cert_uri(state);
        if (parent == NULL)
-               return pr_err("Programming error: CA certificate has no parent.");
+               return pr_crit("CA certificate has no parent.");
 
        if (strcmp(refs->caIssuers, parent->global) != 0) {
                return pr_err("Certificate's AIA ('%s') does not match parent's URI ('%s').",
@@ -67,7 +67,7 @@ validate_signedObject(struct certificate_refs *refs,
     struct rpki_uri const *signedObject_uri)
 {
        if (refs->signedObject == NULL)
-               return pr_err("Programming error: Certificate's signedObject was not recorded.");
+               return pr_crit("Certificate's signedObject was not recorded.");
 
        if (strcmp(refs->signedObject, signedObject_uri->global) != 0) {
                return pr_err("Certificate's signedObject ('%s') does not match the URI of its own signed object (%s).",
@@ -95,7 +95,7 @@ refs_validate_ca(struct certificate_refs *refs, bool is_ta,
                return error;
 
        if (refs->signedObject != NULL) {
-               return pr_err("Programming error: CA summary has a signedObject ('%s').",
+               return pr_crit("CA summary has a signedObject ('%s').",
                    refs->signedObject);
        }
 
index 6ffb3cf8ebd41859e717598398df759919ba1f38..a35c6743ef34b7c2f99237894ce5e4127285a1ae 100644 (file)
@@ -5,12 +5,6 @@
 #include "log.h"
 #include "thread_var.h"
 
-int NID_rpkiManifest;
-int NID_signedObject;
-int NID_rpkiNotify;
-int NID_certPolicyRpki;
-int NID_certPolicyRpkiV2;
-
 /**
  * Does not assume that @string is NULL-terminated.
  */
index 117f6eef63c2604c2392528e6567801a31c6b85d..e109d437bd282052c3793cb66f9177f732d9d021 100644 (file)
  */
 #define ENOTRSYNC 3174
 
-extern int NID_rpkiManifest;
-extern int NID_signedObject;
-extern int NID_rpkiNotify;
-extern int NID_certPolicyRpki;
-extern int NID_certPolicyRpkiV2;
-
 #define ARRAY_LEN(array) (sizeof(array) / sizeof(array[0]))
 
 int string_clone(void const *, size_t, char **);
index 25535baaa97bb0730903d97230a62d79194d4420..18ea94547eb0959fac50e09e71f97ee07595a94f 100644 (file)
 #include "extension.h"
 
 #include <errno.h>
+#include "common.h"
 #include "log.h"
+#include "nid.h"
 #include "thread_var.h"
 #include "crypto/hash.h"
 
-const struct extension_metadata BC = {
-       "Basic Constraints",
-       NID_basic_constraints,
+static struct extension_metadata IR2 = {
+       "Amended IP Resources",
+       /* TODO NID_ipAddrBlocksv2 */ -1,
        true,
 };
-const struct extension_metadata SKI = {
-       "Subject Key Identifier",
-       NID_subject_key_identifier,
-       false,
-};
-const struct extension_metadata AKI = {
-       "Authority Key Identifier",
-       NID_authority_key_identifier,
-       false,
-};
-const struct extension_metadata KU = {
-       "Key Usage",
-       NID_key_usage,
-       true,
-};
-const struct extension_metadata CDP = {
-       "CRL Distribution Points",
-       NID_crl_distribution_points,
-       false,
-};
-const struct extension_metadata AIA = {
-       "Authority Information Access",
-       NID_info_access,
-       false,
-};
-const struct extension_metadata SIA = {
-       "Subject Information Access",
-       NID_sinfo_access ,
-       false,
-};
-const struct extension_metadata CP = {
-       "Certificate Policies",
-       NID_certificate_policies,
-       true,
-};
-const struct extension_metadata IR = {
-       "IP Resources",
-       NID_sbgp_ipAddrBlock,
-       true,
-};
-const struct extension_metadata AR = {
-       "AS Resources",
-       NID_sbgp_autonomousSysNum,
+
+static struct extension_metadata AR2 = {
+       "Amended AS Resources",
+       /* TODO NID_autonomousSysIdsv2 */ -1,
        true,
 };
-const struct extension_metadata CN = {
-       "CRL Number",
-       NID_crl_number,
-       false,
-};
+
+int extension_init(void)
+{
+       IR2.nid = nid_ipAddrBlocksv2();
+       AR2.nid = nid_autonomousSysIdsv2();
+       return 0;
+}
+
+struct extension_metadata const *ext_bc(void)
+{
+       static const struct extension_metadata BC = {
+               "Basic Constraints",
+               NID_basic_constraints,
+               true,
+       };
+       return &BC;
+}
+
+struct extension_metadata const *ext_ski(void)
+{
+       static const struct extension_metadata SKI = {
+               "Subject Key Identifier",
+               NID_subject_key_identifier,
+               false,
+       };
+       return &SKI;
+}
+
+struct extension_metadata const *ext_aki(void)
+{
+       static const struct extension_metadata AKI = {
+               "Authority Key Identifier",
+               NID_authority_key_identifier,
+               false,
+       };
+       return &AKI;
+}
+
+struct extension_metadata const *ext_ku(void)
+{
+       static const struct extension_metadata KU = {
+               "Key Usage",
+               NID_key_usage,
+               true,
+       };
+       return &KU;
+}
+
+struct extension_metadata const *ext_cdp(void)
+{
+       static const struct extension_metadata CDP = {
+               "CRL Distribution Points",
+               NID_crl_distribution_points,
+               false,
+       };
+       return &CDP;
+}
+
+struct extension_metadata const *ext_aia(void)
+{
+       static const struct extension_metadata AIA = {
+               "Authority Information Access",
+               NID_info_access,
+               false,
+       };
+       return &AIA;
+}
+
+struct extension_metadata const *ext_sia(void)
+{
+       static const struct extension_metadata SIA = {
+               "Subject Information Access",
+               NID_sinfo_access ,
+               false,
+       };
+       return &SIA;
+}
+
+struct extension_metadata const *ext_cp(void)
+{
+       static const struct extension_metadata CP = {
+               "Certificate Policies",
+               NID_certificate_policies,
+               true,
+       };
+       return &CP;
+}
+
+struct extension_metadata const *ext_ir(void)
+{
+       static const struct extension_metadata IR = {
+               "IP Resources",
+               NID_sbgp_ipAddrBlock,
+               true,
+       };
+       return &IR;
+}
+
+struct extension_metadata const *ext_ar(void)
+{
+       static const struct extension_metadata AR = {
+               "AS Resources",
+               NID_sbgp_autonomousSysNum,
+               true,
+       };
+       return &AR;
+}
+
+struct extension_metadata const *ext_ir2(void)
+{
+       return &IR2;
+}
+
+struct extension_metadata const *ext_ar2(void)
+{
+       return &AR2;
+}
+
+struct extension_metadata const *ext_cn(void)
+{
+       static const struct extension_metadata CN = {
+               "CRL Number",
+               NID_crl_number,
+               false,
+       };
+       return &CN;
+}
 
 static int
 handle_extension(struct extension_handler *handlers, X509_EXTENSION *ext)
@@ -111,8 +196,6 @@ handle_extensions(struct extension_handler *handlers,
        int e;
        int error;
 
-       /* TODO check that no other extensions are present? */
-
        for (e = 0; e < sk_X509_EXTENSION_num(extensions); e++) {
                error = handle_extension(handlers,
                    sk_X509_EXTENSION_value(extensions, e));
@@ -192,7 +275,7 @@ validate_public_key_hash(X509 *cert, ASN1_OCTET_STRING *hash)
        /* Hash the SPK, compare SPK hash with the SKI */
        if (hash->length < 0 || SIZE_MAX < hash->length) {
                return pr_err("%s length (%d) is out of bounds. (0-%zu)",
-                   SKI.name, hash->length, SIZE_MAX);
+                   ext_ski()->name, hash->length, SIZE_MAX);
        }
        if (spk_len < 0 || SIZE_MAX < spk_len) {
                return pr_err("Subject Public Key length (%d) is out of bounds. (0-%zu)",
@@ -202,7 +285,7 @@ validate_public_key_hash(X509 *cert, ASN1_OCTET_STRING *hash)
        error = hash_validate("sha1", hash->data, hash->length, spk, spk_len);
        if (error) {
                pr_err("The Subject Public Key's hash does not match the %s.",
-                   SKI.name);
+                   ext_ski()->name);
        }
 
        return error;
@@ -218,16 +301,16 @@ handle_aki(X509_EXTENSION *ext, void *arg)
 
        aki = X509V3_EXT_d2i(ext);
        if (aki == NULL)
-               return cannot_decode(&AKI);
+               return cannot_decode(ext_aki());
 
        if (aki->issuer != NULL) {
                error = pr_err("%s extension contains an authorityCertIssuer.",
-                   AKI.name);
+                   ext_aki()->name);
                goto end;
        }
        if (aki->serial != NULL) {
                error = pr_err("%s extension contains an authorityCertSerialNumber.",
-                   AKI.name);
+                   ext_aki()->name);
                goto end;
        }
 
index e8cd9cde4a4e2b070aa3afbdf1dbc4438c45f9ba..707c199174be681078703ce782ca5a02f1d4d676 100644 (file)
@@ -22,17 +22,21 @@ struct extension_handler {
        bool found;
 };
 
-extern const struct extension_metadata BC;
-extern const struct extension_metadata SKI;
-extern const struct extension_metadata AKI;
-extern const struct extension_metadata KU;
-extern const struct extension_metadata CDP;
-extern const struct extension_metadata AIA;
-extern const struct extension_metadata SIA;
-extern const struct extension_metadata CP;
-extern const struct extension_metadata IR;
-extern const struct extension_metadata AR;
-extern const struct extension_metadata CN;
+int extension_init(void);
+
+struct extension_metadata const *ext_bc(void);
+struct extension_metadata const *ext_ski(void);
+struct extension_metadata const *ext_aki(void);
+struct extension_metadata const *ext_ku(void);
+struct extension_metadata const *ext_cdp(void);
+struct extension_metadata const *ext_aia(void);
+struct extension_metadata const *ext_sia(void);
+struct extension_metadata const *ext_cp(void);
+struct extension_metadata const *ext_ir(void);
+struct extension_metadata const *ext_ar(void);
+struct extension_metadata const *ext_ir2(void);
+struct extension_metadata const *ext_ar2(void);
+struct extension_metadata const *ext_cn(void);
 
 int handle_extensions(struct extension_handler *,
     STACK_OF(X509_EXTENSION) const *);
index a1343da2ef4c748781e8c8064eb0cb8c8759dc21..cfc06c42246bbd13a16e980809f53a2de33adf23 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -45,21 +45,16 @@ pr_rm_indent(void)
 }
 
 
-#endif
-
 void
 pr_debug_prefix(void)
 {
-#ifdef DEBUG
        fprintf(STDOUT, "DBG: ");
        pr_indent(STDOUT);
-#endif
 }
 
 void
 pr_debug(const char *format, ...)
 {
-#ifdef DEBUG
        va_list args;
 
        pr_debug_prefix();
@@ -68,13 +63,11 @@ pr_debug(const char *format, ...)
        vfprintf(STDOUT, format, args);
        va_end(args);
        fprintf(STDOUT, "\n");
-#endif
 }
 
 void
 pr_debug_add(const char *format, ...)
 {
-#ifdef DEBUG
        va_list args;
 
        pr_debug_prefix();
@@ -85,13 +78,11 @@ pr_debug_add(const char *format, ...)
        fprintf(STDOUT, "\n");
 
        pr_add_indent();
-#endif
 }
 
 void
 pr_debug_rm(const char *format, ...)
 {
-#ifdef DEBUG
        va_list args;
 
        pr_rm_indent();
@@ -102,18 +93,19 @@ pr_debug_rm(const char *format, ...)
        vfprintf(STDOUT, format, args);
        va_end(args);
        fprintf(STDOUT, "\n");
-#endif
 }
 
+#endif
+
 static void
-pr_err_prefix(void)
+pr_prefix(char const *level)
 {
-       fprintf(STDERR, "ERR: ");
+       fprintf(STDERR, "%s: ", level);
        pr_indent(STDERR);
 }
 
-#define PR_ERR(args) do {                      \
-       pr_err_prefix();                        \
+#define PR_PREFIX(level, args) do {            \
+       pr_prefix(level);                       \
        pr_file_name(STDERR);                   \
                                                \
        va_start(args, format);                 \
@@ -121,6 +113,19 @@ pr_err_prefix(void)
        va_end(args);                           \
 } while (0)
 
+/**
+ * Always appends a newline at the end. Always returs 0. (So you can interrupt
+ * whatever you're doing without failing validation.)
+ */
+int
+pr_warn(const char *format, ...)
+{
+       va_list args;
+       PR_PREFIX("WRN", args);
+       fprintf(STDERR, "\n");
+       return 0;
+}
+
 /**
  * Always appends a newline at the end. Always returs -EINVAL.
  */
@@ -128,7 +133,7 @@ int
 pr_err(const char *format, ...)
 {
        va_list args;
-       PR_ERR(args);
+       PR_PREFIX("ERR", args);
        fprintf(STDERR, "\n");
        return -EINVAL;
 }
@@ -152,7 +157,7 @@ pr_errno(int error, const char *format, ...)
 {
        va_list args;
 
-       PR_ERR(args);
+       PR_PREFIX("ERR", args);
 
        if (error) {
                fprintf(STDERR, ": %s", strerror(error));
@@ -188,7 +193,7 @@ crypto_err(const char *format, ...)
        va_list args;
        int error;
 
-       PR_ERR(args);
+       PR_PREFIX("ERR", args);
        fprintf(STDERR, ": ");
 
        error = ERR_GET_REASON(ERR_peek_last_error());
@@ -223,7 +228,7 @@ pr_crit(const char *format, ...)
 {
        va_list args;
 
-       pr_err_prefix();
+       pr_prefix("CRT");
        pr_file_name(STDERR);
 
        fprintf(STDERR, "Programming error: ");
index 365ec403f28fa557d745f939dd64ce73a0631f49..fa002c178d4b70db95ce7f3899176f206c7b3997 100644 (file)
--- a/src/log.h
+++ b/src/log.h
  *   to ease debugging.
  */
 
+#ifdef DEBUG
+
 void pr_debug(const char *, ...);
 void pr_debug_add(const char *, ...);
 void pr_debug_rm(const char *, ...);
 void pr_debug_prefix(void);
 
+#else
+
+#define pr_debug(...)
+#define pr_debug_add(...)
+#define pr_debug_rm(...)
+#define pr_debug_prefix
+
+#endif
+
+int pr_warn(const char *, ...);
 int pr_err(const char *, ...);
 int pr_errno(int, const char *, ...);
 int crypto_err(const char *, ...);
index 0ec4ba5af2bc9d2844443178d232407541a656ff..c729b43ec7fc94ed6ce8525e89f5e31f1d72f5b4 100644 (file)
@@ -1,12 +1,13 @@
 #include <err.h>
 #include <errno.h>
 #include <getopt.h>
-#include <openssl/objects.h>
 
 #include "common.h"
 #include "config.h"
 #include "debug.h"
+#include "extension.h"
 #include "log.h"
+#include "nid.h"
 #include "rpp.h"
 #include "thread_var.h"
 #include "object/certificate.h"
 #include "object/tal.h"
 #include "rsync/rsync.h"
 
-/**
- * Registers the RPKI-specific OIDs in the SSL library.
- * LibreSSL needs it; not sure about OpenSSL.
- */
-static void
-add_rpki_oids(void)
-{
-       NID_rpkiManifest = OBJ_create("1.3.6.1.5.5.7.48.10",
-           "rpkiManifest",
-           "RPKI Manifest (RFC 6487)");
-       printf("rpkiManifest registered. Its nid is %d.\n", NID_rpkiManifest);
-
-       NID_signedObject = OBJ_create("1.3.6.1.5.5.7.48.11",
-           "signedObject",
-           "RPKI Signed Object (RFC 6487)");
-       printf("signedObject registered. Its nid is %d.\n", NID_signedObject);
-
-       NID_rpkiNotify = OBJ_create("1.3.6.1.5.5.7.48.13",
-           "rpkiNotify",
-           "RPKI Update Notification File (RFC 8182)");
-       printf("rpkiNotify registered. Its nid is %d.\n", NID_rpkiNotify);
-
-       NID_certPolicyRpki = OBJ_create("1.3.6.1.5.5.7.14.2",
-           "id-cp-ipAddr-asNumber (RFC 6484)",
-           "Certificate Policy (CP) for the Resource PKI (RPKI)");
-       printf("certPolicyRpki registered. Its nid is %d.\n", NID_certPolicyRpki);
-
-       /* TODO implement RFC 8360 */
-       NID_certPolicyRpkiV2 = OBJ_create("1.3.6.1.5.5.7.14.3",
-           "id-cp-ipAddr-asNumber-v2 (RFC 8360)",
-           "Certificate Policy for Use with Validation Reconsidered in the RPKI");
-       printf("certPolicyRpkiV2 registered. Its nid is %d.\n",
-           NID_certPolicyRpkiV2);
-}
-
 /**
  * Performs the whole validation walkthrough on uri @uri, which is assumed to
  * have been extracted from a TAL.
@@ -154,7 +120,7 @@ handle_args(int argc, char **argv)
        config.shuffle_uris = false;
        config.local_repository = NULL;
        config.tal = NULL;
-       config.maximum_certificate_depth = 32;
+       config.maximum_certificate_depth = 64;
 
        while ((opt = getopt_long(argc, argv, "t:l:rsm:", long_options, NULL))
            != -1) {
@@ -217,7 +183,12 @@ main(int argc, char **argv)
        if (error)
                return error;
 
-       add_rpki_oids();
+       error = nid_init();
+       if (error)
+               goto end;
+       error = extension_init();
+       if (error)
+               goto end;
        thvar_init();
        fnstack_store();
        fnstack_push(config_get_tal());
@@ -232,6 +203,7 @@ main(int argc, char **argv)
                tal_destroy(tal);
        }
 
+end:
        rsync_destroy();
        return error;
 }
diff --git a/src/nid.c b/src/nid.c
new file mode 100644 (file)
index 0000000..5decf80
--- /dev/null
+++ b/src/nid.c
@@ -0,0 +1,114 @@
+#include "nid.h"
+
+#include <errno.h>
+#include <openssl/objects.h>
+
+#include "log.h"
+
+static int NID_rpkiManifest;
+static int NID_signedObject;
+static int NID_rpkiNotify;
+static int NID_certPolicyRpki;
+static int NID_certPolicyRpkiV2;
+static int NID_ipAddrBlocksv2;
+static int NID_autonomousSysIdsv2;
+
+static int
+register_oid(const char *oid, const char *sn, const char *ln)
+{
+       int nid;
+
+       nid = OBJ_create(oid, sn, ln);
+       if (nid == 0)
+               return crypto_err("Unable to register the %s NID.", sn);
+
+       printf("%s registered. Its nid is %d.\n", sn, nid);
+       return nid;
+}
+
+/**
+ * Registers the RPKI-specific OIDs in the SSL library.
+ * LibreSSL needs it; not sure about OpenSSL.
+ */
+int
+nid_init(void)
+{
+       NID_rpkiManifest = register_oid("1.3.6.1.5.5.7.48.10",
+           "rpkiManifest",
+           "RPKI Manifest (RFC 6487)");
+       if (NID_rpkiManifest == 0)
+               return -EINVAL;
+
+       NID_signedObject = register_oid("1.3.6.1.5.5.7.48.11",
+           "signedObject",
+           "RPKI Signed Object (RFC 6487)");
+       if (NID_signedObject == 0)
+               return -EINVAL;
+
+       NID_rpkiNotify = register_oid("1.3.6.1.5.5.7.48.13",
+           "rpkiNotify",
+           "RPKI Update Notification File (RFC 8182)");
+       if (NID_rpkiNotify == 0)
+               return -EINVAL;
+
+       NID_certPolicyRpki = register_oid("1.3.6.1.5.5.7.14.2",
+           "id-cp-ipAddr-asNumber (RFC 6484)",
+           "Certificate Policy (CP) for the Resource PKI (RPKI)");
+       if (NID_certPolicyRpki == 0)
+               return -EINVAL;
+
+       NID_certPolicyRpkiV2 = register_oid("1.3.6.1.5.5.7.14.3",
+           "id-cp-ipAddr-asNumber-v2 (RFC 8360)",
+           "Certificate Policy for Use with Validation Reconsidered in the RPKI");
+       if (NID_certPolicyRpkiV2 == 0)
+               return -EINVAL;
+
+       NID_ipAddrBlocksv2 = register_oid("1.3.6.1.5.5.7.1.28",
+           "id-pe-ipAddrBlocks-v2",
+           "Amended IP Resources (RFC 8360)");
+       if (NID_ipAddrBlocksv2 == 0)
+               return -EINVAL;
+
+       NID_autonomousSysIdsv2 = register_oid("1.3.6.1.5.5.7.1.29",
+           "id-pe-autonomousSysIds-v2",
+           "Amended AS Resources (RFC 8360)");
+       if (NID_autonomousSysIdsv2 == 0)
+               return -EINVAL;
+
+       return 0;
+}
+
+int nid_rpkiManifest(void)
+{
+       return NID_rpkiManifest;
+}
+
+int nid_signedObject(void)
+{
+       return NID_signedObject;
+}
+
+int nid_rpkiNotify(void)
+{
+       return NID_rpkiNotify;
+}
+
+int nid_certPolicyRpki(void)
+{
+       return NID_certPolicyRpki;
+}
+
+int nid_certPolicyRpkiV2(void)
+{
+       return NID_certPolicyRpkiV2;
+}
+
+int nid_ipAddrBlocksv2(void)
+{
+       return NID_ipAddrBlocksv2;
+}
+
+int nid_autonomousSysIdsv2(void)
+{
+       return NID_autonomousSysIdsv2;
+}
diff --git a/src/nid.h b/src/nid.h
new file mode 100644 (file)
index 0000000..64cdac8
--- /dev/null
+++ b/src/nid.h
@@ -0,0 +1,14 @@
+#ifndef SRC_NID_H_
+#define SRC_NID_H_
+
+int nid_init(void);
+
+int nid_rpkiManifest(void);
+int nid_signedObject(void);
+int nid_rpkiNotify(void);
+int nid_certPolicyRpki(void);
+int nid_certPolicyRpkiV2(void);
+int nid_ipAddrBlocksv2(void);
+int nid_autonomousSysIdsv2(void);
+
+#endif /* SRC_NID_H_ */
index c8741becda72a4175e871a9375cc774b6bb41950..34bd3afe2d92b27032df917e5c8c20f877f941fe 100644 (file)
@@ -12,6 +12,7 @@
 #include "extension.h"
 #include "log.h"
 #include "manifest.h"
+#include "nid.h"
 #include "thread_var.h"
 #include "asn1/decode.h"
 #include "asn1/oid.h"
@@ -470,9 +471,12 @@ handle_asn_extension(X509_EXTENSION *ext, struct resources *resources)
 }
 
 int
-certificate_get_resources(X509 *cert, struct resources *resources)
+__certificate_get_resources(X509 *cert, struct resources *resources,
+    int addr_nid, int asn_nid, int bad_addr_nid, int bad_asn_nid,
+    char const *policy_rfc, char const *bad_ext_rfc)
 {
        X509_EXTENSION *ext;
+       int nid;
        int i;
        int error;
        bool ip_ext_found = false;
@@ -483,9 +487,9 @@ certificate_get_resources(X509 *cert, struct resources *resources)
 
        for (i = 0; i < X509_get_ext_count(cert); i++) {
                ext = X509_get_ext(cert, i);
+               nid = OBJ_obj2nid(X509_EXTENSION_get_object(ext));
 
-               switch (OBJ_obj2nid(X509_EXTENSION_get_object(ext))) {
-               case NID_sbgp_ipAddrBlock:
+               if (nid == addr_nid) {
                        if (ip_ext_found)
                                return pr_err("Multiple IP extensions found.");
                        if (!X509_EXTENSION_get_critical(ext))
@@ -498,9 +502,8 @@ certificate_get_resources(X509 *cert, struct resources *resources)
 
                        if (error)
                                return error;
-                       break;
 
-               case NID_sbgp_autonomousSysNum:
+               } else if (nid == asn_nid) {
                        if (asn_ext_found)
                                return pr_err("Multiple AS extensions found.");
                        if (!X509_EXTENSION_get_critical(ext))
@@ -513,7 +516,13 @@ certificate_get_resources(X509 *cert, struct resources *resources)
 
                        if (error)
                                return error;
-                       break;
+
+               } else if (nid == bad_addr_nid) {
+                       return pr_err("Certificate has an RFC%s policy, but contains an RFC%s IP extension.",
+                           policy_rfc, bad_ext_rfc);
+               } else if (nid == bad_asn_nid) {
+                       return pr_err("Certificate has an RFC%s policy, but contains an RFC%s ASN extension.",
+                           policy_rfc, bad_ext_rfc);
                }
        }
 
@@ -523,6 +532,28 @@ certificate_get_resources(X509 *cert, struct resources *resources)
        return 0;
 }
 
+int
+certificate_get_resources(X509 *cert, struct resources *resources)
+{
+       enum rpki_policy policy;
+
+       policy = resources_get_policy(resources);
+       switch (policy) {
+       case RPKI_POLICY_RFC6484:
+               return __certificate_get_resources(cert, resources,
+                   NID_sbgp_ipAddrBlock, NID_sbgp_autonomousSysNum,
+                   nid_ipAddrBlocksv2(), nid_autonomousSysIdsv2(),
+                   "6484", "8360");
+       case RPKI_POLICY_RFC8360:
+               return __certificate_get_resources(cert, resources,
+                   nid_ipAddrBlocksv2(), nid_autonomousSysIdsv2(),
+                   NID_sbgp_ipAddrBlock, NID_sbgp_autonomousSysNum,
+                   "8360", "6484");
+       }
+
+       return pr_crit("Unknown policy: %u", policy);
+}
+
 static bool
 is_rsync(ASN1_IA5STRING *uri)
 {
@@ -575,7 +606,7 @@ handle_bc(X509_EXTENSION *ext, void *arg)
 
        bc = X509V3_EXT_d2i(ext);
        if (bc == NULL)
-               return cannot_decode(&BC);
+               return cannot_decode(ext_bc());
 
        /*
         * 'The issuer determines whether the "cA" boolean is set.'
@@ -585,7 +616,8 @@ handle_bc(X509_EXTENSION *ext, void *arg)
 
        error = (bc->pathlen == NULL)
            ? 0
-           : pr_err("%s extension contains a Path Length Constraint.", BC.name);
+           : pr_err("%s extension contains a Path Length Constraint.",
+                 ext_bc()->name);
 
        BASIC_CONSTRAINTS_free(bc);
        return error;
@@ -599,7 +631,7 @@ handle_ski_ca(X509_EXTENSION *ext, void *arg)
 
        ski = X509V3_EXT_d2i(ext);
        if (ski == NULL)
-               return cannot_decode(&SKI);
+               return cannot_decode(ext_ski());
 
        error = validate_public_key_hash(arg, ski);
 
@@ -617,7 +649,7 @@ handle_ski_ee(X509_EXTENSION *ext, void *arg)
 
        ski = X509V3_EXT_d2i(ext);
        if (ski == NULL)
-               return cannot_decode(&SKI);
+               return cannot_decode(ext_ski());
 
        args = arg;
        error = validate_public_key_hash(args->cert, ski);
@@ -673,16 +705,16 @@ handle_aki_ta(X509_EXTENSION *aki, void *arg)
 
        for (i = 0; i < X509_get_ext_count(cert); i++) {
                other = X509_get_ext(cert, i);
-               if (OBJ_obj2nid(X509_EXTENSION_get_object(other)) == SKI.nid) {
+               if (OBJ_obj2nid(X509_EXTENSION_get_object(other)) == ext_ski()->nid) {
                        if (extension_equals(aki, other))
                                return 0;
 
                        return pr_err("The '%s' does not equal the '%s'.",
-                           AKI.name, SKI.name);
+                           ext_aki()->name, ext_ski()->name);
                }
        }
 
-       pr_err("Certificate lacks the '%s' extension.", SKI.name);
+       pr_err("Certificate lacks the '%s' extension.", ext_ski()->name);
        return -ESRCH;
 }
 
@@ -701,10 +733,11 @@ handle_ku(X509_EXTENSION *ext, unsigned char byte1)
 
        ku = X509V3_EXT_d2i(ext);
        if (ku == NULL)
-               return cannot_decode(&KU);
+               return cannot_decode(ext_ku());
 
        if (ku->length == 0) {
-               error = pr_err("%s bit string has no enabled bits.", KU.name);
+               error = pr_err("%s bit string has no enabled bits.",
+                   ext_ku()->name);
                goto end;
        }
 
@@ -752,11 +785,11 @@ handle_cdp(X509_EXTENSION *ext, void *arg)
 
        crldp = X509V3_EXT_d2i(ext);
        if (crldp == NULL)
-               return cannot_decode(&CDP);
+               return cannot_decode(ext_cdp());
 
        if (sk_DIST_POINT_num(crldp) != 1) {
                error = pr_err("The %s extension has %u distribution points. (1 expected)",
-                   CDP.name, sk_DIST_POINT_num(crldp));
+                   ext_cdp()->name, sk_DIST_POINT_num(crldp));
                goto end;
        }
 
@@ -814,8 +847,8 @@ handle_cdp(X509_EXTENSION *ext, void *arg)
        error_msg = "lacks an RSYNC URI";
 
 dist_point_error:
-       error = pr_err("The %s extension's distribution point %s.", CDP.name,
-           error_msg);
+       error = pr_err("The %s extension's distribution point %s.",
+           ext_cdp()->name, error_msg);
 
 end:
        sk_DIST_POINT_pop_free(crldp, DIST_POINT_free);
@@ -910,7 +943,7 @@ handle_aia(X509_EXTENSION *ext, void *arg)
 
        aia = X509V3_EXT_d2i(ext);
        if (aia == NULL)
-               return cannot_decode(&AIA);
+               return cannot_decode(ext_aia());
 
        error = handle_ad("AIA", aia, "caIssuers", NID_ad_ca_issuers,
            handle_caIssuers, arg);
@@ -927,7 +960,7 @@ handle_sia_ca(X509_EXTENSION *ext, void *arg)
 
        sia = X509V3_EXT_d2i(ext);
        if (sia == NULL)
-               return cannot_decode(&SIA);
+               return cannot_decode(ext_sia());
 
        /* rsync */
        error = handle_ad("SIA", sia, "caRepository", NID_caRepository,
@@ -940,7 +973,7 @@ handle_sia_ca(X509_EXTENSION *ext, void *arg)
         * (We won't actually touch the manifest until we know the certificate
         * is fully valid.)
         */
-       error = handle_ad("SIA", sia, "rpkiManifest",NID_rpkiManifest,
+       error = handle_ad("SIA", sia, "rpkiManifest", nid_rpkiManifest(),
            handle_rpkiManifest, arg);
 
 end:
@@ -956,9 +989,9 @@ handle_sia_ee(X509_EXTENSION *ext, void *arg)
 
        sia = X509V3_EXT_d2i(ext);
        if (sia == NULL)
-               return cannot_decode(&SIA);
+               return cannot_decode(ext_sia());
 
-       error = handle_ad("SIA", sia, "signedObject", NID_signedObject,
+       error = handle_ad("SIA", sia, "signedObject", nid_signedObject(),
            handle_signedObject, arg);
 
        AUTHORITY_INFO_ACCESS_free(sia);
@@ -968,6 +1001,7 @@ handle_sia_ee(X509_EXTENSION *ext, void *arg)
 static int
 handle_cp(X509_EXTENSION *ext, void *arg)
 {
+       enum rpki_policy *policy = arg;
        CERTIFICATEPOLICIES *cp;
        POLICYINFO *pi;
        POLICYQUALINFO *pqi;
@@ -976,21 +1010,29 @@ handle_cp(X509_EXTENSION *ext, void *arg)
        error = 0;
        cp = X509V3_EXT_d2i(ext);
        if (cp == NULL)
-               return cannot_decode(&CP);
+               return cannot_decode(ext_cp());
 
        if (sk_POLICYINFO_num(cp) != 1) {
                error = pr_err("The %s extension has %u policy information's. (1 expected)",
-                   CP.name, sk_POLICYINFO_num(cp));
+                   ext_cp()->name, sk_POLICYINFO_num(cp));
                goto end;
        }
 
        /* rfc7318#section-2 and consider rfc8360#section-4.2.1 */
        pi = sk_POLICYINFO_value(cp, 0);
        nid_cp = OBJ_obj2nid(pi->policyid);
-       if (nid_cp != NID_certPolicyRpki && nid_cp != NID_certPolicyRpkiV2) {
+       if (nid_cp == nid_certPolicyRpki()) {
+               if (policy != NULL)
+                       *policy = RPKI_POLICY_RFC6484;
+       } else if (nid_cp == nid_certPolicyRpkiV2()) {
+               pr_debug("Found RFC8360 policy!");
+               if (policy != NULL)
+                       *policy = RPKI_POLICY_RFC8360;
+       } else {
                error = pr_err("Invalid certificate policy OID, isn't 'id-cp-ipAddr-asNumber' nor 'id-cp-ipAddr-asNumber-v2'");
                goto end;
        }
+
        /* Exactly one policy qualifier MAY be included (so none is also valid) */
        if (pi->qualifiers == NULL)
                goto end;
@@ -1000,7 +1042,7 @@ handle_cp(X509_EXTENSION *ext, void *arg)
                goto end;
        if (pqi_num != 1) {
                error = pr_err("The %s extension has %d policy qualifiers. (none or only 1 expected)",
-                   CP.name, pqi_num);
+                   ext_cp()->name, pqi_num);
                goto end;
        }
 
@@ -1028,18 +1070,21 @@ handle_ar(X509_EXTENSION *ext, void *arg)
 }
 
 int
-certificate_validate_extensions_ta(X509 *cert, struct rpki_uri *mft)
+certificate_validate_extensions_ta(X509 *cert, struct rpki_uri *mft,
+    enum rpki_policy *policy)
 {
        struct extension_handler handlers[] = {
-          /* ext   reqd   handler        arg       */
-           { &BC,  true,  handle_bc,               },
-           { &SKI, true,  handle_ski_ca, cert      },
-           { &AKI, false, handle_aki_ta, cert      },
-           { &KU,  true,  handle_ku_ca,            },
-           { &SIA, true,  handle_sia_ca, mft       },
-           { &CP,  true,  handle_cp,               },
-           { &IR,  false, handle_ir,               },
-           { &AR,  false, handle_ar,               },
+          /* ext        reqd   handler        arg       */
+           { ext_bc(),  true,  handle_bc,               },
+           { ext_ski(), true,  handle_ski_ca, cert      },
+           { ext_aki(), false, handle_aki_ta, cert      },
+           { ext_ku(),  true,  handle_ku_ca,            },
+           { ext_sia(), true,  handle_sia_ca, mft       },
+           { ext_cp(),  true,  handle_cp,               },
+           { ext_ir(),  false, handle_ir,               },
+           { ext_ar(),  false, handle_ar,               },
+           { ext_ir2(), false, handle_ir,               },
+           { ext_ar2(), false, handle_ar,               },
            { NULL },
        };
 
@@ -1048,20 +1093,22 @@ certificate_validate_extensions_ta(X509 *cert, struct rpki_uri *mft)
 
 int
 certificate_validate_extensions_ca(X509 *cert, struct rpki_uri *mft,
-    struct certificate_refs *refs)
+    struct certificate_refs *refs, enum rpki_policy *policy)
 {
        struct extension_handler handlers[] = {
-          /* ext   reqd   handler        arg       */
-           { &BC,  true,  handle_bc,               },
-           { &SKI, true,  handle_ski_ca, cert      },
-           { &AKI, true,  handle_aki,              },
-           { &KU,  true,  handle_ku_ca,            },
-           { &CDP, true,  handle_cdp,    refs      },
-           { &AIA, true,  handle_aia,    refs      },
-           { &SIA, true,  handle_sia_ca, mft       },
-           { &CP,  true,  handle_cp,               },
-           { &IR,  false, handle_ir,               },
-           { &AR,  false, handle_ar,               },
+          /* ext        reqd   handler        arg       */
+           { ext_bc(),  true,  handle_bc,               },
+           { ext_ski(), true,  handle_ski_ca, cert      },
+           { ext_aki(), true,  handle_aki,              },
+           { ext_ku(),  true,  handle_ku_ca,            },
+           { ext_cdp(), true,  handle_cdp,    refs      },
+           { ext_aia(), true,  handle_aia,    refs      },
+           { ext_sia(), true,  handle_sia_ca, mft       },
+           { ext_cp(),  true,  handle_cp,               },
+           { ext_ir(),  false, handle_ir,               },
+           { ext_ar(),  false, handle_ar,               },
+           { ext_ir2(), false, handle_ir,               },
+           { ext_ar2(), false, handle_ar,               },
            { NULL },
        };
 
@@ -1070,20 +1117,22 @@ certificate_validate_extensions_ca(X509 *cert, struct rpki_uri *mft,
 
 int
 certificate_validate_extensions_ee(X509 *cert, OCTET_STRING_t *sid,
-    struct certificate_refs *refs)
+    struct certificate_refs *refs, enum rpki_policy *policy)
 {
        struct ski_arguments ski_args;
        struct extension_handler handlers[] = {
-          /* ext   reqd   handler        arg */
-           { &SKI, true,  handle_ski_ee, &ski_args },
-           { &AKI, true,  handle_aki,              },
-           { &KU,  true,  handle_ku_ee,            },
-           { &CDP, true,  handle_cdp,    refs      },
-           { &AIA, true,  handle_aia,    refs      },
-           { &SIA, true,  handle_sia_ee, refs      },
-           { &CP,  true,  handle_cp,               },
-           { &IR,  false, handle_ir,               },
-           { &AR,  false, handle_ar,               },
+          /* ext        reqd   handler        arg       */
+           { ext_ski(), true,  handle_ski_ee, &ski_args },
+           { ext_aki(), true,  handle_aki,              },
+           { ext_ku(),  true,  handle_ku_ee,            },
+           { ext_cdp(), true,  handle_cdp,    refs      },
+           { ext_aia(), true,  handle_aia,    refs      },
+           { ext_sia(), true,  handle_sia_ee, refs      },
+           { ext_cp(),  true,  handle_cp,     policy    },
+           { ext_ir(),  false, handle_ir,               },
+           { ext_ar(),  false, handle_ar,               },
+           { ext_ir2(), false, handle_ir,               },
+           { ext_ar2(), false, handle_ar,               },
            { NULL },
        };
 
@@ -1102,6 +1151,7 @@ certificate_traverse(struct rpp *rpp_parent, struct rpki_uri const *cert_uri,
        X509 *cert;
        struct rpki_uri mft;
        struct certificate_refs refs;
+       enum rpki_policy policy;
        struct rpp *pp;
        int error;
 
@@ -1129,8 +1179,8 @@ certificate_traverse(struct rpp *rpp_parent, struct rpki_uri const *cert_uri,
        if (error)
                goto end2;
        error = is_ta
-           ? certificate_validate_extensions_ta(cert, &mft)
-           : certificate_validate_extensions_ca(cert, &mft, &refs);
+           ? certificate_validate_extensions_ta(cert, &mft, &policy)
+           : certificate_validate_extensions_ca(cert, &mft, &refs, &policy);
        if (error)
                goto end2;
 
@@ -1139,7 +1189,7 @@ certificate_traverse(struct rpp *rpp_parent, struct rpki_uri const *cert_uri,
                goto end3;
 
        /* -- Validate the manifest (@mft) pointed by the certificate -- */
-       error = validation_push_cert(state, cert_uri, cert, is_ta);
+       error = validation_push_cert(state, cert_uri, cert, policy, is_ta);
        if (error)
                goto end3;
 
index 57456834c62c417a42499d472a6e0293626ab9a6..5b87e3ea0af816900d57f3f25332ed62e65abafa 100644 (file)
@@ -34,7 +34,8 @@ int certificate_get_resources(X509 *, struct resources *);
  * Also initializes the second argument as the URI of the rpkiManifest Access
  * Description from the SIA extension.
  */
-int certificate_validate_extensions_ta(X509 *, struct rpki_uri *);
+int certificate_validate_extensions_ta(X509 *, struct rpki_uri *,
+    enum rpki_policy *);
 /**
  * Validates the certificate extensions, (intermediate) Certificate Authority
  * style.
@@ -45,7 +46,7 @@ int certificate_validate_extensions_ta(X509 *, struct rpki_uri *);
  * extensions.
  */
 int certificate_validate_extensions_ca(X509 *, struct rpki_uri *,
-    struct certificate_refs *);
+    struct certificate_refs *, enum rpki_policy *);
 /**
  * Validates the certificate extensions, End-Entity style.
  *
@@ -53,7 +54,7 @@ int certificate_validate_extensions_ca(X509 *, struct rpki_uri *,
  * extensions.
  */
 int certificate_validate_extensions_ee(X509 *, OCTET_STRING_t *,
-    struct certificate_refs *);
+    struct certificate_refs *, enum rpki_policy *);
 
 int certificate_traverse(struct rpp *, struct rpki_uri const *,
     STACK_OF(X509_CRL) *, bool);
index 913386bcd87560ea1d8952f01cc09578c4275e81..8bd2caa77ba7710a8a35a05ce1923b840ce84ef6 100644 (file)
@@ -49,7 +49,7 @@ validate_revoked(X509_CRL *crl)
 
        revoked_stack = X509_CRL_get_REVOKED(crl);
        if (revoked_stack == NULL)
-               return pr_err("Likely programming error: CRL revoked stack is NULL.");
+               return 0; /* Guess the RFC doesn't enforce this thing. */
 
        for (i = 0; i < sk_X509_REVOKED_num(revoked_stack); i++) {
                revoked = sk_X509_REVOKED_value(revoked_stack, i);
@@ -102,8 +102,8 @@ validate_extensions(X509_CRL *crl)
 {
        struct extension_handler handlers[] = {
           /* ext   reqd   handler        arg */
-           { &AKI, true,  handle_aki,              },
-           { &CN,  true,  handle_crlnum,           },
+           { ext_aki(), true,  handle_aki,              },
+           { ext_cn(),  true,  handle_crlnum,           },
            { NULL },
        };
 
index 0248f5749672187053e09c1439071ac62fdeb6cd..e31a4844c9c22135d805c069b871eeed07eecd70 100644 (file)
@@ -31,7 +31,7 @@ print_addr4(struct resources *parent, unsigned long asn,
                        return pr_err("The ROA's IPv4 maxLength isn't a valid unsigned long");
                }
 
-               if (max_length < 0 || 32 < max_length) {
+               if (max_length > 32) {
                        return pr_err("maxLength (%lu) is out of bounds (0-32).",
                            max_length);
                }
@@ -83,7 +83,7 @@ print_addr6(struct resources *parent, unsigned long asn,
                        return pr_err("The ROA's IPv6 maxLength isn't a valid unsigned long");
                }
 
-               if (max_length < 0 || 128 < max_length) {
+               if (max_length > 128) {
                        return pr_err("maxLength (%lu) is out of bounds (0-128).",
                            max_length);
                }
index 83ba33f0c544784f8d5de42a5760c0888a60182f..dd3733b30a3d4426a3fb33ce0d1e0b4b4c85199f 100644 (file)
@@ -1,7 +1,6 @@
 #include "resource.h"
 
 #include <errno.h>
-#include <arpa/inet.h>
 #include <stdint.h> /* UINT32_MAX */
 
 #include "address.h"
@@ -17,6 +16,7 @@ struct resources {
        struct resources_ipv4 *ip4s;
        struct resources_ipv6 *ip6s;
        struct resources_asn *asns;
+       enum rpki_policy policy;
 };
 
 struct resources *
@@ -31,6 +31,7 @@ resources_create(void)
        result->ip4s = NULL;
        result->ip6s = NULL;
        result->asns = NULL;
+       result->policy = RPKI_POLICY_RFC6484;
 
        return result;
 }
@@ -78,48 +79,6 @@ get_parent_resources(void)
        return (state != NULL) ? validation_peek_resource(state) : NULL;
 }
 
-static void
-pr_debug_ip_prefix(int family, void *addr, unsigned int length)
-{
-#ifdef DEBUG
-       char buffer[INET6_ADDRSTRLEN];
-       char const *string;
-
-       string = inet_ntop(family, addr, buffer, sizeof(buffer));
-       if (string != NULL)
-               pr_debug("Prefix: %s/%u", string, length);
-       else {
-               pr_debug("Prefix: (Cannot convert to string. Errcode %d)",
-                   errno);
-       }
-#endif
-}
-
-static void
-pr_debug_range(int family, void *min, void *max)
-{
-#ifdef DEBUG
-       char buffer_min[INET6_ADDRSTRLEN];
-       char buffer_max[INET6_ADDRSTRLEN];
-       char const *string_min;
-       char const *string_max;
-
-       string_min = inet_ntop(family, min, buffer_min, sizeof(buffer_min));
-       if (string_min == NULL)
-               goto fail;
-
-       string_max = inet_ntop(family, max, buffer_max, sizeof(buffer_max));
-       if (string_max == NULL)
-               goto fail;
-
-       pr_debug("Range: %s-%s", string_min, string_max);
-       return;
-
-fail:
-       pr_debug("Range: (Cannot convert to string. Errcode %d)", errno);
-#endif
-}
-
 static int
 inherit_aors(struct resources *resources, int family)
 {
@@ -170,8 +129,16 @@ add_prefix4(struct resources *resources, IPAddress2_t *addr)
        if (error)
                return error;
 
-       if (parent && !res4_contains_prefix(parent->ip4s, &prefix))
-               return pr_err("Parent certificate doesn't own child's IPv4 resource.");
+       if (parent && !res4_contains_prefix(parent->ip4s, &prefix)) {
+               switch (resources->policy) {
+               case RPKI_POLICY_RFC6484:
+                       return pr_err("Parent certificate doesn't own IPv4 prefix '%s/%u'.",
+                           v4addr2str(&prefix.addr), prefix.len);
+               case RPKI_POLICY_RFC8360:
+                       return pr_warn("Certificate is overclaiming the IPv4 prefix '%s/%u'.",
+                           v4addr2str(&prefix.addr), prefix.len);
+               }
+       }
 
        if (resources->ip4s == NULL) {
                resources->ip4s = res4_create();
@@ -181,12 +148,13 @@ add_prefix4(struct resources *resources, IPAddress2_t *addr)
 
        error = res4_add_prefix(resources->ip4s, &prefix);
        if (error) {
-               pr_err("Error adding IPv4 prefix to certificate resources: %s",
+               pr_err("Error adding IPv4 prefix '%s/%u' to certificate resources: %s",
+                   v4addr2str(&prefix.addr), prefix.len,
                    sarray_err2str(error));
                return error;
        }
 
-       pr_debug_ip_prefix(AF_INET, &prefix.addr, prefix.len);
+       pr_debug("Prefix: %s/%u", v4addr2str(&prefix.addr), prefix.len);
        return 0;
 }
 
@@ -206,8 +174,16 @@ add_prefix6(struct resources *resources, IPAddress2_t *addr)
        if (error)
                return error;
 
-       if (parent && !res6_contains_prefix(parent->ip6s, &prefix))
-               return pr_err("Parent certificate doesn't own child's IPv6 resource.");
+       if (parent && !res6_contains_prefix(parent->ip6s, &prefix)) {
+               switch (resources->policy) {
+               case RPKI_POLICY_RFC6484:
+                       return pr_err("Parent certificate doesn't own IPv6 prefix '%s/%u'.",
+                           v6addr2str(&prefix.addr), prefix.len);
+               case RPKI_POLICY_RFC8360:
+                       return pr_warn("Certificate is overclaiming the IPv6 prefix '%s/%u'.",
+                           v6addr2str(&prefix.addr), prefix.len);
+               }
+       }
 
        if (resources->ip6s == NULL) {
                resources->ip6s = res6_create();
@@ -217,12 +193,13 @@ add_prefix6(struct resources *resources, IPAddress2_t *addr)
 
        error = res6_add_prefix(resources->ip6s, &prefix);
        if (error) {
-               pr_err("Error adding IPv6 prefix to certificate resources: %s",
+               pr_err("Error adding IPv6 prefix '%s/%u' to certificate resources: %s",
+                   v6addr2str(&prefix.addr), prefix.len,
                    sarray_err2str(error));
                return error;
        }
 
-       pr_debug_ip_prefix(AF_INET6, &prefix.addr, prefix.len);
+       pr_debug("Prefix: %s/%u", v6addr2str(&prefix.addr), prefix.len);
        return 0;
 }
 
@@ -255,8 +232,16 @@ add_range4(struct resources *resources, IPAddressRange_t *input)
        if (error)
                return error;
 
-       if (parent && !res4_contains_range(parent->ip4s, &range))
-               return pr_err("Parent certificate doesn't own child's IPv4 resource.");
+       if (parent && !res4_contains_range(parent->ip4s, &range)) {
+               switch (resources->policy) {
+               case RPKI_POLICY_RFC6484:
+                       return pr_err("Parent certificate doesn't own IPv4 range '%s-%s'.",
+                           v4addr2str(&range.min), v4addr2str2(&range.max));
+               case RPKI_POLICY_RFC8360:
+                       return pr_warn("Certificate is overclaiming the IPv4 range '%s-%s'.",
+                           v4addr2str(&range.min), v4addr2str2(&range.max));
+               }
+       }
 
        if (resources->ip4s == NULL) {
                resources->ip4s = res4_create();
@@ -266,12 +251,14 @@ add_range4(struct resources *resources, IPAddressRange_t *input)
 
        error = res4_add_range(resources->ip4s, &range);
        if (error) {
-               pr_err("Error adding IPv4 range to certificate resources: %s",
+               pr_err("Error adding IPv4 range '%s-%s' to certificate resources: %s",
+                   v4addr2str(&range.min), v4addr2str2(&range.max),
                    sarray_err2str(error));
                return error;
        }
 
-       pr_debug_range(AF_INET, &range.min, &range.max);
+       pr_debug("Range: %s-%s", v4addr2str(&range.min),
+           v4addr2str2(&range.max));
        return 0;
 }
 
@@ -291,8 +278,16 @@ add_range6(struct resources *resources, IPAddressRange_t *input)
        if (error)
                return error;
 
-       if (parent && !res6_contains_range(parent->ip6s, &range))
-               return pr_err("Parent certificate doesn't own child's IPv6 resource.");
+       if (parent && !res6_contains_range(parent->ip6s, &range)) {
+               switch (resources->policy) {
+               case RPKI_POLICY_RFC6484:
+                       return pr_err("Parent certificate doesn't own IPv6 range '%s-%s'.",
+                           v6addr2str(&range.min), v6addr2str2(&range.max));
+               case RPKI_POLICY_RFC8360:
+                       return pr_warn("Certificate is overclaiming the IPv6 range '%s-%s'.",
+                           v6addr2str(&range.min), v6addr2str2(&range.max));
+               }
+       }
 
        if (resources->ip6s == NULL) {
                resources->ip6s = res6_create();
@@ -302,12 +297,14 @@ add_range6(struct resources *resources, IPAddressRange_t *input)
 
        error = res6_add_range(resources->ip6s, &range);
        if (error) {
-               pr_err("Error adding IPv6 range to certificate resources: %s",
+               pr_err("Error adding IPv6 range '%s-%s' to certificate resources: %s",
+                   v6addr2str(&range.min), v6addr2str2(&range.max),
                    sarray_err2str(error));
                return error;
        }
 
-       pr_debug_range(AF_INET6, &range.min, &range.max);
+       pr_debug("Range: %s-%s", v6addr2str(&range.min),
+           v6addr2str2(&range.max));
        return 0;
 }
 
@@ -332,6 +329,9 @@ add_aors(struct resources *resources, int family,
        int i;
        int error;
 
+       if (aors->list.count == 0)
+               return pr_err("IP extension's set of IP address records is empty.");
+
        for (i = 0; i < aors->list.count; i++) {
                aor = aors->list.array[i];
                switch (aor->present) {
@@ -431,8 +431,16 @@ add_asn(struct resources *resources, unsigned long min, unsigned long max,
        if (min > max)
                return pr_err("The ASN range %lu-%lu is inverted.", min, max);
 
-       if (parent && !rasn_contains(parent->asns, min, max))
-               return pr_err("Parent certificate doesn't own child's ASN resource.");
+       if (parent && !rasn_contains(parent->asns, min, max)) {
+               switch (resources->policy) {
+               case RPKI_POLICY_RFC6484:
+                       return pr_err("Parent certificate doesn't own ASN range '%lu-%lu'.",
+                           min, max);
+               case RPKI_POLICY_RFC8360:
+                       return pr_warn("Certificate is overclaiming the ASN range '%lu-%lu'.",
+                           min, max);
+               }
+       }
 
        if (resources->asns == NULL) {
                resources->asns = rasn_create();
@@ -442,8 +450,8 @@ add_asn(struct resources *resources, unsigned long min, unsigned long max,
 
        error = rasn_add(resources->asns, min, max);
        if (error){
-               pr_err("Error adding ASN range to certificate resources: %s",
-                   sarray_err2str(error));
+               pr_err("Error adding ASN range '%lu-%lu' to certificate resources: %s",
+                   min, max, sarray_err2str(error));
                return error;
        }
 
@@ -507,6 +515,8 @@ resources_add_asn(struct resources *resources, struct ASIdentifiers *ids)
                return inherit_asiors(resources);
        case ASIdentifierChoice_PR_asIdsOrRanges:
                iors = &ids->asnum->choice.asIdsOrRanges;
+               if (iors->list.count == 0)
+                       return pr_err("AS extension's set of AS number records is empty.");
                for (i = 0; i < iors->list.count; i++) {
                        error = add_asior(resources, iors->list.array[i]);
                        if (error)
@@ -547,3 +557,14 @@ resources_contains_ipv6(struct resources *res, struct ipv6_prefix *prefix)
        return res6_contains_prefix(res->ip6s, prefix);
 }
 
+enum rpki_policy
+resources_get_policy(struct resources *res)
+{
+       return res->policy;
+}
+
+void
+resources_set_policy(struct resources *res, enum rpki_policy policy)
+{
+       res->policy = policy;
+}
index fa1acb87a8b4e4f92834c2adad3ccf7a2ff7eb2b..62101da5097779145f8443b928ddf3c20c115ad0 100644 (file)
@@ -6,6 +6,19 @@
 #include <libcmscodec/IPAddressFamily.h>
 #include "address.h"
 
+enum rpki_policy {
+       /**
+        * If certificate `x`'s resources are not a subset of `x - 1`'s
+        * resources, then `x` is to be rejected.
+        */
+       RPKI_POLICY_RFC6484,
+       /**
+        * If certificate `x`'s resources are not a subset of `x - 1`'s
+        * resources, then the overclaiming resources are to be ignored.
+        */
+       RPKI_POLICY_RFC8360,
+};
+
 int get_addr_family(OCTET_STRING_t *);
 
 struct resources;
@@ -21,4 +34,7 @@ bool resources_contains_asn(struct resources *, unsigned long);
 bool resources_contains_ipv4(struct resources *, struct ipv4_prefix *);
 bool resources_contains_ipv6(struct resources *, struct ipv6_prefix *);
 
+enum rpki_policy resources_get_policy(struct resources *);
+void resources_set_policy(struct resources *, enum rpki_policy);
+
 #endif /* SRC_RESOURCE_H_ */
index 140f0961eb55c4374947888df5891aed5a393317..f1902e6791d363841b1e5517fdf1645d802d8847 100644 (file)
@@ -32,7 +32,7 @@ static void
 pton(struct ipv4_prefix *p, struct r4_node *n)
 {
        n->min = ntohl(p->addr.s_addr);
-       n->max = n->min | (0xFFFFFFFFu >> p->len);
+       n->max = n->min | u32_suffix_mask(p->len);
 }
 
 static void
index ccb7c5094499c81d69078d1cb7c1bdabb969ec6a..a8b94650104a8bf5b259a1743abbb508ea16e3d2 100644 (file)
@@ -62,6 +62,16 @@ struct validation {
 
        /* Did the TAL's public key match the root certificate's public key? */
        enum pubkey_state pubkey_state;
+
+       /**
+        * Two buffers calling code will store stringified IP addresses in,
+        * to prevent proliferation of similar buffers on the stack.
+        *
+        * They are meant to be large enough to contain both IPv4 and IPv6
+        * addresses.
+        */
+       char addr_buffer1[INET6_ADDRSTRLEN];
+       char addr_buffer2[INET6_ADDRSTRLEN];
 };
 
 /*
@@ -224,7 +234,7 @@ enum pubkey_state validation_pubkey_state(struct validation *state)
  */
 int
 validation_push_cert(struct validation *state, struct rpki_uri const *cert_uri,
-    X509 *x509, bool is_ta)
+    X509 *x509, enum rpki_policy policy, bool is_ta)
 {
        struct certificate *cert;
        int ok;
@@ -249,6 +259,7 @@ validation_push_cert(struct validation *state, struct rpki_uri const *cert_uri,
                goto end4;
        }
 
+       resources_set_policy(cert->resources, policy);
        error = certificate_get_resources(x509, cert->resources);
        if (error)
                goto end5;
@@ -376,3 +387,15 @@ validation_store_subject(struct validation *state, char *subject)
 
        return error;
 }
+
+char *
+validation_get_ip_buffer1(struct validation *state)
+{
+       return state->addr_buffer1;
+}
+
+char *
+validation_get_ip_buffer2(struct validation *state)
+{
+       return state->addr_buffer2;
+}
index 4e3b150612876840ee81b354ea5f77a6398c50a1..9ff7809b7027ca954c6ccc6d35b98e1a4e3fe820 100644 (file)
@@ -25,7 +25,7 @@ void validation_pubkey_invalid(struct validation *);
 enum pubkey_state validation_pubkey_state(struct validation *);
 
 int validation_push_cert(struct validation *, struct rpki_uri const *, X509 *,
-    bool);
+    enum rpki_policy, bool);
 int validation_pop_cert(struct validation *);
 X509 *validation_peek_cert(struct validation *);
 struct rpki_uri const *validation_peek_cert_uri(struct validation *);
@@ -35,4 +35,7 @@ struct resources *validation_peek_resource(struct validation *);
 int validation_store_serial_number(struct validation *, BIGNUM *);
 int validation_store_subject(struct validation *, char *);
 
+char *validation_get_ip_buffer1(struct validation *);
+char *validation_get_ip_buffer2(struct validation *);
+
 #endif /* SRC_STATE_H_ */
index dd7ca94338174a2be4fb0c68e1f49749b643804c..056be6f35b5f1907cd884b768365cec86112934b 100644 (file)
@@ -5,6 +5,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <arpa/inet.h>
 
 static pthread_key_t state_key;
 static pthread_key_t filenames_key;
@@ -173,3 +174,58 @@ fnstack_pop(void)
 
        files->len--;
 }
+
+static char const *
+addr2str(int af, void *addr, char *(*buffer_cb)(struct validation *))
+{
+       struct validation *state;
+
+       state = state_retrieve();
+       if (!state)
+               return NULL;
+
+       return inet_ntop(af, addr, buffer_cb(state), INET6_ADDRSTRLEN);
+}
+
+/**
+ * Returns @addr, converted to a printable string. Intended for minimal clutter
+ * address printing.
+ *
+ * The buffer the string is stored in was allocated in a thread variable, so it
+ * will be overridden the next time you call this function. Also, you should not
+ * free it.
+ *
+ * The buffer is the same as v6addr2str()'s, so don't mix them either.
+ */
+char const *
+v4addr2str(struct in_addr *addr)
+{
+       return addr2str(AF_INET, addr, validation_get_ip_buffer1);
+}
+
+/**
+ * Same as v4addr2str(), except a different buffer is used.
+ */
+char const *
+v4addr2str2(struct in_addr *addr)
+{
+       return addr2str(AF_INET, addr, validation_get_ip_buffer2);
+}
+
+/**
+ * See v4addr2str().
+ */
+char const *
+v6addr2str(struct in6_addr *addr)
+{
+       return addr2str(AF_INET6, addr, validation_get_ip_buffer1);
+}
+
+/**
+ * See v4addr2str2().
+ */
+char const *
+v6addr2str2(struct in6_addr *addr)
+{
+       return addr2str(AF_INET6, addr, validation_get_ip_buffer2);
+}
index c0cea0bee5f0642c39f5167e515aeb81fb8ff19b..868cc6ea43954af8582992bb72bac928ee608640 100644 (file)
@@ -13,4 +13,10 @@ void fnstack_push(char const *);
 char const *fnstack_peek(void);
 void fnstack_pop(void);
 
+/* TODO use these more, to print better error messages. */
+char const *v4addr2str(struct in_addr *addr);
+char const *v4addr2str2(struct in_addr *addr);
+char const *v6addr2str(struct in6_addr *addr);
+char const *v6addr2str2(struct in6_addr *addr);
+
 #endif /* SRC_THREAD_VAR_H_ */