]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Read and validate BGPsec router certificates
authorpcarana <pc.moreno2099@gmail.com>
Wed, 10 Jul 2019 22:48:31 +0000 (17:48 -0500)
committerpcarana <pc.moreno2099@gmail.com>
Wed, 10 Jul 2019 22:48:31 +0000 (17:48 -0500)
-Prepare structs and functions to send RTRv1 router key PDUs.
-Basic preparation to store router keys, still needs more work.
-Validate BGPsec certificates based on RFCs 8209 and 8608.
-Configure RTRv1 intervals (refresh, retry, expire), more validations and logic are pending.
-Update sorted array to allow iterations on its elements.

34 files changed:
src/Makefile.am
src/algorithm.c
src/algorithm.h
src/asn1/signed_data.c
src/cert_stack.c
src/cert_stack.h
src/config.c
src/config.h
src/extension.c
src/extension.h
src/nid.c
src/nid.h
src/object/bgpsec.c [new file with mode: 0644]
src/object/bgpsec.h [new file with mode: 0644]
src/object/certificate.c
src/object/certificate.h
src/object/router_key.h [new file with mode: 0644]
src/resource.c
src/resource.h
src/resource/asn.c
src/resource/asn.h
src/rtr/db/delta.c
src/rtr/db/delta.h
src/rtr/db/roa_table.c
src/rtr/db/vrp.h
src/rtr/db/vrps.c
src/rtr/db/vrps.h
src/rtr/pdu_handler.c
src/rtr/pdu_sender.c
src/rtr/pdu_sender.h
src/sorted_array.c
src/sorted_array.h
src/validation_handler.c
src/validation_handler.h

index 1155489e2da9ad51f6e4c239ff3a7af36094d48e..7aea1e14fd37fb9dec61285ddb22397ed472e84d 100644 (file)
@@ -61,12 +61,14 @@ fort_SOURCES += data_structure/uthash_nonfatal.h
 
 fort_SOURCES += incidence/incidence.h incidence/incidence.c
 
+fort_SOURCES += object/bgpsec.h object/bgpsec.c
 fort_SOURCES += object/certificate.h object/certificate.c
 fort_SOURCES += object/crl.h object/crl.c
 fort_SOURCES += object/ghostbusters.h object/ghostbusters.c
 fort_SOURCES += object/manifest.h object/manifest.c
 fort_SOURCES += object/name.h object/name.c
 fort_SOURCES += object/roa.h object/roa.c
+fort_SOURCES += object/router_key.h
 fort_SOURCES += object/signed_object.h object/signed_object.c
 fort_SOURCES += object/tal.h object/tal.c
 fort_SOURCES += object/vcard.h object/vcard.c
index 02e93eb98f30f104d25a15292475ccf256ec57c0..98254f734326b55d36148aa92f5232befddd268b 100644 (file)
@@ -2,6 +2,8 @@
 
 #include <stdbool.h>
 #include <openssl/obj_mac.h>
+#include <openssl/objects.h>
+
 #include "log.h"
 
 static bool
@@ -30,18 +32,40 @@ validate_certificate_signature_algorithm(int nid, char const *what)
 }
 
 int
-validate_certificate_public_key_algorithm(int nid)
+validate_certificate_public_key_algorithm(X509_ALGOR *pa, bool is_bgpsec)
 {
+       int nid;
+
        /*
         * RFC says sha256WithRSAEncryption, but current IETF concensus (and
         * practice) say that the right one is rsaEncryption.
         * https://mailarchive.ietf.org/arch/browse/sidr/
         */
-       if (nid == NID_rsaEncryption)
-               return 0;
+       nid = OBJ_obj2nid(pa->algorithm);
+       if (!is_bgpsec) {
+               if (nid == NID_rsaEncryption)
+                       return 0;
+               return pr_err("Certificate's public key format is NID '%s', not rsaEncryption.",
+                   OBJ_nid2sn(nid));
+       }
+
+       /* Validate algorithm and parameters (RFC 8608#section-3.1.1) */
+       if (nid != NID_X9_62_id_ecPublicKey)
+               return pr_err("Certificate's public key format is NID '%s', not id-ecPublicKey.",
+                   OBJ_nid2sn(nid));
 
-       return pr_err("Certificate's public key format is NID '%d', not rsaEncryption.",
-           nid);
+       if (pa->parameter == NULL)
+               return pr_err("Certificate's public key algorithm MUST have parameters");
+
+       if (pa->parameter->type != V_ASN1_OBJECT)
+               return pr_err("Certificate's public key parameter type isn't valid");
+
+       nid = OBJ_obj2nid((ASN1_OBJECT *)pa->parameter->value.object);
+       if (nid != NID_X9_62_prime256v1)
+               return pr_err("Certificate's public key format is NID '%s', not secp256r1 (a.k.a prime256v1).",
+                   OBJ_nid2sn(nid));
+
+       return 0;
 }
 
 int
index 1ab5201c694bd870e1af29394d9c8207481b81a7..460620f3374ed62bf7e878738ba8ab9e95bce074 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef SRC_ALGORITHM_H_
 #define SRC_ALGORITHM_H_
 
+#include <stdbool.h>
+#include <openssl/x509.h>
 #include "asn1/asn1c/AlgorithmIdentifier.h"
 #include "asn1/asn1c/OBJECT_IDENTIFIER.h"
 
@@ -9,7 +11,7 @@
  */
 
 int validate_certificate_signature_algorithm(int, char const *);
-int validate_certificate_public_key_algorithm(int);
+int validate_certificate_public_key_algorithm(X509_ALGOR *, bool);
 
 int validate_cms_hashing_algorithm(AlgorithmIdentifier_t *, char const *);
 int validate_cms_hashing_algorithm_oid(OBJECT_IDENTIFIER_t *, char const *);
index d4a1a7ef53fbf243b3d722ec16a04eb4000ebe32..732ffd405de0f770a15ca90408a70b60f8ecb937 100644 (file)
@@ -93,7 +93,7 @@ handle_sdata_certificate(ANY_t *cert_encoded, struct signed_object_args *args,
        error = certificate_validate_chain(cert, args->crls);
        if (error)
                goto end2;
-       error = certificate_validate_rfc6487(cert, false);
+       error = certificate_validate_rfc6487(cert, EE);
        if (error)
                goto end2;
        error = certificate_validate_extensions_ee(cert, sid, &args->refs,
@@ -105,7 +105,7 @@ handle_sdata_certificate(ANY_t *cert_encoded, struct signed_object_args *args,
                goto end2;
 
        resources_set_policy(args->res, policy);
-       error = certificate_get_resources(cert, args->res);
+       error = certificate_get_resources(cert, args->res, EE);
        if (error)
                goto end2;
 
index cd70e4707901ad317dd455307ad289ef1fb4bda8..61943e44c53460dcaa0d2d2bdada0e38d07e4fa8 100644 (file)
@@ -7,7 +7,6 @@
 #include "thread_var.h"
 #include "data_structure/array_list.h"
 #include "object/name.h"
-#include "object/certificate.h"
 
 enum defer_node_type {
        DNT_SEPARATOR,
@@ -265,7 +264,7 @@ deferstack_is_empty(struct cert_stack *stack)
 /** Steals ownership of @x509 on success. */
 int
 x509stack_push(struct cert_stack *stack, struct rpki_uri *uri, X509 *x509,
-    enum rpki_policy policy, bool is_ta)
+    enum rpki_policy policy, enum cert_type type)
 {
        struct metadata_node *meta;
        struct defer_node *defer_separator;
@@ -287,7 +286,7 @@ x509stack_push(struct cert_stack *stack, struct rpki_uri *uri, X509 *x509,
                goto end4;
        }
        resources_set_policy(meta->resources, policy);
-       error = certificate_get_resources(x509, meta->resources);
+       error = certificate_get_resources(x509, meta->resources, type);
        if (error)
                goto end5;
 
@@ -298,7 +297,7 @@ x509stack_push(struct cert_stack *stack, struct rpki_uri *uri, X509 *x509,
         * The "It MUST NOT use the "inherit" form of the INR extension(s)"
         * part is already handled in certificate_get_resources().
         */
-       if (is_ta && resources_empty(meta->resources)) {
+       if (type == TA && resources_empty(meta->resources)) {
                error = pr_err("Trust Anchor certificate does not define any number resources.");
                goto end5;
        }
index 6e0533c392bf844b9059bdb06146d010c98271ac..4ff617c3a19d34253bf1759c8fa924ff2dec9cc9 100644 (file)
@@ -4,6 +4,7 @@
 #include <openssl/x509.h>
 #include "resource.h"
 #include "uri.h"
+#include "object/certificate.h"
 #include "object/name.h"
 
 /*
@@ -41,7 +42,7 @@ int deferstack_pop(struct cert_stack *, struct deferred_cert *cert);
 bool deferstack_is_empty(struct cert_stack *);
 
 int x509stack_push(struct cert_stack *, struct rpki_uri *, X509 *,
-    enum rpki_policy, bool);
+    enum rpki_policy, enum cert_type);
 void x509stack_cancel(struct cert_stack *);
 X509 *x509stack_peek(struct cert_stack *);
 struct rpki_uri *x509stack_peek_uri(struct cert_stack *);
index d1440dfd2d5ba37d14282f5c025e36252f2463b9..a7737683b390b02e28c9e1d0d3714a89f9495086 100644 (file)
@@ -58,15 +58,13 @@ struct rpki_config {
                /** Outstanding connections in the socket's listen queue */
                unsigned int backlog;
 
-               /** Interval used to look for updates at VRPs location */
-               unsigned int validation_interval;
-
-               /*
-                * TODO (next iteration) Intervals used at End of data PDU
-                * uint32_t refresh_interval;
-                * uint32_t retry_interval;
-                * uint32_t expire_interval;
-                */
+               struct {
+                       /** Interval used to look for updates at VRPs location */
+                       unsigned int validation;
+                       unsigned int refresh;
+                       unsigned int retry;
+                       unsigned int expire;
+               } interval;
        } server;
 
        struct {
@@ -226,10 +224,10 @@ static const struct option_field options[] = {
                .max = SOMAXCONN,
        }, {
                .id = 5003,
-               .name = "server.validation-interval",
+               .name = "server.interval.validation",
                .type = &gt_uint,
                .offset = offsetof(struct rpki_config,
-                   server.validation_interval),
+                   server.interval.validation),
                .doc = "Interval used to look for updates at VRPs location",
                /*
                 * RFC 6810 and 8210:
@@ -240,13 +238,55 @@ static const struct option_field options[] = {
                 */
                .min = 60,
                .max = UINT_MAX,
+       }, {
+               .id = 5004,
+               .name = "server.interval.refresh",
+               .type = &gt_uint,
+               .offset = offsetof(struct rpki_config,
+                   server.interval.refresh),
+               .doc = "Interval between normal cache polls", // TODO
+               /*
+                * RFC 6810 and 8210:
+                * "The cache MUST rate-limit Serial Notifies to no more
+                * frequently than one per minute."
+                * We do this by not getting new information more than once per
+                * minute.
+                */
+               .min = 1,
+               .max = 86400,
+       }, {
+               .id = 5005,
+               .name = "server.interval.retry",
+               .type = &gt_uint,
+               .offset = offsetof(struct rpki_config,
+                   server.interval.retry),
+               .doc = "Interval between cache poll retries after a failed cache poll", // TODO
+               /*
+                * RFC 6810 and 8210:
+                * "The cache MUST rate-limit Serial Notifies to no more
+                * frequently than one per minute."
+                * We do this by not getting new information more than once per
+                * minute.
+                */
+               .min = 1,
+               .max = 7200,
+       }, {
+               .id = 5006,
+               .name = "server.interval.expire",
+               .type = &gt_uint,
+               .offset = offsetof(struct rpki_config,
+                   server.interval.expire),
+               .doc = "Interval during which data fetched from a cache remains valid in the absence of a successful subsequent cache poll", // TODO
+               /*
+                * RFC 6810 and 8210:
+                * "The cache MUST rate-limit Serial Notifies to no more
+                * frequently than one per minute."
+                * We do this by not getting new information more than once per
+                * minute.
+                */
+               .min = 600,
+               .max = 172800,
        },
-       /*
-        * TODO (next iteration) RTRv1 intervals with values:
-        * - refresh: min = 1, max = 86400, default = 3600
-        * - retry: min = 1, max = 7200, default = 600
-        * - expire: min = 600, max = 172800, default = 7200
-        */
 
        /* RSYNC fields */
        {
@@ -469,7 +509,10 @@ set_default_values(void)
                return pr_enomem();
 
        rpki_config.server.backlog = SOMAXCONN;
-       rpki_config.server.validation_interval = 3600;
+       rpki_config.server.interval.validation = 3600;
+       rpki_config.server.interval.refresh = 3600;
+       rpki_config.server.interval.retry = 600;
+       rpki_config.server.interval.expire = 7200;
 
        rpki_config.tal = NULL;
        rpki_config.slurm = NULL;
@@ -522,6 +565,12 @@ revert_port:
 static int
 validate_config(void)
 {
+       if (rpki_config.server.interval.expire <
+           rpki_config.server.interval.refresh ||
+           rpki_config.server.interval.expire <
+           rpki_config.server.interval.retry)
+               return pr_err("Expire interval must be greater than refresh and retry intervals");
+
        return (rpki_config.tal != NULL)
            ? 0
            : pr_err("The TAL file/directory (--tal) is mandatory.");
@@ -666,7 +715,25 @@ config_get_server_queue(void)
 unsigned int
 config_get_validation_interval(void)
 {
-       return rpki_config.server.validation_interval;
+       return rpki_config.server.interval.validation;
+}
+
+unsigned int
+config_get_interval_refresh(void)
+{
+       return rpki_config.server.interval.refresh;
+}
+
+unsigned int
+config_get_interval_retry(void)
+{
+       return rpki_config.server.interval.retry;
+}
+
+unsigned int
+config_get_interval_expire(void)
+{
+       return rpki_config.server.interval.expire;
 }
 
 char const *
index 581cc38218b5aed5d2e5e07d93e17770e289bb01..ad6a9c340edcb301f5b0ddc2c3c2c982fe5f36e7 100644 (file)
@@ -19,6 +19,9 @@ char const *config_get_server_address(void);
 char const *config_get_server_port(void);
 int config_get_server_queue(void);
 unsigned int config_get_validation_interval(void);
+unsigned int config_get_interval_refresh(void);
+unsigned int config_get_interval_retry(void);
+unsigned int config_get_interval_expire(void);
 char const *config_get_slurm(void);
 
 char const *config_get_tal(void);
index 2baa428f9acbf2f989ee300d86642213351f2d72..3301d95a294723e1bf30d055ac813f55472bb629 100644 (file)
@@ -146,6 +146,16 @@ struct extension_metadata const *ext_cn(void)
        return &CN;
 }
 
+struct extension_metadata const *ext_eku(void)
+{
+       static const struct extension_metadata EKU = {
+               "Extended Key Usage",
+               NID_ext_key_usage,
+               false,
+       };
+       return &EKU;
+}
+
 static int
 handle_extension(struct extension_handler *handlers, X509_EXTENSION *ext)
 {
index 74817ff6ee026fb736d6827b60d728bafba18494..543731860ada9ed9fb44172d6c427cc969147a32 100644 (file)
@@ -36,6 +36,7 @@ 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);
+struct extension_metadata const *ext_eku(void);
 
 int handle_extensions(struct extension_handler *,
     STACK_OF(X509_EXTENSION) const *);
index 7bbb148ccfa87d41c47b4926f7b4aa610e8bff8b..eb279830795a4d09a9404c8afb3655432bb22c32 100644 (file)
--- a/src/nid.c
+++ b/src/nid.c
@@ -12,6 +12,7 @@ static int NID_certPolicyRpki;
 static int NID_certPolicyRpkiV2;
 static int NID_ipAddrBlocksv2;
 static int NID_autonomousSysIdsv2;
+static int NID_bgpsecRouter;
 
 static int
 register_oid(const char *oid, const char *sn, const char *ln)
@@ -75,6 +76,12 @@ nid_init(void)
        if (NID_autonomousSysIdsv2 == 0)
                return -EINVAL;
 
+       NID_bgpsecRouter = register_oid("1.3.6.1.5.5.7.3.30",
+           "id-kp-bgpsec-router",
+           "BGPsec Extended Key Usage (RFC 8209)");
+       if (NID_bgpsecRouter == 0)
+               return -EINVAL;
+
        return 0;
 }
 
@@ -118,3 +125,8 @@ int nid_autonomousSysIdsv2(void)
 {
        return NID_autonomousSysIdsv2;
 }
+
+int nid_bgpsecRouter(void)
+{
+       return NID_bgpsecRouter;
+}
index 2b34afc1d5edd2248957d35e745debfbd60b14c2..3d0f643d80ab57783e2df10f255e79f27b4cdda1 100644 (file)
--- a/src/nid.h
+++ b/src/nid.h
@@ -11,5 +11,6 @@ int nid_certPolicyRpki(void);
 int nid_certPolicyRpkiV2(void);
 int nid_ipAddrBlocksv2(void);
 int nid_autonomousSysIdsv2(void);
+int nid_bgpsecRouter(void);
 
 #endif /* SRC_NID_H_ */
diff --git a/src/object/bgpsec.c b/src/object/bgpsec.c
new file mode 100644 (file)
index 0000000..e5bc894
--- /dev/null
@@ -0,0 +1,64 @@
+#include "bgpsec.h"
+
+#include "log.h"
+#include "validation_handler.h"
+
+struct resource_params {
+       struct router_key *router_key;
+       struct resources *resources;
+};
+
+static int
+asn_cb(unsigned long asn, void *arg)
+{
+       struct resource_params *params = arg;
+       struct router_key router_key;
+
+       if (!resources_contains_asn(params->resources, asn))
+               return pr_err("BGPsec certificate is not allowed for ASN %lu.",
+                   asn);
+
+       memcpy(&router_key, params->router_key, sizeof(*params->router_key));
+       router_key.asn = asn;
+
+       return vhandler_handle_bgpsec(&router_key);
+}
+
+int
+handle_bgpsec(X509 *cert, unsigned char *ski, int ski_len,
+    struct resources *resources)
+{
+       /*
+        * FIXME: Store the public key, SKI, and the resources
+        */
+       struct resource_params res_params;
+       struct router_key router_key;
+       ASN1_OBJECT *cert_alg;
+       X509_PUBKEY *pub_key;
+       unsigned char const *cert_spk;
+       int cert_spk_len;
+       int ok;
+
+       pub_key = X509_get_X509_PUBKEY(cert);
+       if (pub_key == NULL)
+               return crypto_err("X509_get_X509_PUBKEY() returned NULL at BGPsec");
+
+       ok = X509_PUBKEY_get0_param(&cert_alg, &cert_spk, &cert_spk_len, NULL,
+           pub_key);
+       if (!ok)
+               return crypto_err("X509_PUBKEY_get0_param() returned %d at BGPsec",
+                   ok);
+
+       router_key.spk = cert_spk;
+       router_key.spk_len = cert_spk_len;
+       router_key.ski = ski;
+       router_key.ski_len = ski_len;
+
+       res_params.router_key = &router_key;
+       res_params.resources = resources;
+
+       ok = resources_foreach_asn(resources, asn_cb, &res_params);
+       /* FIXME Maybe this should be released elsewhere.. */
+       free(ski);
+       return ok;
+}
diff --git a/src/object/bgpsec.h b/src/object/bgpsec.h
new file mode 100644 (file)
index 0000000..c34eba4
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef SRC_OBJECT_BGPSEC_H_
+#define SRC_OBJECT_BGPSEC_H_
+
+#include <openssl/x509.h>
+#include "resource.h"
+
+int handle_bgpsec(X509 *, unsigned char *, int, struct resources *);
+
+#endif /* SRC_OBJECT_BGPSEC_H_ */
index 37bc077c3a7dcf1ba404f06e11923c29db7b8c1c..dc27a79f8d565cd6935d749ba41b6f44da19c91b 100644 (file)
@@ -16,6 +16,7 @@
 #include "asn1/asn1c/IPAddrBlocks.h"
 #include "crypto/hash.h"
 #include "object/name.h"
+#include "object/bgpsec.h"
 #include "object/manifest.h"
 #include "rsync/rsync.h"
 
@@ -39,6 +40,12 @@ struct sia_uris {
        struct rpki_uri **mft;
 };
 
+struct bgpsec_ski {
+       X509 *cert;
+       int *ski_len;
+       unsigned char **ski_data;
+};
+
 static int
 validate_serial_number(X509 *cert)
 {
@@ -211,9 +218,10 @@ fail1:
 }
 
 static int
-validate_public_key(X509 *cert, bool is_root)
+validate_public_key(X509 *cert, enum cert_type type)
 {
        X509_PUBKEY *pubkey;
+       X509_ALGOR *pa;
        ASN1_OBJECT *alg;
        int ok;
        int error;
@@ -223,11 +231,11 @@ validate_public_key(X509 *cert, bool is_root)
        if (pubkey == NULL)
                return crypto_err("X509_get_X509_PUBKEY() returned NULL");
 
-       ok = X509_PUBKEY_get0_param(&alg, NULL, NULL, NULL, pubkey);
+       ok = X509_PUBKEY_get0_param(&alg, NULL, NULL, &pa, pubkey);
        if (!ok)
                return crypto_err("X509_PUBKEY_get0_param() returned %d", ok);
 
-       error = validate_certificate_public_key_algorithm(OBJ_obj2nid(alg));
+       error = validate_certificate_public_key_algorithm(pa, type == BGPSEC);
        if (error)
                return error;
 
@@ -243,7 +251,7 @@ validate_public_key(X509 *cert, bool is_root)
         * getting the message.
         */
 
-       if (is_root) {
+       if (type == TA) {
                error = validate_spki(pubkey);
                if (error)
                        return error;
@@ -253,7 +261,7 @@ validate_public_key(X509 *cert, bool is_root)
 }
 
 int
-certificate_validate_rfc6487(X509 *cert, bool is_root)
+certificate_validate_rfc6487(X509 *cert, enum cert_type type)
 {
        int error;
 
@@ -285,7 +293,7 @@ certificate_validate_rfc6487(X509 *cert, bool is_root)
                return error;
 
        /* rfc6487#section-4.4 */
-       error = validate_issuer(cert, is_root);
+       error = validate_issuer(cert, type == TA);
        if (error)
                return error;
 
@@ -304,7 +312,7 @@ certificate_validate_rfc6487(X509 *cert, bool is_root)
 
        /* rfc6487#section-4.7 */
        /* Fragment of rfc7730#section-2.2 */
-       error = validate_public_key(cert, is_root);
+       error = validate_public_key(cert, type);
        if (error)
                return error;
 
@@ -702,7 +710,8 @@ end:
 }
 
 static int
-handle_asn_extension(X509_EXTENSION *ext, struct resources *resources)
+handle_asn_extension(X509_EXTENSION *ext, struct resources *resources,
+    bool allow_inherit)
 {
        ASN1_OCTET_STRING *string;
        struct ASIdentifiers *ids;
@@ -714,7 +723,7 @@ handle_asn_extension(X509_EXTENSION *ext, struct resources *resources)
        if (error)
                return error;
 
-       error = resources_add_asn(resources, ids);
+       error = resources_add_asn(resources, ids, allow_inherit);
 
        ASN_STRUCT_FREE(asn_DEF_ASIdentifiers, ids);
        return error;
@@ -723,7 +732,7 @@ handle_asn_extension(X509_EXTENSION *ext, struct resources *resources)
 int
 __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)
+    char const *policy_rfc, char const *bad_ext_rfc, bool allow_asn_inherit)
 {
        X509_EXTENSION *ext;
        int nid;
@@ -760,7 +769,8 @@ __certificate_get_resources(X509 *cert, struct resources *resources,
                                return pr_err("The AS extension is not marked as critical.");
 
                        pr_debug_add("ASN {");
-                       error = handle_asn_extension(ext, resources);
+                       error = handle_asn_extension(ext, resources,
+                           allow_asn_inherit);
                        pr_debug_rm("}");
                        asn_ext_found = true;
 
@@ -783,7 +793,8 @@ __certificate_get_resources(X509 *cert, struct resources *resources,
 }
 
 int
-certificate_get_resources(X509 *cert, struct resources *resources)
+certificate_get_resources(X509 *cert, struct resources *resources,
+    enum cert_type type)
 {
        enum rpki_policy policy;
 
@@ -793,12 +804,12 @@ certificate_get_resources(X509 *cert, struct resources *resources)
                return __certificate_get_resources(cert, resources,
                    NID_sbgp_ipAddrBlock, NID_sbgp_autonomousSysNum,
                    nid_ipAddrBlocksv2(), nid_autonomousSysIdsv2(),
-                   "6484", "8360");
+                   "6484", "8360", type != BGPSEC);
        case RPKI_POLICY_RFC8360:
                return __certificate_get_resources(cert, resources,
                    nid_ipAddrBlocksv2(), nid_autonomousSysIdsv2(),
                    NID_sbgp_ipAddrBlock, NID_sbgp_autonomousSysNum,
-                   "8360", "6484");
+                   "8360", "6484", type != BGPSEC);
        }
 
        pr_crit("Unknown policy: %u", policy);
@@ -921,6 +932,36 @@ end:
        return error;
 }
 
+static int
+handle_ski_bgpsec(X509_EXTENSION *ext, void *arg)
+{
+       ASN1_OCTET_STRING *ski;
+       struct bgpsec_ski *params;
+       unsigned char *tmp;
+       int error;
+
+       ski = X509V3_EXT_d2i(ext);
+       if (ski == NULL)
+               return cannot_decode(ext_ski());
+
+       params = arg;
+       error = validate_public_key_hash(params->cert, ski);
+       if (error)
+               goto end;
+
+       tmp = malloc(ski->length + 1);
+       if (tmp == NULL)
+               goto end;
+
+       (*params->ski_len) = ski->length;
+       memcpy(tmp, ski->data, ski->length);
+       *params->ski_data = tmp;
+
+end:
+       ASN1_OCTET_STRING_free(ski);
+       return error;
+}
+
 static int
 handle_aki_ta(X509_EXTENSION *ext, void *arg)
 {
@@ -1313,6 +1354,37 @@ handle_ar(X509_EXTENSION *ext, void *arg)
        return 0; /* Handled in certificate_get_resources(). */
 }
 
+static int
+handle_eku(X509_EXTENSION *ext, void *arg)
+{
+       EXTENDED_KEY_USAGE *eku;
+       int nid;
+       int error;
+
+       eku = X509V3_EXT_d2i(ext);
+       if (eku == NULL)
+               return cannot_decode(ext_eku());
+
+       /*
+        * RFC 8209 allows multiple KeyPurposeId, so look only for the one
+        * required and specified at section 3.1.3.2
+        */
+       error = -ENOENT;
+       while (sk_ASN1_OBJECT_num(eku) > 0) {
+               nid = OBJ_obj2nid(sk_ASN1_OBJECT_pop(eku));
+               if (nid == nid_bgpsecRouter()) {
+                       error = 0;
+                       goto end;
+               }
+       }
+
+       if (error)
+               pr_err("Extended Key Usage doesn't include id-kp-bgpsec-router.");
+end:
+       EXTENDED_KEY_USAGE_free(eku);
+       return error;
+}
+
 /**
  * Validates the certificate extensions, Trust Anchor style.
  *
@@ -1383,6 +1455,32 @@ certificate_validate_extensions_ca(X509 *cert, struct rpki_uri **mft,
        return handle_extensions(handlers, X509_get0_extensions(cert));
 }
 
+static int
+certificate_validate_extensions_bgpsec(X509 *cert, unsigned char **ski,
+    int *ski_len, struct certificate_refs *refs, enum rpki_policy *policy)
+{
+       struct bgpsec_ski ski_param;
+       struct extension_handler handlers[] = {
+          /* ext        reqd   handler            arg        */
+           { ext_ski(), true,  handle_ski_bgpsec, &ski_param },
+           { ext_aki(), true,  handle_aki,                   },
+           { ext_ku(),  true,  handle_ku_ee,                 },
+           { ext_cdp(), true,  handle_cdp,        refs       },
+           { ext_aia(), true,  handle_aia,        refs       },
+           { ext_cp(),  true,  handle_cp,         policy     },
+           { ext_eku(), true,  handle_eku,                   },
+           { ext_ar(),  false, handle_ar,                    },
+           { ext_ar2(), false, handle_ar,                    },
+           { NULL },
+       };
+
+       ski_param.cert = cert;
+       ski_param.ski_data = ski;
+       ski_param.ski_len = ski_len;
+
+       return handle_extensions(handlers, X509_get0_extensions(cert));
+}
+
 int
 certificate_validate_extensions_ee(X509 *cert, OCTET_STRING_t *sid,
     struct certificate_refs *refs, enum rpki_policy *policy)
@@ -1410,6 +1508,18 @@ certificate_validate_extensions_ee(X509 *cert, OCTET_STRING_t *sid,
        return handle_extensions(handlers, X509_get0_extensions(cert));
 }
 
+static enum cert_type
+get_certificate_type(X509 *cert, bool is_ta)
+{
+       if (is_ta)
+               return TA;
+       if (X509_get_ext_by_NID(cert, ext_bc()->nid, -1) >= 0)
+               return CA;
+       if (X509_get_ext_by_NID(cert, NID_ext_key_usage, -1) >= 0)
+               return BGPSEC;
+       return EE;
+}
+
 /** Boilerplate code for CA certificate validation and recursive traversal. */
 int
 certificate_traverse(struct rpp *rpp_parent, struct rpki_uri *cert_uri)
@@ -1424,9 +1534,12 @@ certificate_traverse(struct rpp *rpp_parent, struct rpki_uri *cert_uri)
        struct rpki_uri *mft;
        struct rpki_uri *caRepository;
        struct certificate_refs refs;
+       unsigned char *ski;
        enum rpki_policy policy;
+       enum cert_type type;
        struct rpp *pp;
        bool mft_retry;
+       int ski_len;
        int error;
 
        state = state_retrieve();
@@ -1436,8 +1549,14 @@ certificate_traverse(struct rpp *rpp_parent, struct rpki_uri *cert_uri)
        if (total_parents >= config_get_max_cert_depth())
                return pr_err("Certificate chain maximum depth exceeded.");
 
-       pr_debug_add("%s Certificate '%s' {", IS_TA ? "TA" : "CA",
-           uri_get_printable(cert_uri));
+#ifdef DEBUG
+       if (IS_TA)
+               pr_debug_add("TA Certificate '%s' {",
+                   uri_get_printable(cert_uri));
+       else
+               pr_debug_add("Certificate '%s' {",
+                   uri_get_printable(cert_uri));
+#endif
        fnstack_push_uri(cert_uri);
        memset(&refs, 0, sizeof(refs));
 
@@ -1452,26 +1571,63 @@ certificate_traverse(struct rpp *rpp_parent, struct rpki_uri *cert_uri)
        error = certificate_validate_chain(cert, rpp_parent_crl);
        if (error)
                goto revert_cert;
-       error = certificate_validate_rfc6487(cert, IS_TA);
+
+       type = get_certificate_type(cert, IS_TA);
+#ifdef DEBUG
+       switch(type) {
+       case TA:
+               break;
+       case CA:
+               pr_debug("Type: CA");
+               break;
+       case BGPSEC:
+               pr_debug("Type: BGPsec EE");
+               break;
+       case EE:
+               pr_debug("Type: unexpected, validated as CA");
+               break;
+       }
+#endif
+       error = certificate_validate_rfc6487(cert, type);
        if (error)
                goto revert_cert;
-       error = IS_TA
-           ? certificate_validate_extensions_ta(cert, &mft, &caRepository,
-               &policy)
-           : certificate_validate_extensions_ca(cert, &mft, &caRepository,
-               &refs, &policy);
+       switch (type) {
+       case TA:
+               error = certificate_validate_extensions_ta(cert, &mft,
+                   &caRepository, &policy);
+               break;
+       case BGPSEC:
+               error = certificate_validate_extensions_bgpsec(cert, &ski,
+                   &ski_len, &refs, &policy);
+               break;
+       default:
+               /* Validate as a CA */
+               error = certificate_validate_extensions_ca(cert, &mft,
+                   &caRepository, &refs, &policy);
+               break;
+       }
        if (error)
                goto revert_cert;
 
        error = refs_validate_ca(&refs, rpp_parent);
        if (error)
-               goto revert_uri_and_refs;
+               goto revert_uris;
 
        /* -- Validate the manifest (@mft) pointed by the certificate -- */
        error = x509stack_push(validation_certstack(state), cert_uri, cert,
-           policy, IS_TA);
+           policy, type);
        if (error)
-               goto revert_uri_and_refs;
+               goto revert_uris;
+
+       if (type == BGPSEC) {
+               /* This is an EE, so there's no manifest to process */
+               error = handle_bgpsec(cert, ski, ski_len,
+                   x509stack_peek_resources(validation_certstack(state)));
+               cert = NULL; /* Ownership stolen at x509stack_push */
+               x509stack_cancel(validation_certstack(state));
+
+               goto revert_refs;
+       }
        cert = NULL; /* Ownership stolen */
 
        /*
@@ -1502,16 +1658,17 @@ certificate_traverse(struct rpp *rpp_parent, struct rpki_uri *cert_uri)
 
        if (error) {
                x509stack_cancel(validation_certstack(state));
-               goto revert_uri_and_refs;
+               goto revert_uris;
        }
 
        /* -- Validate & traverse the RPP (@pp) described by the manifest -- */
        rpp_traverse(pp);
 
        rpp_refput(pp);
-revert_uri_and_refs:
+revert_uris:
        uri_refput(caRepository);
        uri_refput(mft);
+revert_refs:
        refs_cleanup(&refs);
 revert_cert:
        if (cert != NULL)
index 5167cf804ac7efdc86b8556ebe847f1aa895f486..758a469d5c88aa9c19b42ad95f774de8ec39cdf6 100644 (file)
 #include "asn1/asn1c/ANY.h"
 #include "asn1/asn1c/SignatureValue.h"
 
+/* Certificate types in the RPKI */
+enum cert_type {
+       TA,             /* Trust Anchor */
+       CA,             /* Certificate Authority */
+       BGPSEC,         /* BGPsec certificates */
+       EE,             /* End Entity certificates */
+};
+
 int certificate_load(struct rpki_uri *, X509 **);
 
 /**
@@ -21,7 +29,7 @@ int certificate_validate_chain(X509 *, STACK_OF(X509_CRL) *);
  * Validates RFC 6487 compliance.
  * (Except extensions.)
  */
-int certificate_validate_rfc6487(X509 *, bool);
+int certificate_validate_rfc6487(X509 *, enum cert_type);
 
 int certificate_validate_signature(X509 *, ANY_t *coded, SignatureValue_t *);
 
@@ -34,7 +42,7 @@ int certificate_validate_signature(X509 *, ANY_t *coded, SignatureValue_t *);
  * not care about order. I don't know if you'll find other reasons if you choose
  * to migrate it.
  */
-int certificate_get_resources(X509 *, struct resources *);
+int certificate_get_resources(X509 *, struct resources *, enum cert_type);
 
 /**
  * Validates the certificate extensions, End-Entity style.
diff --git a/src/object/router_key.h b/src/object/router_key.h
new file mode 100644 (file)
index 0000000..622be74
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef SRC_OBJECT_ROUTER_KEY_H_
+#define SRC_OBJECT_ROUTER_KEY_H_
+
+/*
+ * Roouter Key representation
+ */
+struct router_key {
+       unsigned char   *ski;
+       size_t          ski_len;
+       uint32_t        asn;
+       unsigned char   *spk;
+       size_t          spk_len;
+};
+
+#endif /* SRC_OBJECT_ROUTER_KEY_H_ */
index fcbe7b96001b8151f05a9fd5cf199fa36430d529..fd655f2c36618033bb08c3f2cdd71d26b695931b 100644 (file)
@@ -9,7 +9,6 @@
 #include "thread_var.h"
 #include "resource/ip4.h"
 #include "resource/ip6.h"
-#include "resource/asn.h"
 #include <sys/socket.h>
 
 
@@ -535,7 +534,8 @@ add_asiors(struct resources *resources, struct ASIdentifiers *ids)
 }
 
 int
-resources_add_asn(struct resources *resources, struct ASIdentifiers *ids)
+resources_add_asn(struct resources *resources, struct ASIdentifiers *ids,
+    bool allow_inherit)
 {
        if (ids->asnum == NULL)
                return pr_err("ASN extension lacks 'asnum' element.");
@@ -544,6 +544,9 @@ resources_add_asn(struct resources *resources, struct ASIdentifiers *ids)
 
        switch (ids->asnum->present) {
        case ASIdentifierChoice_PR_inherit:
+               if (!allow_inherit)
+                       return pr_err("ASIdentifierChoice %u isn't allowed",
+                           ids->asnum->present);
                return inherit_asiors(resources);
        case ASIdentifierChoice_PR_asIdsOrRanges:
                return add_asiors(resources, ids);
@@ -591,3 +594,9 @@ resources_set_policy(struct resources *res, enum rpki_policy policy)
 {
        res->policy = policy;
 }
+
+int
+resources_foreach_asn(struct resources *res, foreach_asn_cb cb, void *arg)
+{
+       return rasn_foreach(res->asns, cb, arg);
+}
index 57ee2365fb06fa48b32ce32ed2b59c15cb9da40c..450c8c2ed55f0e68dd3b1f75392c28c2ccc12031 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <stdbool.h>
 #include "address.h"
+#include "resource/asn.h"
 #include "asn1/asn1c/ASIdentifiers.h"
 #include "asn1/asn1c/IPAddressFamily.h"
 
@@ -27,7 +28,7 @@ struct resources *resources_create(bool);
 void resources_destroy(struct resources *);
 
 int resources_add_ip(struct resources *, struct IPAddressFamily *);
-int resources_add_asn(struct resources *, struct ASIdentifiers *);
+int resources_add_asn(struct resources *, struct ASIdentifiers *, bool);
 
 bool resources_empty(struct resources *);
 bool resources_contains_asn(struct resources *, unsigned long);
@@ -37,4 +38,6 @@ 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);
 
+int resources_foreach_asn(struct resources *, foreach_asn_cb, void *);
+
 #endif /* SRC_RESOURCE_H_ */
index d63803ac18f1352af67dbe2f994b74b0f06a4696..62e5757d24360f5975cbef6bd6fcd34f24a75222 100644 (file)
@@ -1,6 +1,7 @@
 #include "asn.h"
 
 #include <errno.h>
+#include <limits.h>
 
 #include "log.h"
 #include "sorted_array.h"
@@ -10,6 +11,11 @@ struct asn_node {
        unsigned long max;
 };
 
+struct asn_cb {
+       foreach_asn_cb cb;
+       void *arg;
+};
+
 static enum sarray_comparison
 asn_cmp(void *arg1, void *arg2)
 {
@@ -74,3 +80,39 @@ rasn_contains(struct resources_asn *asns, unsigned long min, unsigned long max)
        struct asn_node n = { min, max };
        return sarray_contains((struct sorted_array *) asns, &n);
 }
+
+static int
+asn_node_cb(void *elem, void *arg)
+{
+       struct asn_node *node = elem;
+       struct asn_cb *param = arg;
+       unsigned long index;
+       int error;
+
+       for(index = node->min; index <= node->max; index++) {
+               error = param->cb(index, param->arg);
+               if (error)
+                       return error;
+               if (index == ULONG_MAX)
+                       break;
+       }
+
+       return 0;
+}
+
+int
+rasn_foreach(struct resources_asn *asns, foreach_asn_cb cb, void *arg)
+{
+       struct asn_cb param;
+       int error;
+
+       param.cb = cb;
+       param.arg = arg;
+
+       rasn_get(asns);
+       error = sarray_foreach((struct sorted_array *) asns, asn_node_cb,
+           &param);
+       rasn_put(asns);
+
+       return error;
+}
index 34f3733b023f4c67826a05a1d52cfa9950334f1e..42c9dc44f1ae7f2179eac93961cc9787d223d785 100644 (file)
@@ -14,4 +14,7 @@ int rasn_add(struct resources_asn *, unsigned long, unsigned long);
 bool rasn_empty(struct resources_asn *);
 bool rasn_contains(struct resources_asn *, unsigned long, unsigned long);
 
+typedef int (*foreach_asn_cb)(unsigned long, void *);
+int rasn_foreach(struct resources_asn *, foreach_asn_cb, void *);
+
 #endif /* SRC_RESOURCE_ASN_H_ */
index 691bdc695fc00b7b371ddd57fcba26414f6fbe2d..0fd087cc1e5bf27681c1391a26b50e6bf688323c 100644 (file)
@@ -17,8 +17,17 @@ struct delta_v6 {
        uint8_t max_length;
 };
 
+struct delta_bsec {
+       unsigned char *ski;
+       int *ski_len;
+       uint32_t as;
+       unsigned char *spk;
+       int *spk_len;
+};
+
 ARRAY_LIST(deltas_v6, struct delta_v6)
 ARRAY_LIST(deltas_v4, struct delta_v4)
+ARRAY_LIST(deltas_bgpsec, struct delta_bsec)
 
 struct deltas {
        struct {
@@ -29,6 +38,10 @@ struct deltas {
                struct deltas_v6 adds;
                struct deltas_v6 removes;
        } v6;
+       struct {
+               struct deltas_bgpsec adds;
+               struct deltas_bgpsec removes;
+       } bgpsec;
 
        atomic_uint references;
 };
@@ -46,6 +59,8 @@ deltas_create(struct deltas **_result)
        deltas_v4_init(&result->v4.removes);
        deltas_v6_init(&result->v6.adds);
        deltas_v6_init(&result->v6.removes);
+       deltas_bgpsec_init(&result->bgpsec.adds);
+       deltas_bgpsec_init(&result->bgpsec.removes);
        atomic_init(&result->references, 1);
 
        *_result = result;
@@ -70,6 +85,8 @@ deltas_refput(struct deltas *deltas)
                deltas_v4_cleanup(&deltas->v4.removes, NULL);
                deltas_v6_cleanup(&deltas->v6.adds, NULL);
                deltas_v6_cleanup(&deltas->v6.removes, NULL);
+               deltas_bgpsec_cleanup(&deltas->bgpsec.adds, NULL);
+               deltas_bgpsec_cleanup(&deltas->bgpsec.removes, NULL);
                free(deltas);
        }
 }
@@ -114,20 +131,44 @@ deltas_add_roa_v6(struct deltas *deltas, uint32_t as, struct v6_address *addr,
        pr_crit("Unknown delta operation: %d", op);
 }
 
+int
+deltas_add_bgpsec(struct deltas *deltas, unsigned char *ski, int ski_len,
+    uint32_t as, unsigned char *spk, int spk_len, int op)
+{
+       struct delta_bsec delta = {
+               .ski = ski,
+               .ski_len = ski_len,
+               .as = as,
+               .spk = spk,
+               .spk_len = spk_len,
+       };
+
+       switch (op) {
+       case FLAG_ANNOUNCEMENT:
+               return deltas_bgpsec_add(&deltas->bgpsec.adds, &delta);
+       case FLAG_WITHDRAWAL:
+               return deltas_bgpsec_add(&deltas->bgpsec.removes, &delta);
+       }
+
+       pr_crit("Unknown delta operation: %d", op);
+}
+
 bool
 deltas_is_empty(struct deltas *deltas)
 {
        return (deltas->v4.adds.len == 0)
            && (deltas->v4.removes.len == 0)
            && (deltas->v6.adds.len == 0)
-           && (deltas->v6.removes.len == 0);
+           && (deltas->v6.removes.len == 0)
+           && (deltas->bgpsec.adds.len == 0)
+           && (deltas->bgpsec.removes.len == 0);
 }
 
 static int
-__foreach_v4(struct deltas_v4 *array, delta_foreach_cb cb, void *arg,
+__foreach_v4(struct deltas_v4 *array, delta_vrp_foreach_cb cb, void *arg,
     serial_t serial, uint8_t flags)
 {
-       struct delta delta;
+       struct delta_vrp delta;
        struct delta_v4 *d;
        array_index i;
        int error;
@@ -150,10 +191,10 @@ __foreach_v4(struct deltas_v4 *array, delta_foreach_cb cb, void *arg,
 }
 
 static int
-__foreach_v6(struct deltas_v6 *array, delta_foreach_cb cb, void *arg,
+__foreach_v6(struct deltas_v6 *array, delta_vrp_foreach_cb cb, void *arg,
     serial_t serial, uint8_t flags)
 {
-       struct delta delta;
+       struct delta_vrp delta;
        struct delta_v6 *d;
        array_index i;
        int error;
@@ -175,27 +216,67 @@ __foreach_v6(struct deltas_v6 *array, delta_foreach_cb cb, void *arg,
        return 0;
 }
 
+static int
+__foreach_bgpsec(struct deltas_bgpsec *array, delta_bgpsec_foreach_cb cb,
+    void *arg, serial_t serial, uint8_t flags)
+{
+       struct delta_bgpsec delta;
+       struct delta_bsec *d;
+       array_index i;
+       int error;
+
+       delta.serial = serial;
+       delta.flags = flags;
+
+       ARRAYLIST_FOREACH(array, d, i) {
+               delta.router_key.ski = d->ski;
+               delta.router_key.ski_len = d->ski_len;
+               delta.router_key.asn = d->as;
+               delta.router_key.spk = d->spk;
+               delta.router_key.spk_len = d->spk_len;
+               error = cb(&delta, arg);
+               if (error)
+                       return error;
+       }
+
+       return 0;
+}
+
 int
-deltas_foreach(serial_t serial, struct deltas *deltas, delta_foreach_cb cb,
-    void *arg)
+deltas_foreach(serial_t serial, struct deltas *deltas,
+    delta_vrp_foreach_cb cb_vrp, delta_bgpsec_foreach_cb cb_bgpsec, void *arg)
 {
        int error;
 
-       error = __foreach_v4(&deltas->v4.adds, cb, arg, serial,
+       error = __foreach_v4(&deltas->v4.adds, cb_vrp, arg, serial,
+           FLAG_ANNOUNCEMENT);
+       if (error)
+               return error;
+
+       error = __foreach_v4(&deltas->v4.removes, cb_vrp, arg, serial,
+           FLAG_WITHDRAWAL);
+       if (error)
+               return error;
+
+       error = __foreach_v6(&deltas->v6.adds, cb_vrp, arg, serial,
            FLAG_ANNOUNCEMENT);
        if (error)
                return error;
 
-       error = __foreach_v4(&deltas->v4.removes, cb, arg, serial,
+       error = __foreach_v6(&deltas->v6.removes, cb_vrp, arg, serial,
            FLAG_WITHDRAWAL);
        if (error)
                return error;
 
-       error = __foreach_v6(&deltas->v6.adds, cb, arg, serial,
+       /* FIXME Temporary, this must not be null */
+       if (cb_bgpsec == NULL)
+               return 0;
+
+       error = __foreach_bgpsec(&deltas->bgpsec.adds, cb_bgpsec, arg, serial,
            FLAG_ANNOUNCEMENT);
        if (error)
                return error;
 
-       return __foreach_v6(&deltas->v6.removes, cb, arg, serial,
+       return __foreach_bgpsec(&deltas->bgpsec.removes, cb_bgpsec, arg, serial,
            FLAG_WITHDRAWAL);
 }
index a3d66ae63fd4332b001bbee47ffa5bb581ab018b..7512b31790ae93ab00b550223f19b5c2dd98ba15 100644 (file)
@@ -12,8 +12,11 @@ void deltas_refput(struct deltas *);
 
 int deltas_add_roa_v4(struct deltas *, uint32_t, struct v4_address *, int);
 int deltas_add_roa_v6(struct deltas *, uint32_t, struct v6_address *, int);
+int deltas_add_bgpsec(struct deltas *, unsigned char *, int, uint32_t,
+    unsigned char *, int, int);
 
 bool deltas_is_empty(struct deltas *);
-int deltas_foreach(serial_t, struct deltas *, delta_foreach_cb , void *);
+int deltas_foreach(serial_t, struct deltas *, delta_vrp_foreach_cb,
+    delta_bgpsec_foreach_cb, void *);
 
 #endif /* SRC_DELTA_H_ */
index e69b85ff225e89ba17ad46743b4976cf940f8a70..3229069d90cade8ae85d5ba3f24976f5694c012a 100644 (file)
@@ -9,8 +9,15 @@ struct hashable_roa {
        UT_hash_handle hh;
 };
 
+/* FIXME Update whole roa_table logic */
+struct hashable_keys {
+       struct router_key data;
+       UT_hash_handle hh;
+};
+
 struct roa_table {
        struct hashable_roa *roas;
+       struct hashable_keys *router_keys;
 };
 
 struct roa_table *
index 70d5503c289dbcdc3bc9c2b774a71070f15bdaf3..5b1f0c4e521b12f158a0a7462a93d10d4aaaaeb4 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <stdint.h>
 #include <netinet/in.h>
+#include "object/router_key.h"
 
 #define FLAG_WITHDRAWAL                0
 #define FLAG_ANNOUNCEMENT      1
@@ -44,13 +45,22 @@ struct vrp {
        uint8_t addr_fam;
 };
 
-struct delta {
+struct delta_vrp {
        serial_t serial;
        struct vrp vrp;
        uint8_t flags;
 };
 
+struct delta_bgpsec {
+       serial_t serial;
+       struct router_key router_key;
+       uint8_t flags;
+};
+
 typedef int (*vrp_foreach_cb)(struct vrp const *, void *);
-typedef int (*delta_foreach_cb)(struct delta const *, void *);
+typedef int (*router_key_foreach_cb)(struct router_key const *, void *);
+
+typedef int (*delta_vrp_foreach_cb)(struct delta_vrp const *, void *);
+typedef int (*delta_bgpsec_foreach_cb)(struct delta_bgpsec const *, void *);
 
 #endif /* SRC_RTR_DB_VRP_H_ */
index df75bd4dd47a362654cd7a54e0051e7b89fea248..f1ffb0c104d95ed868a0ef2250a9bfbb7f66f1f0 100644 (file)
@@ -9,6 +9,7 @@
 #include "output_printer.h"
 #include "validation_handler.h"
 #include "data_structure/array_list.h"
+#include "object/router_key.h"
 #include "object/tal.h"
 #include "rtr/db/roa_table.h"
 #include "slurm/slurm_loader.h"
@@ -23,7 +24,7 @@
 DEFINE_ARRAY_LIST_FUNCTIONS(deltas_db, struct delta_group, )
 
 struct vrp_node {
-       struct delta delta;
+       struct delta_vrp delta;
        SLIST_ENTRY(vrp_node) next;
 };
 
@@ -112,6 +113,17 @@ __handle_roa_v6(uint32_t as, struct ipv6_prefix const * prefix,
        return rtrhandler_handle_roa_v6(arg, as, prefix, max_length);
 }
 
+int
+__handle_bgpsec(struct router_key const *router_key, void *arg)
+{
+       pr_debug("Handling BGPsec for ASN %u", router_key->asn);
+       /*
+        * FIXME Add RTR handler
+        * return rtrhandler_handle_router_key(arg, as, prefix, max_length);
+        */
+       return 0;
+}
+
 static int
 __perform_standalone_validation(struct roa_table **result)
 {
@@ -125,6 +137,7 @@ __perform_standalone_validation(struct roa_table **result)
 
        validation_handler.handle_roa_v4 = __handle_roa_v4;
        validation_handler.handle_roa_v6 = __handle_roa_v6;
+       validation_handler.handle_bgpsec = __handle_bgpsec;
        validation_handler.arg = roas;
 
        error = perform_standalone_validation(&validation_handler);
@@ -346,7 +359,7 @@ vrps_foreach_base_roa(vrp_foreach_cb cb, void *arg)
  * hash table.)
  */
 static int
-vrp_ovrd_remove(struct delta const *delta, void *arg)
+vrp_ovrd_remove(struct delta_vrp const *delta, void *arg)
 {
        struct vrp_node *ptr;
        struct vrp_slist *filtered_vrps = arg;
@@ -373,7 +386,7 @@ vrp_ovrd_remove(struct delta const *delta, void *arg)
  * @arg) on each element of the resultant delta.
  */
 int
-vrps_foreach_filtered_delta(struct deltas_db *deltas, delta_foreach_cb cb,
+vrps_foreach_filtered_delta(struct deltas_db *deltas, delta_vrp_foreach_cb cb,
     void *arg)
 {
        struct vrp_slist filtered_vrps;
@@ -389,8 +402,9 @@ vrps_foreach_filtered_delta(struct deltas_db *deltas, delta_foreach_cb cb,
         */
        SLIST_INIT(&filtered_vrps);
        ARRAYLIST_FOREACH(deltas, group, i) {
+               /* FIXME Add function for router keys */
                error = deltas_foreach(group->serial, group->deltas,
-                   vrp_ovrd_remove, &filtered_vrps);
+                   vrp_ovrd_remove, NULL, &filtered_vrps);
                if (error)
                        goto release_list;
        }
index 67116c5e3f53ff8dd9df3ba67a87fe80672348c8..347a5fba2deb36ef19920714e111f5f0779cc218 100644 (file)
@@ -28,11 +28,15 @@ int vrps_update(bool *);
  * been called, or while it's still building the database.
  * Handle gracefully.
  */
+
+/* FIXME Also add BGPSEC */
 int vrps_foreach_base_roa(vrp_foreach_cb, void *);
 int vrps_get_deltas_from(serial_t, serial_t *, struct deltas_db *);
 int get_last_serial_number(serial_t *);
 
-int vrps_foreach_filtered_delta(struct deltas_db *, delta_foreach_cb, void *);
+/* FIXME Also filter BGPSEC */
+int vrps_foreach_filtered_delta(struct deltas_db *, delta_vrp_foreach_cb,
+    void *);
 
 uint16_t get_current_session_id(uint8_t);
 
index fa5bfd4e53b3ec70b4af627190553b9294fa1cb3..469e27951c5c5438a6af7228f6b172ece18266b7 100644 (file)
@@ -142,6 +142,7 @@ handle_reset_query_pdu(int fd, struct rtr_request const *request)
         * queries than reset queries.
         */
 
+       /* FIXME Apply to router keys as well */
        error = vrps_foreach_base_roa(send_base_roa, &args);
 
        /* See handle_serial_query_pdu() for some comments. */
index b2ec815582bef7ef50d0bd2583a5f73a4bed4c26..bd7cb00e63938bb888dbf766d57456fad391cc15 100644 (file)
 static void
 set_header_values(struct pdu_header *header, uint8_t type, uint16_t reserved)
 {
+       /* FIXME Remove to support RTR_V1 */
        header->protocol_version = RTR_V0;
        header->pdu_type = type;
        header->m.reserved = reserved;
 }
 
-/* TODO (next iteration) Include Router Key PDU serials */
-/**
- * static uint32_t
- * length_router_key_pdu(struct router_key_pdu *pdu)
- * {
- *     return HEADER_LENGTH +
- *         pdu->ski_len + sizeof(pdu->asn) + pdu->spki_len;
- * }
- */
-
 static int
 send_response(int fd, unsigned char *data, size_t data_len)
 {
@@ -163,13 +154,64 @@ send_prefix_pdu(int fd, struct vrp const *vrp, uint8_t flags)
        return -EINVAL;
 }
 
+int
+send_router_key_pdu(int fd, struct router_key const *router_key, uint8_t flags)
+{
+       struct router_key_pdu pdu;
+       unsigned char *data;
+       size_t len;
+       uint16_t reserved;
+       int error;
+
+       /* TODO Sanity check: this can't be sent on RTRv0 */
+
+       reserved = 0;
+       /* Set the flags at the first 8 bits of reserved field */
+       reserved += (flags << 8);
+       set_header_values(&pdu.header, PDU_TYPE_ROUTER_KEY, reserved);
+
+       pdu.ski = router_key->ski;
+       pdu.ski_len = router_key->ski_len;
+       pdu.asn = router_key->asn;
+       pdu.spki = router_key->spk;
+       pdu.spki_len = router_key->spk_len;
+       pdu.header.length = RTRPDU_HDR_LEN
+           + router_key->ski_len
+           + sizeof(router_key->asn)
+           + router_key->spk_len;
+
+       data = malloc(pdu.header.length);
+       if (data == NULL)
+               return pr_enomem();
+
+       len = serialize_router_key_pdu(&pdu, data);
+       if (len != pdu.header.length)
+               pr_crit("Serialized Router Key PDU is %zu bytes, not the expected %u.",
+                   len, pdu.header.length);
+
+       error = send_response(fd, data, len);
+
+       free(data);
+       return error;
+}
+
 static int
-vrp_simply_send(struct delta const *delta, void *arg)
+vrp_simply_send(struct delta_vrp const *delta, void *arg)
 {
        int *fd = arg;
+
        return send_prefix_pdu(*fd, &delta->vrp, delta->flags);
 }
 
+static int
+router_key_simply_send(struct delta_bgpsec const *delta, void *arg)
+{
+       int *fd = arg;
+
+       return send_router_key_pdu(*fd, &delta->router_key,
+           delta->flags);
+}
+
 int
 send_delta_pdus(int fd, struct deltas_db *deltas)
 {
@@ -182,9 +224,10 @@ send_delta_pdus(int fd, struct deltas_db *deltas)
        if (deltas->len == 1) {
                group = &deltas->array[0];
                return deltas_foreach(group->serial, group->deltas,
-                   vrp_simply_send, &fd);
+                   vrp_simply_send, router_key_simply_send, &fd);
        }
 
+       /* FIXME Apply to router keys as well */
        return vrps_foreach_filtered_delta(deltas, vrp_simply_send, &fd);
 }
 
@@ -201,7 +244,12 @@ send_end_of_data_pdu(int fd, serial_t end_serial)
        pdu.header.length = RTRPDU_END_OF_DATA_LEN;
 
        pdu.serial_number = end_serial;
-       /* TODO (next iteration) Add RTRv1 intervals */
+       /* FIXME WRONG!! Check for the real version */
+       if (pdu.header.protocol_version == RTR_V1) {
+               pdu.refresh_interval = config_get_interval_refresh();
+               pdu.retry_interval = config_get_interval_retry();
+               pdu.expire_interval = config_get_interval_expire();
+       }
 
        len = serialize_end_of_data_pdu(&pdu, data);
        if (len != RTRPDU_END_OF_DATA_LEN)
index 834647182c906568993f059a79c005f4715ccebe..413061d8ca6332bda0bdf3e7b3d887f53254acda 100644 (file)
@@ -10,6 +10,7 @@ int send_serial_notify_pdu(int, serial_t);
 int send_cache_reset_pdu(int);
 int send_cache_response_pdu(int);
 int send_prefix_pdu(int, struct vrp const *, uint8_t);
+int send_router_key_pdu(int, struct router_key const *, uint8_t);
 int send_delta_pdus(int, struct deltas_db *);
 int send_end_of_data_pdu(int, serial_t);
 int send_error_report_pdu(int, uint16_t, struct rtr_request const *, char *);
index 2200331b366ed610bebb47a42acd5e53cdde42f8..73ed0dc05152a8d57152e93a46cc8bbd038c7fb5 100644 (file)
@@ -179,6 +179,21 @@ sarray_contains(struct sorted_array *sarray, void *elem)
        return false;
 }
 
+int
+sarray_foreach(struct sorted_array *sarray, sarray_foreach_cb cb, void *arg)
+{
+       unsigned int index;
+       int error;
+
+       for (index = 0; index < sarray->count; index++) {
+               error = cb(get_nth_element(sarray, index), arg);
+               if (error)
+                       return error;
+       }
+
+       return 0;
+}
+
 char const *sarray_err2str(int error)
 {
        switch (abs(error)) {
index 4198b5f6f40682485c55c47129450c067e1effc6..41fd9d1e29d1694d931410ca5dc8374fe9a34c6a 100644 (file)
@@ -42,6 +42,9 @@ int sarray_add(struct sorted_array *, void *);
 bool sarray_empty(struct sorted_array *);
 bool sarray_contains(struct sorted_array *, void *);
 
+typedef int (*sarray_foreach_cb)(void *, void *);
+int sarray_foreach(struct sorted_array *, sarray_foreach_cb, void *);
+
 char const *sarray_err2str(int);
 
 #endif /* SRC_SORTED_ARRAY_H_ */
index 266658c8259f56412fce85a9a2576ee9d78ef6d8..ec17b12779ef9c372b878bd1efd0644904883b7c 100644 (file)
@@ -52,3 +52,18 @@ vhandler_handle_roa_v6(uint32_t as, struct ipv6_prefix const *prefix,
            ? handler->handle_roa_v6(as, prefix, max_length, handler->arg)
            : 0;
 }
+
+int
+vhandler_handle_bgpsec(struct router_key const *router_key)
+{
+       struct validation_handler const *handler;
+       int error;
+
+       error = get_current_threads_handler(&handler);
+       if (error)
+               return error;
+
+       return (handler->handle_bgpsec != NULL)
+           ? handler->handle_bgpsec(router_key, handler->arg)
+           : 0;
+}
index fc557a205831ff9422afdc0e52ab9e05a535feed..85cebf0d7396fa8f716bbe30aaf7daf0d1561b3d 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "address.h"
 #include "object/name.h"
+#include "object/router_key.h"
 
 /**
  * Functions that handle validation results.
@@ -28,11 +29,14 @@ struct validation_handler {
        /** Called every time Fort has successfully validated an IPv6 ROA. */
        int (*handle_roa_v6)(uint32_t, struct ipv6_prefix const *, uint8_t,
            void *);
+       /** Called every time Fort has successfully a BGPsec certificate */
+       int (*handle_bgpsec)(struct router_key const *, void *);
        /** Generic user-defined argument for the functions above. */
        void *arg;
 };
 
 int vhandler_handle_roa_v4(uint32_t, struct ipv4_prefix const *, uint8_t);
 int vhandler_handle_roa_v6(uint32_t, struct ipv6_prefix const *, uint8_t);
+int vhandler_handle_bgpsec(struct router_key const *);
 
 #endif /* SRC_VALIDATION_HANDLER_H_ */