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