1 /* $OpenBSD: as.c,v 1.6 2020/09/12 15:46:48 claudio 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 <sys/socket.h> 19 20 #include <assert.h> 21 #include <err.h> 22 #include <stdarg.h> 23 #include <stdint.h> 24 #include <stdlib.h> 25 #include <string.h> 26 #include <unistd.h> 27 28 #include "extern.h" 29 30 /* 31 * Parse a uint32_t AS identifier from an ASN1_INTEGER. 32 * This relies on the specification for ASN1_INTEGER itself, which is 33 * essentially a series of big-endian bytes in the unsigned case. 34 * All we do here is check if the number is negative then start copying 35 * over bytes. 36 * This is necessary because ASN1_INTEGER_get() on a 32-bit machine 37 * (e.g., i386) will fail for AS numbers of UINT32_MAX. 38 */ 39 int 40 as_id_parse(const ASN1_INTEGER *v, uint32_t *out) 41 { 42 int i; 43 uint32_t res = 0; 44 45 /* If the negative bit is set, this is wrong. */ 46 47 if (v->type & V_ASN1_NEG) 48 return 0; 49 50 /* Too many bytes for us to consider. */ 51 52 if ((size_t)v->length > sizeof(uint32_t)) 53 return 0; 54 55 /* Stored as big-endian bytes. */ 56 57 for (i = 0; i < v->length; i++) { 58 res <<= 8; 59 res |= v->data[i]; 60 } 61 62 *out = res; 63 return 1; 64 } 65 66 /* 67 * Given a newly-parsed AS number or range "a", make sure that "a" does 68 * not overlap with any other numbers or ranges in the "as" array. 69 * This is defined by RFC 3779 section 3.2.3.4. 70 * Returns zero on failure, non-zero on success. 71 */ 72 int 73 as_check_overlap(const struct cert_as *a, const char *fn, 74 const struct cert_as *as, size_t asz) 75 { 76 size_t i; 77 78 /* We can have only one inheritence statement. */ 79 80 if (asz && 81 (a->type == CERT_AS_INHERIT || as[0].type == CERT_AS_INHERIT)) { 82 warnx("%s: RFC 3779 section 3.2.3.3: " 83 "cannot have inheritence and multiple ASnum or " 84 "multiple inheritence", fn); 85 return 0; 86 } 87 88 /* Now check for overlaps between singletons/ranges. */ 89 90 for (i = 0; i < asz; i++) 91 switch (as[i].type) { 92 case CERT_AS_ID: 93 switch (a->type) { 94 case CERT_AS_ID: 95 if (a->id != as[i].id) 96 break; 97 warnx("%s: RFC 3779 section 3.2.3.4: " 98 "cannot have overlapping ASnum", fn); 99 return 0; 100 case CERT_AS_RANGE: 101 if (as->range.min > as[i].id || 102 as->range.max < as[i].id) 103 break; 104 warnx("%s: RFC 3779 section 3.2.3.4: " 105 "cannot have overlapping ASnum", fn); 106 return 0; 107 default: 108 abort(); 109 } 110 break; 111 case CERT_AS_RANGE: 112 switch (a->type) { 113 case CERT_AS_ID: 114 if (as[i].range.min > a->id || 115 as[i].range.max < a->id) 116 break; 117 warnx("%s: RFC 3779 section 3.2.3.4: " 118 "cannot have overlapping ASnum", fn); 119 return 0; 120 case CERT_AS_RANGE: 121 if (a->range.max < as[i].range.min || 122 a->range.min > as[i].range.max) 123 break; 124 warnx("%s: RFC 3779 section 3.2.3.4: " 125 "cannot have overlapping ASnum", fn); 126 return 0; 127 default: 128 abort(); 129 } 130 break; 131 default: 132 abort(); 133 } 134 135 return 1; 136 } 137 138 /* 139 * See if a given AS range (which may be the same number, in the case of 140 * singleton AS identifiers) is covered by the AS numbers or ranges 141 * specified in the "as" array. 142 * Return <0 if there is no cover, 0 if we're inheriting, >0 if there is. 143 */ 144 int 145 as_check_covered(uint32_t min, uint32_t max, 146 const struct cert_as *as, size_t asz) 147 { 148 size_t i; 149 uint32_t amin, amax; 150 151 for (i = 0; i < asz; i++) { 152 if (as[i].type == CERT_AS_INHERIT) 153 return 0; 154 amin = as[i].type == CERT_AS_RANGE ? 155 as[i].range.min : as[i].id; 156 amax = as[i].type == CERT_AS_RANGE? 157 as[i].range.max : as[i].id; 158 if (min >= amin && max <= amax) 159 return 1; 160 } 161 162 return -1; 163 } 164