1 /* $OpenBSD: as.c,v 1.12 2023/05/23 06:39:31 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 "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 */ 46 int 47 as_check_overlap(const struct cert_as *a, const char *fn, 48 const struct cert_as *as, size_t asz) 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 warnx("%s: RFC 3779 section 3.2.3.3: " 57 "cannot have inheritance and multiple ASnum or " 58 "multiple inheritance", fn); 59 return 0; 60 } 61 62 /* Now check for overlaps between singletons/ranges. */ 63 64 for (i = 0; i < asz; i++) 65 switch (as[i].type) { 66 case CERT_AS_ID: 67 switch (a->type) { 68 case CERT_AS_ID: 69 if (a->id != as[i].id) 70 break; 71 warnx("%s: RFC 3779 section 3.2.3.4: " 72 "cannot have overlapping ASnum", fn); 73 return 0; 74 case CERT_AS_RANGE: 75 if (as->range.min > as[i].id || 76 as->range.max < as[i].id) 77 break; 78 warnx("%s: RFC 3779 section 3.2.3.4: " 79 "cannot have overlapping ASnum", fn); 80 return 0; 81 default: 82 abort(); 83 } 84 break; 85 case CERT_AS_RANGE: 86 switch (a->type) { 87 case CERT_AS_ID: 88 if (as[i].range.min > a->id || 89 as[i].range.max < a->id) 90 break; 91 warnx("%s: RFC 3779 section 3.2.3.4: " 92 "cannot have overlapping ASnum", fn); 93 return 0; 94 case CERT_AS_RANGE: 95 if (a->range.max < as[i].range.min || 96 a->range.min > as[i].range.max) 97 break; 98 warnx("%s: RFC 3779 section 3.2.3.4: " 99 "cannot have overlapping ASnum", fn); 100 return 0; 101 default: 102 abort(); 103 } 104 break; 105 default: 106 abort(); 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 */ 118 int 119 as_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