xref: /openbsd-src/usr.sbin/rpki-client/as.c (revision fc405d53b73a2d73393cb97f684863d17b583e38)
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