mirror of
https://github.com/openbsd/src.git
synced 2026-06-18 15:23:33 +02:00
rpki-client: move RFC 3779 IP address parsing from cert.c to ip.c
ok job
This commit is contained in:
+1
-206
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: cert.c,v 1.234 2026/05/02 10:28:20 tb Exp $ */
|
||||
/* $OpenBSD: cert.c,v 1.235 2026/05/02 10:35:18 tb Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2022,2025 Theo Buehler <tb@openbsd.org>
|
||||
* Copyright (c) 2021 Job Snijders <job@openbsd.org>
|
||||
@@ -1023,211 +1023,6 @@ cert_policies(const char *fn, struct cert *cert, const X509_EXTENSION *ext)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Append an IP address structure to our list of results, ensuring there is
|
||||
* at most one inheritance marker per AFI and no overlapping ranges.
|
||||
*/
|
||||
static int
|
||||
append_ip(const char *fn, struct cert_ip *ips, size_t *num_ips,
|
||||
const struct cert_ip *ip)
|
||||
{
|
||||
if (!ip_addr_check_overlap(ip, fn, ips, *num_ips, 0))
|
||||
return 0;
|
||||
ips[(*num_ips)++] = *ip;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct a RFC 3779 2.2.3.8 range from its bit string.
|
||||
* Returns zero on failure, non-zero on success.
|
||||
*/
|
||||
int
|
||||
sbgp_addr(const char *fn, struct cert_ip *ips, size_t *num_ips, enum afi afi,
|
||||
const ASN1_BIT_STRING *bs)
|
||||
{
|
||||
struct cert_ip ip;
|
||||
|
||||
memset(&ip, 0, sizeof(struct cert_ip));
|
||||
|
||||
ip.afi = afi;
|
||||
ip.type = CERT_IP_ADDR;
|
||||
|
||||
if (!ip_addr_parse(bs, afi, fn, &ip.ip)) {
|
||||
warnx("%s: RFC 3779 section 2.2.3.8: IPAddress: "
|
||||
"invalid IP address", fn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ip_cert_compose_ranges(&ip)) {
|
||||
warnx("%s: RFC 3779 section 2.2.3.8: IPAddress: "
|
||||
"IP address range reversed", fn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return append_ip(fn, ips, num_ips, &ip);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse RFC 3779 2.2.3.9 range of addresses.
|
||||
* Returns zero on failure, non-zero on success.
|
||||
*/
|
||||
int
|
||||
sbgp_addr_range(const char *fn, struct cert_ip *ips, size_t *num_ips,
|
||||
enum afi afi, const IPAddressRange *range)
|
||||
{
|
||||
struct cert_ip ip;
|
||||
|
||||
memset(&ip, 0, sizeof(struct cert_ip));
|
||||
|
||||
ip.afi = afi;
|
||||
ip.type = CERT_IP_RANGE;
|
||||
|
||||
if (!ip_addr_parse(range->min, afi, fn, &ip.range.min)) {
|
||||
warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
|
||||
"invalid IP address", fn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ip_addr_parse(range->max, afi, fn, &ip.range.max)) {
|
||||
warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
|
||||
"invalid IP address", fn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ip_cert_compose_ranges(&ip)) {
|
||||
warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
|
||||
"IP address range reversed", fn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return append_ip(fn, ips, num_ips, &ip);
|
||||
}
|
||||
|
||||
static int
|
||||
sbgp_addr_inherit(const char *fn, struct cert_ip *ips, size_t *num_ips,
|
||||
enum afi afi)
|
||||
{
|
||||
struct cert_ip ip;
|
||||
|
||||
memset(&ip, 0, sizeof(struct cert_ip));
|
||||
|
||||
ip.afi = afi;
|
||||
ip.type = CERT_IP_INHERIT;
|
||||
|
||||
return append_ip(fn, ips, num_ips, &ip);
|
||||
}
|
||||
|
||||
int
|
||||
sbgp_parse_ipaddrblocks(const char *fn, const IPAddrBlocks *addrs,
|
||||
struct cert_ip **out_ips, size_t *out_num_ips)
|
||||
{
|
||||
const IPAddressFamily *af;
|
||||
const IPAddressOrRanges *aors;
|
||||
const IPAddressOrRange *aor;
|
||||
enum afi afi;
|
||||
struct cert_ip *ips = NULL;
|
||||
size_t num_ips = 0, num;
|
||||
int ipv4_seen = 0, ipv6_seen = 0;
|
||||
int i, j, addrsz;
|
||||
|
||||
assert(*out_ips == NULL && *out_num_ips == 0);
|
||||
|
||||
addrsz = sk_IPAddressFamily_num(addrs);
|
||||
if (addrsz != 1 && addrsz != 2) {
|
||||
warnx("%s: RFC 6487 section 4.8.10: unexpected number of "
|
||||
"ipAddrBlocks (got %d, expected 1 or 2)", fn, addrsz);
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < addrsz; i++) {
|
||||
af = sk_IPAddressFamily_value(addrs, i);
|
||||
|
||||
switch (af->ipAddressChoice->type) {
|
||||
case IPAddressChoice_inherit:
|
||||
aors = NULL;
|
||||
num = num_ips + 1;
|
||||
break;
|
||||
case IPAddressChoice_addressesOrRanges:
|
||||
aors = af->ipAddressChoice->u.addressesOrRanges;
|
||||
num = num_ips + sk_IPAddressOrRange_num(aors);
|
||||
break;
|
||||
default:
|
||||
warnx("%s: RFC 3779: IPAddressChoice: unknown type %d",
|
||||
fn, af->ipAddressChoice->type);
|
||||
goto out;
|
||||
}
|
||||
if (num == num_ips) {
|
||||
warnx("%s: RFC 6487 section 4.8.10: "
|
||||
"empty ipAddressesOrRanges", fn);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (num >= MAX_IP_SIZE)
|
||||
goto out;
|
||||
ips = recallocarray(ips, num_ips, num, sizeof(struct cert_ip));
|
||||
if (ips == NULL)
|
||||
err(1, NULL);
|
||||
|
||||
if (!ip_addr_afi_parse(fn, af->addressFamily, &afi)) {
|
||||
warnx("%s: RFC 3779: invalid AFI", fn);
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (afi) {
|
||||
case AFI_IPV4:
|
||||
if (ipv4_seen++ > 0) {
|
||||
warnx("%s: RFC 6487 section 4.8.10: "
|
||||
"IPv4 appears twice", fn);
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case AFI_IPV6:
|
||||
if (ipv6_seen++ > 0) {
|
||||
warnx("%s: RFC 6487 section 4.8.10: "
|
||||
"IPv6 appears twice", fn);
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (aors == NULL) {
|
||||
if (!sbgp_addr_inherit(fn, ips, &num_ips, afi))
|
||||
goto out;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (j = 0; j < sk_IPAddressOrRange_num(aors); j++) {
|
||||
aor = sk_IPAddressOrRange_value(aors, j);
|
||||
switch (aor->type) {
|
||||
case IPAddressOrRange_addressPrefix:
|
||||
if (!sbgp_addr(fn, ips, &num_ips, afi,
|
||||
aor->u.addressPrefix))
|
||||
goto out;
|
||||
break;
|
||||
case IPAddressOrRange_addressRange:
|
||||
if (!sbgp_addr_range(fn, ips, &num_ips, afi,
|
||||
aor->u.addressRange))
|
||||
goto out;
|
||||
break;
|
||||
default:
|
||||
warnx("%s: RFC 3779: IPAddressOrRange: "
|
||||
"unknown type %d", fn, aor->type);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*out_ips = ips;
|
||||
*out_num_ips = num_ips;
|
||||
|
||||
return 1;
|
||||
|
||||
out:
|
||||
free(ips);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse an IP Resources X.509v3 extension, RFC 6487 4.8.10, with
|
||||
* syntax documented in RFC 3779 starting in section 2.2.
|
||||
|
||||
+207
-1
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: ip.c,v 1.37 2025/12/04 06:11:44 tb Exp $ */
|
||||
/* $OpenBSD: ip.c,v 1.38 2026/05/02 10:35:18 tb Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -367,3 +368,208 @@ ip_warn(const char *fn, const char *msg, const struct cert_ip *ip)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Append an IP address structure to our list of results, ensuring there is
|
||||
* at most one inheritance marker per AFI and no overlapping ranges.
|
||||
*/
|
||||
static int
|
||||
append_ip(const char *fn, struct cert_ip *ips, size_t *num_ips,
|
||||
const struct cert_ip *ip)
|
||||
{
|
||||
if (!ip_addr_check_overlap(ip, fn, ips, *num_ips, 0))
|
||||
return 0;
|
||||
ips[(*num_ips)++] = *ip;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct a RFC 3779 2.2.3.8 range from its bit string.
|
||||
* Returns zero on failure, non-zero on success.
|
||||
*/
|
||||
int
|
||||
sbgp_addr(const char *fn, struct cert_ip *ips, size_t *num_ips, enum afi afi,
|
||||
const ASN1_BIT_STRING *bs)
|
||||
{
|
||||
struct cert_ip ip;
|
||||
|
||||
memset(&ip, 0, sizeof(struct cert_ip));
|
||||
|
||||
ip.afi = afi;
|
||||
ip.type = CERT_IP_ADDR;
|
||||
|
||||
if (!ip_addr_parse(bs, afi, fn, &ip.ip)) {
|
||||
warnx("%s: RFC 3779 section 2.2.3.8: IPAddress: "
|
||||
"invalid IP address", fn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ip_cert_compose_ranges(&ip)) {
|
||||
warnx("%s: RFC 3779 section 2.2.3.8: IPAddress: "
|
||||
"IP address range reversed", fn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return append_ip(fn, ips, num_ips, &ip);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse RFC 3779 2.2.3.9 range of addresses.
|
||||
* Returns zero on failure, non-zero on success.
|
||||
*/
|
||||
int
|
||||
sbgp_addr_range(const char *fn, struct cert_ip *ips, size_t *num_ips,
|
||||
enum afi afi, const IPAddressRange *range)
|
||||
{
|
||||
struct cert_ip ip;
|
||||
|
||||
memset(&ip, 0, sizeof(struct cert_ip));
|
||||
|
||||
ip.afi = afi;
|
||||
ip.type = CERT_IP_RANGE;
|
||||
|
||||
if (!ip_addr_parse(range->min, afi, fn, &ip.range.min)) {
|
||||
warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
|
||||
"invalid IP address", fn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ip_addr_parse(range->max, afi, fn, &ip.range.max)) {
|
||||
warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
|
||||
"invalid IP address", fn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ip_cert_compose_ranges(&ip)) {
|
||||
warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
|
||||
"IP address range reversed", fn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return append_ip(fn, ips, num_ips, &ip);
|
||||
}
|
||||
|
||||
static int
|
||||
sbgp_addr_inherit(const char *fn, struct cert_ip *ips, size_t *num_ips,
|
||||
enum afi afi)
|
||||
{
|
||||
struct cert_ip ip;
|
||||
|
||||
memset(&ip, 0, sizeof(struct cert_ip));
|
||||
|
||||
ip.afi = afi;
|
||||
ip.type = CERT_IP_INHERIT;
|
||||
|
||||
return append_ip(fn, ips, num_ips, &ip);
|
||||
}
|
||||
|
||||
int
|
||||
sbgp_parse_ipaddrblocks(const char *fn, const IPAddrBlocks *addrs,
|
||||
struct cert_ip **out_ips, size_t *out_num_ips)
|
||||
{
|
||||
const IPAddressFamily *af;
|
||||
const IPAddressOrRanges *aors;
|
||||
const IPAddressOrRange *aor;
|
||||
enum afi afi;
|
||||
struct cert_ip *ips = NULL;
|
||||
size_t num_ips = 0, num;
|
||||
int ipv4_seen = 0, ipv6_seen = 0;
|
||||
int i, j, addrsz;
|
||||
|
||||
assert(*out_ips == NULL && *out_num_ips == 0);
|
||||
|
||||
addrsz = sk_IPAddressFamily_num(addrs);
|
||||
if (addrsz != 1 && addrsz != 2) {
|
||||
warnx("%s: RFC 6487 section 4.8.10: unexpected number of "
|
||||
"ipAddrBlocks (got %d, expected 1 or 2)", fn, addrsz);
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < addrsz; i++) {
|
||||
af = sk_IPAddressFamily_value(addrs, i);
|
||||
|
||||
switch (af->ipAddressChoice->type) {
|
||||
case IPAddressChoice_inherit:
|
||||
aors = NULL;
|
||||
num = num_ips + 1;
|
||||
break;
|
||||
case IPAddressChoice_addressesOrRanges:
|
||||
aors = af->ipAddressChoice->u.addressesOrRanges;
|
||||
num = num_ips + sk_IPAddressOrRange_num(aors);
|
||||
break;
|
||||
default:
|
||||
warnx("%s: RFC 3779: IPAddressChoice: unknown type %d",
|
||||
fn, af->ipAddressChoice->type);
|
||||
goto out;
|
||||
}
|
||||
if (num == num_ips) {
|
||||
warnx("%s: RFC 6487 section 4.8.10: "
|
||||
"empty ipAddressesOrRanges", fn);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (num >= MAX_IP_SIZE)
|
||||
goto out;
|
||||
ips = recallocarray(ips, num_ips, num, sizeof(struct cert_ip));
|
||||
if (ips == NULL)
|
||||
err(1, NULL);
|
||||
|
||||
if (!ip_addr_afi_parse(fn, af->addressFamily, &afi)) {
|
||||
warnx("%s: RFC 3779: invalid AFI", fn);
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (afi) {
|
||||
case AFI_IPV4:
|
||||
if (ipv4_seen++ > 0) {
|
||||
warnx("%s: RFC 6487 section 4.8.10: "
|
||||
"IPv4 appears twice", fn);
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case AFI_IPV6:
|
||||
if (ipv6_seen++ > 0) {
|
||||
warnx("%s: RFC 6487 section 4.8.10: "
|
||||
"IPv6 appears twice", fn);
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (aors == NULL) {
|
||||
if (!sbgp_addr_inherit(fn, ips, &num_ips, afi))
|
||||
goto out;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (j = 0; j < sk_IPAddressOrRange_num(aors); j++) {
|
||||
aor = sk_IPAddressOrRange_value(aors, j);
|
||||
switch (aor->type) {
|
||||
case IPAddressOrRange_addressPrefix:
|
||||
if (!sbgp_addr(fn, ips, &num_ips, afi,
|
||||
aor->u.addressPrefix))
|
||||
goto out;
|
||||
break;
|
||||
case IPAddressOrRange_addressRange:
|
||||
if (!sbgp_addr_range(fn, ips, &num_ips, afi,
|
||||
aor->u.addressRange))
|
||||
goto out;
|
||||
break;
|
||||
default:
|
||||
warnx("%s: RFC 3779: IPAddressOrRange: "
|
||||
"unknown type %d", fn, aor->type);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*out_ips = ips;
|
||||
*out_num_ips = num_ips;
|
||||
|
||||
return 1;
|
||||
|
||||
out:
|
||||
free(ips);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user