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