1
0
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:
tb
2026-05-02 10:35:18 +00:00
parent 216fe456b2
commit 648db74a06
2 changed files with 208 additions and 207 deletions
+1 -206
View File
@@ -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
View File
@@ -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;
}