1 /* $OpenBSD: as.c,v 1.17 2024/11/12 09:23:07 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. */ 27 int 28 as_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 "as", make sure that "as" does 42 * not overlap with any other numbers or ranges in the "ases" array. 43 * This is defined by RFC 3779 section 3.2.3.4. 44 * Returns zero on failure, non-zero on success. 45 */ 46 int 47 as_check_overlap(const struct cert_as *as, const char *fn, 48 const struct cert_as *ases, size_t num_ases, int quiet) 49 { 50 size_t i; 51 52 /* We can have only one inheritance statement. */ 53 54 if (num_ases && 55 (as->type == CERT_AS_INHERIT || ases[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 < num_ases; i++) { 67 switch (ases[i].type) { 68 case CERT_AS_ID: 69 switch (as->type) { 70 case CERT_AS_ID: 71 if (as->id != ases[i].id) 72 continue; 73 break; 74 case CERT_AS_RANGE: 75 if (ases->range.min > ases[i].id || 76 ases->range.max < ases[i].id) 77 continue; 78 break; 79 default: 80 abort(); 81 } 82 break; 83 case CERT_AS_RANGE: 84 switch (as->type) { 85 case CERT_AS_ID: 86 if (ases[i].range.min > as->id || 87 ases[i].range.max < as->id) 88 continue; 89 break; 90 case CERT_AS_RANGE: 91 if (as->range.max < ases[i].range.min || 92 as->range.min > ases[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 "ases" array. 116 * Return <0 if there is no cover, 0 if we're inheriting, >0 if there is. 117 */ 118 int 119 as_check_covered(uint32_t min, uint32_t max, 120 const struct cert_as *ases, size_t num_ases) 121 { 122 size_t i; 123 uint32_t amin, amax; 124 125 for (i = 0; i < num_ases; i++) { 126 if (ases[i].type == CERT_AS_INHERIT) 127 return 0; 128 amin = ases[i].type == CERT_AS_RANGE ? 129 ases[i].range.min : ases[i].id; 130 amax = ases[i].type == CERT_AS_RANGE ? 131 ases[i].range.max : ases[i].id; 132 if (min >= amin && max <= amax) 133 return 1; 134 } 135 136 return -1; 137 } 138 139 void 140 as_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