xref: /openbsd/usr.sbin/rpki-client/as.c (revision 381ee599)
1*381ee599Stb /*	$OpenBSD: as.c,v 1.17 2024/11/12 09:23:07 tb Exp $ */
29a7e9e7fSjob /*
39a7e9e7fSjob  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
49a7e9e7fSjob  *
59a7e9e7fSjob  * Permission to use, copy, modify, and distribute this software for any
69a7e9e7fSjob  * purpose with or without fee is hereby granted, provided that the above
79a7e9e7fSjob  * copyright notice and this permission notice appear in all copies.
89a7e9e7fSjob  *
99a7e9e7fSjob  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
109a7e9e7fSjob  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
119a7e9e7fSjob  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
129a7e9e7fSjob  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
139a7e9e7fSjob  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
149a7e9e7fSjob  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
159a7e9e7fSjob  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
169a7e9e7fSjob  */
179a7e9e7fSjob 
189a7e9e7fSjob #include <err.h>
199a7e9e7fSjob #include <stdint.h>
209a7e9e7fSjob #include <stdlib.h>
219a7e9e7fSjob #include <string.h>
229a7e9e7fSjob #include <unistd.h>
239a7e9e7fSjob 
249a7e9e7fSjob #include "extern.h"
259a7e9e7fSjob 
262cdc38edStb /* Parse a uint32_t AS identifier from an ASN1_INTEGER. */
279a7e9e7fSjob int
as_id_parse(const ASN1_INTEGER * v,uint32_t * out)289a7e9e7fSjob as_id_parse(const ASN1_INTEGER *v, uint32_t *out)
299a7e9e7fSjob {
302cdc38edStb 	uint64_t res = 0;
319a7e9e7fSjob 
322cdc38edStb 	if (!ASN1_INTEGER_get_uint64(&res, v))
339a7e9e7fSjob 		return 0;
342cdc38edStb 	if (res > UINT32_MAX)
359a7e9e7fSjob 		return 0;
369a7e9e7fSjob 	*out = res;
379a7e9e7fSjob 	return 1;
389a7e9e7fSjob }
399a7e9e7fSjob 
409a7e9e7fSjob /*
41*381ee599Stb  * Given a newly-parsed AS number or range "as", make sure that "as" does
42*381ee599Stb  * not overlap with any other numbers or ranges in the "ases" array.
439a7e9e7fSjob  * This is defined by RFC 3779 section 3.2.3.4.
449a7e9e7fSjob  * Returns zero on failure, non-zero on success.
459a7e9e7fSjob  */
469a7e9e7fSjob int
as_check_overlap(const struct cert_as * as,const char * fn,const struct cert_as * ases,size_t num_ases,int quiet)47*381ee599Stb as_check_overlap(const struct cert_as *as, const char *fn,
48*381ee599Stb     const struct cert_as *ases, size_t num_ases, int quiet)
499a7e9e7fSjob {
509a7e9e7fSjob 	size_t	 i;
519a7e9e7fSjob 
526822deefStb 	/* We can have only one inheritance statement. */
539a7e9e7fSjob 
54*381ee599Stb 	if (num_ases &&
55*381ee599Stb 	    (as->type == CERT_AS_INHERIT || ases[0].type == CERT_AS_INHERIT)) {
56e88acb21Stb 		if (!quiet) {
5780272c49Sderaadt 			warnx("%s: RFC 3779 section 3.2.3.3: "
586822deefStb 			    "cannot have inheritance and multiple ASnum or "
596822deefStb 			    "multiple inheritance", fn);
60e88acb21Stb 		}
619a7e9e7fSjob 		return 0;
629a7e9e7fSjob 	}
639a7e9e7fSjob 
649a7e9e7fSjob 	/* Now check for overlaps between singletons/ranges. */
659a7e9e7fSjob 
66*381ee599Stb 	for (i = 0; i < num_ases; i++) {
67*381ee599Stb 		switch (ases[i].type) {
689a7e9e7fSjob 		case CERT_AS_ID:
69*381ee599Stb 			switch (as->type) {
709a7e9e7fSjob 			case CERT_AS_ID:
71*381ee599Stb 				if (as->id != ases[i].id)
72e88acb21Stb 					continue;
739a7e9e7fSjob 				break;
749a7e9e7fSjob 			case CERT_AS_RANGE:
75*381ee599Stb 				if (ases->range.min > ases[i].id ||
76*381ee599Stb 				    ases->range.max < ases[i].id)
77e88acb21Stb 					continue;
789a7e9e7fSjob 				break;
799a7e9e7fSjob 			default:
809a7e9e7fSjob 				abort();
819a7e9e7fSjob 			}
829a7e9e7fSjob 			break;
839a7e9e7fSjob 		case CERT_AS_RANGE:
84*381ee599Stb 			switch (as->type) {
859a7e9e7fSjob 			case CERT_AS_ID:
86*381ee599Stb 				if (ases[i].range.min > as->id ||
87*381ee599Stb 				    ases[i].range.max < as->id)
88e88acb21Stb 					continue;
899a7e9e7fSjob 				break;
909a7e9e7fSjob 			case CERT_AS_RANGE:
91*381ee599Stb 				if (as->range.max < ases[i].range.min ||
92*381ee599Stb 				    as->range.min > ases[i].range.max)
93e88acb21Stb 					continue;
949a7e9e7fSjob 				break;
959a7e9e7fSjob 			default:
969a7e9e7fSjob 				abort();
979a7e9e7fSjob 			}
989a7e9e7fSjob 			break;
999a7e9e7fSjob 		default:
1009a7e9e7fSjob 			abort();
1019a7e9e7fSjob 		}
102e88acb21Stb 		if (!quiet) {
103e88acb21Stb 			warnx("%s: RFC 3779 section 3.2.3.4: "
104e88acb21Stb 			    "cannot have overlapping ASnum", fn);
105e88acb21Stb 		}
106e88acb21Stb 		return 0;
107e88acb21Stb 	}
1089a7e9e7fSjob 
1099a7e9e7fSjob 	return 1;
1109a7e9e7fSjob }
1119a7e9e7fSjob 
1129a7e9e7fSjob /*
1139a7e9e7fSjob  * See if a given AS range (which may be the same number, in the case of
1149a7e9e7fSjob  * singleton AS identifiers) is covered by the AS numbers or ranges
115*381ee599Stb  * specified in the "ases" array.
1169a7e9e7fSjob  * Return <0 if there is no cover, 0 if we're inheriting, >0 if there is.
1179a7e9e7fSjob  */
1189a7e9e7fSjob int
as_check_covered(uint32_t min,uint32_t max,const struct cert_as * ases,size_t num_ases)1199a7e9e7fSjob as_check_covered(uint32_t min, uint32_t max,
120*381ee599Stb     const struct cert_as *ases, size_t num_ases)
1219a7e9e7fSjob {
1229a7e9e7fSjob 	size_t	 i;
1239a7e9e7fSjob 	uint32_t amin, amax;
1249a7e9e7fSjob 
125*381ee599Stb 	for (i = 0; i < num_ases; i++) {
126*381ee599Stb 		if (ases[i].type == CERT_AS_INHERIT)
1279a7e9e7fSjob 			return 0;
128*381ee599Stb 		amin = ases[i].type == CERT_AS_RANGE ?
129*381ee599Stb 		    ases[i].range.min : ases[i].id;
130*381ee599Stb 		amax = ases[i].type == CERT_AS_RANGE ?
131*381ee599Stb 		    ases[i].range.max : ases[i].id;
1329a7e9e7fSjob 		if (min >= amin && max <= amax)
1339a7e9e7fSjob 			return 1;
1349a7e9e7fSjob 	}
1359a7e9e7fSjob 
1369a7e9e7fSjob 	return -1;
1379a7e9e7fSjob }
138891d6bceSjob 
139891d6bceSjob void
as_warn(const char * fn,const char * msg,const struct cert_as * as)1404032f119Stb as_warn(const char *fn, const char *msg, const struct cert_as *as)
141891d6bceSjob {
1424032f119Stb 	switch (as->type) {
143891d6bceSjob 	case CERT_AS_ID:
1444032f119Stb 		warnx("%s: %s: AS %u", fn, msg, as->id);
145891d6bceSjob 		break;
146891d6bceSjob 	case CERT_AS_RANGE:
1474032f119Stb 		warnx("%s: %s: AS range %u--%u", fn, msg, as->range.min,
1484032f119Stb 		    as->range.max);
149891d6bceSjob 		break;
15076dbb2b6Stb 	case CERT_AS_INHERIT:
1514032f119Stb 		warnx("%s: %s: AS (inherit)", fn, msg);
15276dbb2b6Stb 		break;
153891d6bceSjob 	default:
154891d6bceSjob 		warnx("%s: corrupt cert", fn);
155891d6bceSjob 		break;
156891d6bceSjob 	}
157891d6bceSjob }
158