1*381ee599Stb /* $OpenBSD: as.c,v 1.17 2024/11/12 09:23:07 tb Exp $ */ 29a7e9e7fSjob /* 39a7e9e7fSjob * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv> 49a7e9e7fSjob * 59a7e9e7fSjob * Permission to use, copy, modify, and distribute this software for any 69a7e9e7fSjob * purpose with or without fee is hereby granted, provided that the above 79a7e9e7fSjob * copyright notice and this permission notice appear in all copies. 89a7e9e7fSjob * 99a7e9e7fSjob * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 109a7e9e7fSjob * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 119a7e9e7fSjob * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 129a7e9e7fSjob * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 139a7e9e7fSjob * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 149a7e9e7fSjob * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 159a7e9e7fSjob * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 169a7e9e7fSjob */ 179a7e9e7fSjob 189a7e9e7fSjob #include <err.h> 199a7e9e7fSjob #include <stdint.h> 209a7e9e7fSjob #include <stdlib.h> 219a7e9e7fSjob #include <string.h> 229a7e9e7fSjob #include <unistd.h> 239a7e9e7fSjob 249a7e9e7fSjob #include "extern.h" 259a7e9e7fSjob 262cdc38edStb /* Parse a uint32_t AS identifier from an ASN1_INTEGER. */ 279a7e9e7fSjob int 289a7e9e7fSjob as_id_parse(const ASN1_INTEGER *v, uint32_t *out) 299a7e9e7fSjob { 302cdc38edStb uint64_t res = 0; 319a7e9e7fSjob 322cdc38edStb if (!ASN1_INTEGER_get_uint64(&res, v)) 339a7e9e7fSjob return 0; 342cdc38edStb if (res > UINT32_MAX) 359a7e9e7fSjob return 0; 369a7e9e7fSjob *out = res; 379a7e9e7fSjob return 1; 389a7e9e7fSjob } 399a7e9e7fSjob 409a7e9e7fSjob /* 41*381ee599Stb * Given a newly-parsed AS number or range "as", make sure that "as" does 42*381ee599Stb * not overlap with any other numbers or ranges in the "ases" array. 439a7e9e7fSjob * This is defined by RFC 3779 section 3.2.3.4. 449a7e9e7fSjob * Returns zero on failure, non-zero on success. 459a7e9e7fSjob */ 469a7e9e7fSjob int 47*381ee599Stb as_check_overlap(const struct cert_as *as, const char *fn, 48*381ee599Stb const struct cert_as *ases, size_t num_ases, int quiet) 499a7e9e7fSjob { 509a7e9e7fSjob size_t i; 519a7e9e7fSjob 526822deefStb /* We can have only one inheritance statement. */ 539a7e9e7fSjob 54*381ee599Stb if (num_ases && 55*381ee599Stb (as->type == CERT_AS_INHERIT || ases[0].type == CERT_AS_INHERIT)) { 56e88acb21Stb if (!quiet) { 5780272c49Sderaadt warnx("%s: RFC 3779 section 3.2.3.3: " 586822deefStb "cannot have inheritance and multiple ASnum or " 596822deefStb "multiple inheritance", fn); 60e88acb21Stb } 619a7e9e7fSjob return 0; 629a7e9e7fSjob } 639a7e9e7fSjob 649a7e9e7fSjob /* Now check for overlaps between singletons/ranges. */ 659a7e9e7fSjob 66*381ee599Stb for (i = 0; i < num_ases; i++) { 67*381ee599Stb switch (ases[i].type) { 689a7e9e7fSjob case CERT_AS_ID: 69*381ee599Stb switch (as->type) { 709a7e9e7fSjob case CERT_AS_ID: 71*381ee599Stb if (as->id != ases[i].id) 72e88acb21Stb continue; 739a7e9e7fSjob break; 749a7e9e7fSjob case CERT_AS_RANGE: 75*381ee599Stb if (ases->range.min > ases[i].id || 76*381ee599Stb ases->range.max < ases[i].id) 77e88acb21Stb continue; 789a7e9e7fSjob break; 799a7e9e7fSjob default: 809a7e9e7fSjob abort(); 819a7e9e7fSjob } 829a7e9e7fSjob break; 839a7e9e7fSjob case CERT_AS_RANGE: 84*381ee599Stb switch (as->type) { 859a7e9e7fSjob case CERT_AS_ID: 86*381ee599Stb if (ases[i].range.min > as->id || 87*381ee599Stb ases[i].range.max < as->id) 88e88acb21Stb continue; 899a7e9e7fSjob break; 909a7e9e7fSjob case CERT_AS_RANGE: 91*381ee599Stb if (as->range.max < ases[i].range.min || 92*381ee599Stb as->range.min > ases[i].range.max) 93e88acb21Stb continue; 949a7e9e7fSjob break; 959a7e9e7fSjob default: 969a7e9e7fSjob abort(); 979a7e9e7fSjob } 989a7e9e7fSjob break; 999a7e9e7fSjob default: 1009a7e9e7fSjob abort(); 1019a7e9e7fSjob } 102e88acb21Stb if (!quiet) { 103e88acb21Stb warnx("%s: RFC 3779 section 3.2.3.4: " 104e88acb21Stb "cannot have overlapping ASnum", fn); 105e88acb21Stb } 106e88acb21Stb return 0; 107e88acb21Stb } 1089a7e9e7fSjob 1099a7e9e7fSjob return 1; 1109a7e9e7fSjob } 1119a7e9e7fSjob 1129a7e9e7fSjob /* 1139a7e9e7fSjob * See if a given AS range (which may be the same number, in the case of 1149a7e9e7fSjob * singleton AS identifiers) is covered by the AS numbers or ranges 115*381ee599Stb * specified in the "ases" array. 1169a7e9e7fSjob * Return <0 if there is no cover, 0 if we're inheriting, >0 if there is. 1179a7e9e7fSjob */ 1189a7e9e7fSjob int 1199a7e9e7fSjob as_check_covered(uint32_t min, uint32_t max, 120*381ee599Stb const struct cert_as *ases, size_t num_ases) 1219a7e9e7fSjob { 1229a7e9e7fSjob size_t i; 1239a7e9e7fSjob uint32_t amin, amax; 1249a7e9e7fSjob 125*381ee599Stb for (i = 0; i < num_ases; i++) { 126*381ee599Stb if (ases[i].type == CERT_AS_INHERIT) 1279a7e9e7fSjob return 0; 128*381ee599Stb amin = ases[i].type == CERT_AS_RANGE ? 129*381ee599Stb ases[i].range.min : ases[i].id; 130*381ee599Stb amax = ases[i].type == CERT_AS_RANGE ? 131*381ee599Stb ases[i].range.max : ases[i].id; 1329a7e9e7fSjob if (min >= amin && max <= amax) 1339a7e9e7fSjob return 1; 1349a7e9e7fSjob } 1359a7e9e7fSjob 1369a7e9e7fSjob return -1; 1379a7e9e7fSjob } 138891d6bceSjob 139891d6bceSjob void 1404032f119Stb as_warn(const char *fn, const char *msg, const struct cert_as *as) 141891d6bceSjob { 1424032f119Stb switch (as->type) { 143891d6bceSjob case CERT_AS_ID: 1444032f119Stb warnx("%s: %s: AS %u", fn, msg, as->id); 145891d6bceSjob break; 146891d6bceSjob case CERT_AS_RANGE: 1474032f119Stb warnx("%s: %s: AS range %u--%u", fn, msg, as->range.min, 1484032f119Stb as->range.max); 149891d6bceSjob break; 15076dbb2b6Stb case CERT_AS_INHERIT: 1514032f119Stb warnx("%s: %s: AS (inherit)", fn, msg); 15276dbb2b6Stb break; 153891d6bceSjob default: 154891d6bceSjob warnx("%s: corrupt cert", fn); 155891d6bceSjob break; 156891d6bceSjob } 157891d6bceSjob } 158