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