1/* $OpenBSD: as.c,v 1.16 2023/12/27 07:15:55 tb Exp $ */ 2/* 3 * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18#include <err.h> 19#include <stdint.h> 20#include <stdlib.h> 21#include <string.h> 22#include <unistd.h> 23 24#include "extern.h" 25 26/* Parse a uint32_t AS identifier from an ASN1_INTEGER. */ 27int 28as_id_parse(const ASN1_INTEGER *v, uint32_t *out) 29{ 30 uint64_t res = 0; 31 32 if (!ASN1_INTEGER_get_uint64(&res, v)) 33 return 0; 34 if (res > UINT32_MAX) 35 return 0; 36 *out = res; 37 return 1; 38} 39 40/* 41 * Given a newly-parsed AS number or range "a", make sure that "a" does 42 * not overlap with any other numbers or ranges in the "as" array. 43 * This is defined by RFC 3779 section 3.2.3.4. 44 * Returns zero on failure, non-zero on success. 45 */ 46int 47as_check_overlap(const struct cert_as *a, const char *fn, 48 const struct cert_as *as, size_t asz, int quiet) 49{ 50 size_t i; 51 52 /* We can have only one inheritance statement. */ 53 54 if (asz && 55 (a->type == CERT_AS_INHERIT || as[0].type == CERT_AS_INHERIT)) { 56 if (!quiet) { 57 warnx("%s: RFC 3779 section 3.2.3.3: " 58 "cannot have inheritance and multiple ASnum or " 59 "multiple inheritance", fn); 60 } 61 return 0; 62 } 63 64 /* Now check for overlaps between singletons/ranges. */ 65 66 for (i = 0; i < asz; i++) { 67 switch (as[i].type) { 68 case CERT_AS_ID: 69 switch (a->type) { 70 case CERT_AS_ID: 71 if (a->id != as[i].id) 72 continue; 73 break; 74 case CERT_AS_RANGE: 75 if (as->range.min > as[i].id || 76 as->range.max < as[i].id) 77 continue; 78 break; 79 default: 80 abort(); 81 } 82 break; 83 case CERT_AS_RANGE: 84 switch (a->type) { 85 case CERT_AS_ID: 86 if (as[i].range.min > a->id || 87 as[i].range.max < a->id) 88 continue; 89 break; 90 case CERT_AS_RANGE: 91 if (a->range.max < as[i].range.min || 92 a->range.min > as[i].range.max) 93 continue; 94 break; 95 default: 96 abort(); 97 } 98 break; 99 default: 100 abort(); 101 } 102 if (!quiet) { 103 warnx("%s: RFC 3779 section 3.2.3.4: " 104 "cannot have overlapping ASnum", fn); 105 } 106 return 0; 107 } 108 109 return 1; 110} 111 112/* 113 * See if a given AS range (which may be the same number, in the case of 114 * singleton AS identifiers) is covered by the AS numbers or ranges 115 * specified in the "as" array. 116 * Return <0 if there is no cover, 0 if we're inheriting, >0 if there is. 117 */ 118int 119as_check_covered(uint32_t min, uint32_t max, 120 const struct cert_as *as, size_t asz) 121{ 122 size_t i; 123 uint32_t amin, amax; 124 125 for (i = 0; i < asz; i++) { 126 if (as[i].type == CERT_AS_INHERIT) 127 return 0; 128 amin = as[i].type == CERT_AS_RANGE ? 129 as[i].range.min : as[i].id; 130 amax = as[i].type == CERT_AS_RANGE ? 131 as[i].range.max : as[i].id; 132 if (min >= amin && max <= amax) 133 return 1; 134 } 135 136 return -1; 137} 138 139void 140as_warn(const char *fn, const char *msg, const struct cert_as *as) 141{ 142 switch (as->type) { 143 case CERT_AS_ID: 144 warnx("%s: %s: AS %u", fn, msg, as->id); 145 break; 146 case CERT_AS_RANGE: 147 warnx("%s: %s: AS range %u--%u", fn, msg, as->range.min, 148 as->range.max); 149 break; 150 case CERT_AS_INHERIT: 151 warnx("%s: %s: AS (inherit)", fn, msg); 152 break; 153 default: 154 warnx("%s: corrupt cert", fn); 155 break; 156 } 157} 158