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