fort_SOURCES = main.c
+fort_SOURCES += as_number.h
fort_SOURCES += algorithm.h algorithm.c
fort_SOURCES += alloc.h alloc.c
fort_SOURCES += certificate_refs.h certificate_refs.c
--- /dev/null
+#ifndef SRC_AS_NUMBER_H_
+#define SRC_AS_NUMBER_H_
+
+#include <stdint.h>
+
+struct asn_range {
+ uint32_t min;
+ uint32_t max;
+};
+
+#endif /* SRC_AS_NUMBER_H_ */
#include "validation_handler.h"
struct resource_params {
- unsigned char const *ski;
- unsigned char const *spk;
- struct resources *resources;
+ unsigned char const *ski;
+ unsigned char const *spk;
+ struct resources *parent_resources;
};
static int
-asn_cb(unsigned long asn, void *arg)
+asn_cb(struct asn_range const *range, void *arg)
{
struct resource_params *params = arg;
- if (!resources_contains_asn(params->resources, asn))
- return pr_val_err("BGPsec certificate is not allowed for ASN %lu.",
- asn);
+ if (!resources_contains_asns(params->parent_resources, range))
+ return pr_val_err("BGPsec certificate is not allowed to contain ASN range %u-%u.",
+ range->min, range->max);
- return vhandler_handle_router_key(params->ski, asn, params->spk);
+ return vhandler_handle_router_key(params->ski, range, params->spk);
}
int
X509_PUBKEY *pub_key;
unsigned char *cert_spk, *tmp;
int cert_spk_len;
- int ok;
+ int error;
pub_key = X509_get_X509_PUBKEY(cert);
if (pub_key == NULL)
res_params.spk = cert_spk;
res_params.ski = ski;
- res_params.resources = resources;
+ res_params.parent_resources = resources;
- ok = resources_foreach_asn(resources, asn_cb, &res_params);
+ error = resources_foreach_asn(resources, asn_cb, &res_params);
free(cert_spk);
- return ok;
+ return error;
}
}
static int
-ASId2ulong(ASId_t *as_id, unsigned long *result)
+ASId2u32(ASId_t *as_id, uint32_t *result)
{
static const unsigned long ASN_MAX = UINT32_MAX;
+ unsigned long ulong;
int error;
- error = asn_INTEGER2ulong(as_id, result);
+ error = asn_INTEGER2ulong(as_id, &ulong);
if (error) {
if (errno) {
pr_val_err("Error converting ASN value: %s",
return pr_val_err("ASN value is not a valid unsigned long");
}
- if ((*result) > ASN_MAX) {
+ if (ulong > ASN_MAX) {
return pr_val_err("ASN value '%lu' is out of bounds. (0-%lu)",
- *result, ASN_MAX);
+ ulong, ASN_MAX);
}
+ *result = ulong;
return 0;
}
static int
-add_asn(struct resources *resources, unsigned long min, unsigned long max,
+add_asn(struct resources *resources, struct asn_range const *asns,
struct resources *parent)
{
int error;
- if (min > max)
- return pr_val_err("The ASN range %lu-%lu is inverted.", min, max);
+ if (asns->min > asns->max) {
+ return pr_val_err("The ASN range %u-%u is inverted.",
+ asns->min, asns->max);
+ }
- if (parent && !rasn_contains(parent->asns, min, max)) {
+ if (parent && !rasn_contains(parent->asns, asns)) {
switch (resources->policy) {
case RPKI_POLICY_RFC6484:
- return pr_val_err("Parent certificate doesn't own ASN range '%lu-%lu'.",
- min, max);
+ return pr_val_err("Parent certificate doesn't own ASN range '%u-%u'.",
+ asns->min, asns->max);
case RPKI_POLICY_RFC8360:
- return pr_val_warn("Certificate is overclaiming the ASN range '%lu-%lu'.",
- min, max);
+ return pr_val_warn("Certificate is overclaiming the ASN range '%u-%u'.",
+ asns->min, asns->max);
}
}
enomem_panic();
}
- error = rasn_add(resources->asns, min, max);
+ error = rasn_add(resources->asns, asns);
if (error){
- pr_val_err("Error adding ASN range '%lu-%lu' to certificate resources: %s",
- min, max, sarray_err2str(error));
+ pr_val_err("Error adding ASN range '%u-%u' to certificate resources: %s",
+ asns->min, asns->max, sarray_err2str(error));
return error;
}
- if (min == max)
- pr_val_debug("ASN: %lu", min);
+ if (asns->min == asns->max)
+ pr_val_debug("ASN: %u", asns->min);
else
- pr_val_debug("ASN: %lu-%lu", min, max);
+ pr_val_debug("ASN: %u-%u", asns->min, asns->max);
return 0;
}
add_asior(struct resources *resources, struct ASIdOrRange *obj)
{
struct resources *parent;
- unsigned long asn_min;
- unsigned long asn_max;
+ struct asn_range asns;
int error;
parent = get_parent_resources();
break;
case ASIdOrRange_PR_id:
- error = ASId2ulong(&obj->choice.id, &asn_min);
+ error = ASId2u32(&obj->choice.id, &asns.min);
if (error)
return error;
- return add_asn(resources, asn_min, asn_min, parent);
+ asns.max = asns.min;
+ return add_asn(resources, &asns, parent);
case ASIdOrRange_PR_range:
- error = ASId2ulong(&obj->choice.range.min, &asn_min);
+ error = ASId2u32(&obj->choice.range.min, &asns.min);
if (error)
return error;
- error = ASId2ulong(&obj->choice.range.max, &asn_max);
+ error = ASId2u32(&obj->choice.range.max, &asns.max);
if (error)
return error;
- return add_asn(resources, asn_min, asn_max, parent);
+ return add_asn(resources, &asns, parent);
}
return pr_val_err("Unknown ASIdOrRange type: %u", obj->present);
}
bool
-resources_contains_asn(struct resources *res, unsigned long asn)
+resources_contains_asns(struct resources *res, struct asn_range const *range)
{
- return rasn_contains(res->asns, asn, asn);
+ return rasn_contains(res->asns, range);
}
bool
-resources_contains_ipv4(struct resources *res, struct ipv4_prefix *prefix)
+resources_contains_ipv4(struct resources *res, struct ipv4_prefix const *prefix)
{
return res4_contains_prefix(res->ip4s, prefix);
}
bool
-resources_contains_ipv6(struct resources *res, struct ipv6_prefix *prefix)
+resources_contains_ipv6(struct resources *res, struct ipv6_prefix const *prefix)
{
return res6_contains_prefix(res->ip6s, prefix);
}
int resources_add_asn(struct resources *, struct ASIdentifiers *, bool);
bool resources_empty(struct resources *);
-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 *);
+bool resources_contains_asns(struct resources *, struct asn_range const *);
+bool resources_contains_ipv4(struct resources *, struct ipv4_prefix const *);
+bool resources_contains_ipv6(struct resources *, struct ipv6_prefix const *);
enum rpki_policy resources_get_policy(struct resources *);
void resources_set_policy(struct resources *, enum rpki_policy);
#include "log.h"
#include "sorted_array.h"
-struct asn_node {
- unsigned long min;
- unsigned long max;
-};
-
struct asn_cb {
foreach_asn_cb cb;
void *arg;
};
static enum sarray_comparison
-asn_cmp(void *arg1, void *arg2)
+asn_cmp(void const *arg1, void const *arg2)
{
- unsigned long n1min = ((struct asn_node *) arg1)->min;
- unsigned long n1max = ((struct asn_node *) arg1)->max;
- unsigned long n2min = ((struct asn_node *) arg2)->min;
- unsigned long n2max = ((struct asn_node *) arg2)->max;
+ uint32_t n1min = ((struct asn_range const *) arg1)->min;
+ uint32_t n1max = ((struct asn_range const *) arg1)->max;
+ uint32_t n2min = ((struct asn_range const *) arg2)->min;
+ uint32_t n2max = ((struct asn_range const *) arg2)->max;
if (n1min == n2min && n1max == n2max)
return SACMP_EQUAL;
rasn_create(void)
{
return (struct resources_asn *)
- sarray_create(sizeof(struct asn_node), asn_cmp);
+ sarray_create(sizeof(struct asn_range), asn_cmp);
}
void
}
int
-rasn_add(struct resources_asn *asns, unsigned long min, unsigned long max)
+rasn_add(struct resources_asn *asns, struct asn_range const *range)
{
- struct asn_node n = { min, max };
- return sarray_add((struct sorted_array *) asns, &n);
+ return sarray_add((struct sorted_array *) asns, range);
}
bool
}
bool
-rasn_contains(struct resources_asn *asns, unsigned long min, unsigned long max)
+rasn_contains(struct resources_asn *asns, struct asn_range const *range)
{
- struct asn_node n = { min, max };
- return sarray_contains((struct sorted_array *) asns, &n);
+ return sarray_contains((struct sorted_array *) asns, range);
}
static int
-asn_node_cb(void *elem, void *arg)
+asn_range_cb(void *node, 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;
+ return param->cb(node, param->arg);
}
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,
+ struct asn_cb param = { .cb = cb, .arg = arg };
+ return sarray_foreach((struct sorted_array *) asns, asn_range_cb,
¶m);
- rasn_put(asns);
-
- return error;
}
#define SRC_RESOURCE_ASN_H_
#include <stdbool.h>
+#include "as_number.h"
#include "asn1/asn1c/ASId.h"
+/*
+ * Implementation note: This is just a casted struct sorted_array.
+ * Why? Because this module doesn't have anything to add.
+ * Why not make the methods return a sorted_array? Because they're not meant to
+ * be tied to the sorted array implementation.
+ * Why not convert this into a structure that contains a sorted_array? Because
+ * sorted_array is private, so resources_asn would have to contain a pointer to
+ * it, which is another level of indirection, which is slightly wasted
+ * performance.
+ */
struct resources_asn;
struct resources_asn *rasn_create(void);
void rasn_get(struct resources_asn *);
void rasn_put(struct resources_asn *);
-int rasn_add(struct resources_asn *, unsigned long, unsigned long);
+int rasn_add(struct resources_asn *, struct asn_range const *);
bool rasn_empty(struct resources_asn *);
-bool rasn_contains(struct resources_asn *, unsigned long, unsigned long);
+bool rasn_contains(struct resources_asn *, struct asn_range const *);
-typedef int (*foreach_asn_cb)(unsigned long, void *);
+typedef int (*foreach_asn_cb)(struct asn_range const *, void *);
int rasn_foreach(struct resources_asn *, foreach_asn_cb, void *);
#endif /* SRC_RESOURCE_ASN_H_ */
};
static enum sarray_comparison
-r4_cmp(void *arg1, void *arg2)
+r4_cmp(void const *arg1, void const *arg2)
{
- uint32_t n1min = ((struct r4_node *) arg1)->min;
- uint32_t n2min = ((struct r4_node *) arg2)->min;
- uint32_t n1max = ((struct r4_node *) arg1)->max;
- uint32_t n2max = ((struct r4_node *) arg2)->max;
+ uint32_t n1min = ((struct r4_node const *) arg1)->min;
+ uint32_t n2min = ((struct r4_node const *) arg2)->min;
+ uint32_t n1max = ((struct r4_node const *) arg1)->max;
+ uint32_t n2max = ((struct r4_node const *) arg2)->max;
if (n1min == n2min && n1max == n2max)
return SACMP_EQUAL;
}
static void
-pton(struct ipv4_prefix *p, struct r4_node *n)
+pton(struct ipv4_prefix const *p, struct r4_node *n)
{
n->min = ntohl(p->addr.s_addr);
n->max = n->min | u32_suffix_mask(p->len);
}
static void
-rton(struct ipv4_range *r, struct r4_node *n)
+rton(struct ipv4_range const *r, struct r4_node *n)
{
n->min = ntohl(r->min.s_addr);
n->max = ntohl(r->max.s_addr);
}
int
-res4_add_prefix(struct resources_ipv4 *ips, struct ipv4_prefix *prefix)
+res4_add_prefix(struct resources_ipv4 *ips, struct ipv4_prefix const *prefix)
{
struct r4_node n;
pton(prefix, &n);
}
int
-res4_add_range(struct resources_ipv4 *ips, struct ipv4_range *range)
+res4_add_range(struct resources_ipv4 *ips, struct ipv4_range const *range)
{
struct r4_node n;
rton(range, &n);
}
bool
-res4_empty(struct resources_ipv4 *ips)
+res4_empty(struct resources_ipv4 const *ips)
{
- return sarray_empty((struct sorted_array *) ips);
+ return sarray_empty((struct sorted_array const *) ips);
}
bool
-res4_contains_prefix(struct resources_ipv4 *ips, struct ipv4_prefix *prefix)
+res4_contains_prefix(struct resources_ipv4 *ips,
+ struct ipv4_prefix const *prefix)
{
struct r4_node n;
}
bool
-res4_contains_range(struct resources_ipv4 *ips, struct ipv4_range *range)
+res4_contains_range(struct resources_ipv4 *ips, struct ipv4_range const *range)
{
struct r4_node n;
rton(range, &n);
void res4_get(struct resources_ipv4 *);
void res4_put(struct resources_ipv4 *);
-int res4_add_prefix(struct resources_ipv4 *, struct ipv4_prefix *);
-int res4_add_range(struct resources_ipv4 *, struct ipv4_range *);
-bool res4_empty(struct resources_ipv4 *);
-bool res4_contains_prefix(struct resources_ipv4 *, struct ipv4_prefix *);
-bool res4_contains_range(struct resources_ipv4 *, struct ipv4_range *);
+int res4_add_prefix(struct resources_ipv4 *, struct ipv4_prefix const *);
+int res4_add_range(struct resources_ipv4 *, struct ipv4_range const *);
+bool res4_empty(struct resources_ipv4 const *);
+bool res4_contains_prefix(struct resources_ipv4 *, struct ipv4_prefix const *);
+bool res4_contains_range(struct resources_ipv4 *, struct ipv4_range const *);
#endif /* SRC_RESOURCE_IP4_H_ */
}
static enum sarray_comparison
-r6_cmp(void *arg1, void *arg2)
+r6_cmp(void const *arg1, void const *arg2)
{
- struct in6_addr const *a1min = &((struct ipv6_range *) arg1)->min;
- struct in6_addr const *a2min = &((struct ipv6_range *) arg2)->min;
- struct in6_addr const *a1max = &((struct ipv6_range *) arg1)->max;
- struct in6_addr const *a2max = &((struct ipv6_range *) arg2)->max;
+ struct in6_addr const *a1min = &((struct ipv6_range const *) arg1)->min;
+ struct in6_addr const *a2min = &((struct ipv6_range const *) arg2)->min;
+ struct in6_addr const *a1max = &((struct ipv6_range const *) arg1)->max;
+ struct in6_addr const *a2max = &((struct ipv6_range const *) arg2)->max;
if (addr_equals(a1min, a2min) && addr_equals(a1max, a2max))
return SACMP_EQUAL;
}
int
-res6_add_prefix(struct resources_ipv6 *ips, struct ipv6_prefix *prefix)
+res6_add_prefix(struct resources_ipv6 *ips, struct ipv6_prefix const *prefix)
{
struct ipv6_range r;
ptor(prefix, &r);
}
int
-res6_add_range(struct resources_ipv6 *ips, struct ipv6_range *range)
+res6_add_range(struct resources_ipv6 *ips, struct ipv6_range const *range)
{
return sarray_add((struct sorted_array *) ips, range);
}
bool
-res6_empty(struct resources_ipv6 *ips)
+res6_empty(struct resources_ipv6 const *ips)
{
- return sarray_empty((struct sorted_array *) ips);
+ return sarray_empty((struct sorted_array const *) ips);
}
bool
-res6_contains_prefix(struct resources_ipv6 *ips, struct ipv6_prefix *prefix)
+res6_contains_prefix(struct resources_ipv6 *ips,
+ struct ipv6_prefix const *prefix)
{
struct ipv6_range r;
ptor(prefix, &r);
}
bool
-res6_contains_range(struct resources_ipv6 *ips, struct ipv6_range *range)
+res6_contains_range(struct resources_ipv6 *ips, struct ipv6_range const *range)
{
return sarray_contains((struct sorted_array *) ips, range);
}
void res6_get(struct resources_ipv6 *);
void res6_put(struct resources_ipv6 *);
-int res6_add_prefix(struct resources_ipv6 *ps, struct ipv6_prefix *);
-int res6_add_range(struct resources_ipv6 *, struct ipv6_range *);
-bool res6_empty(struct resources_ipv6 *ips);
-bool res6_contains_prefix(struct resources_ipv6 *, struct ipv6_prefix *);
-bool res6_contains_range(struct resources_ipv6 *, struct ipv6_range *);
+int res6_add_prefix(struct resources_ipv6 *ps, struct ipv6_prefix const *);
+int res6_add_range(struct resources_ipv6 *, struct ipv6_range const *);
+bool res6_empty(struct resources_ipv6 const *ips);
+bool res6_contains_prefix(struct resources_ipv6 *, struct ipv6_prefix const *);
+bool res6_contains_range(struct resources_ipv6 *, struct ipv6_range const *);
#endif /* SRC_RESOURCE_IP6_H_ */
}
int
-handle_router_key(unsigned char const *ski, uint32_t as,
+handle_router_key(unsigned char const *ski, struct asn_range const *asns,
unsigned char const *spk, void *arg)
{
- WLOCK_HANDLER(rtrhandler_handle_router_key(arg, ski, as, spk))
+ uint64_t asn;
+ int error = 0;
+
+ mutex_lock(&table_lock);
+
+ /*
+ * TODO (warning) Umm... this is begging for a limit.
+ * If the issuer gets it wrong, we can iterate up to 2^32 times.
+ * The RFCs don't seem to care about this.
+ */
+ for (asn = asns->min; asn <= asns->max; asn++) {
+ error = rtrhandler_handle_router_key(arg, ski, asn, spk);
+ if (error)
+ break;
+ }
+
+ mutex_unlock(&table_lock);
+ return error;
}
static int
*/
#include <stdbool.h>
+#include "as_number.h"
#include "types/address.h"
#include "rtr/db/deltas_array.h"
int handle_roa_v4(uint32_t, struct ipv4_prefix const *, uint8_t, void *);
int handle_roa_v6(uint32_t, struct ipv6_prefix const *, uint8_t, void *);
-int handle_router_key(unsigned char const *, uint32_t, unsigned char const *,
- void *);
+int handle_router_key(unsigned char const *, struct asn_range const *,
+ unsigned char const *, void *);
uint16_t get_current_session_id(uint8_t);
/* Does not check boundaries. */
static void *
-get_nth_element(struct sorted_array *sarray, unsigned int index)
+get_nth_element(struct sorted_array const *sarray, unsigned int index)
{
return ((char *)sarray->array) + index * sarray->size;
}
* @array.)
*/
static int
-compare(struct sorted_array *sarray, void *new)
+compare(struct sorted_array *sarray, void const *new)
{
enum sarray_comparison cmp;
}
int
-sarray_add(struct sorted_array *sarray, void *element)
+sarray_add(struct sorted_array *sarray, void const *element)
{
int error;
}
bool
-sarray_empty(struct sorted_array *sarray)
+sarray_empty(struct sorted_array const *sarray)
{
return (sarray == NULL) || (sarray->count == 0);
}
bool
-sarray_contains(struct sorted_array *sarray, void *elem)
+sarray_contains(struct sorted_array const *sarray, void const *elem)
{
unsigned int left, mid, right;
enum sarray_comparison cmp;
SACMP_INTERSECTION,
};
-typedef enum sarray_comparison (*sarray_cmp)(void *, void *);
+typedef enum sarray_comparison (*sarray_cmp)(void const *, void const *);
struct sorted_array *sarray_create(size_t, sarray_cmp);
void sarray_get(struct sorted_array *);
#define EADJRIGHT 7899
#define EINTERSECTION 7900
-int sarray_add(struct sorted_array *, void *);
-bool sarray_empty(struct sorted_array *);
-bool sarray_contains(struct sorted_array *, void *);
+int sarray_add(struct sorted_array *, void const *);
+bool sarray_empty(struct sorted_array const *);
+bool sarray_contains(struct sorted_array const *, void const *);
typedef int (*sarray_foreach_cb)(void *, void *);
int sarray_foreach(struct sorted_array *, sarray_foreach_cb, void *);
}
int
-vhandler_handle_router_key(unsigned char const *ski, uint32_t as,
- unsigned char const *spk)
+vhandler_handle_router_key(unsigned char const *ski,
+ struct asn_range const *asns, unsigned char const *spk)
{
struct validation_handler const *handler;
handler = get_current_threads_handler();
return (handler->handle_router_key != NULL)
- ? handler->handle_router_key(ski, as, spk, handler->arg)
+ ? handler->handle_router_key(ski, asns, spk, handler->arg)
: 0;
}
#ifndef SRC_VALIDATION_HANDLER_H_
#define SRC_VALIDATION_HANDLER_H_
+#include "as_number.h"
#include "types/address.h"
#include "types/router_key.h"
#include "object/name.h"
int (*handle_roa_v6)(uint32_t, struct ipv6_prefix const *, uint8_t,
void *);
/** Called every time Fort has successfully validated a BGPsec cert */
- int (*handle_router_key)(unsigned char const *, uint32_t,
- unsigned char const *, void *);
+ int (*handle_router_key)(unsigned char const *,
+ struct asn_range const *, unsigned char 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_router_key(unsigned char const *, uint32_t,
+int vhandler_handle_router_key(unsigned char const *, struct asn_range const *,
unsigned char const *);
#endif /* SRC_VALIDATION_HANDLER_H_ */
static void
add_rk(struct validation_handler *handler, uint32_t as)
{
- ck_assert_int_eq(0, handler->handle_router_key(db_imp_ski, as,
+ struct asn_range range = { .min = as, .max = as };
+ ck_assert_int_eq(0, handler->handle_router_key(db_imp_ski, &range,
db_imp_spk, handler->arg));
}
}
int
-__handle_router_key(unsigned char const *ski, uint32_t as,
+__handle_router_key(unsigned char const *ski, struct asn_range const *range,
unsigned char const *spk, void *arg)
{
- return rtrhandler_handle_router_key(arg, ski, as, spk);
+ uint64_t as;
+ int error;
+
+ for (as = range->min; as <= range->max; as++) {
+ error = rtrhandler_handle_router_key(arg, ski, as, spk);
+ if (error)
+ break;
+ }
+
+ return error;
}
int