Bug Summary

File:src/usr.sbin/rpki-client/cert.c
Warning:line 753, column 2
Value stored to 'nid' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name cert.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/rpki-client/obj -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/usr.sbin/rpki-client -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/rpki-client/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/usr.sbin/rpki-client/cert.c
1/* $OpenBSD: cert.c,v 1.121 2023/12/14 07:52:53 tb Exp $ */
2/*
3 * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
4 * Copyright (c) 2021 Job Snijders <job@openbsd.org>
5 * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include <assert.h>
21#include <err.h>
22#include <stdlib.h>
23#include <string.h>
24#include <unistd.h>
25
26#include <openssl/asn1.h>
27#include <openssl/x509.h>
28#include <openssl/x509v3.h>
29
30#include "extern.h"
31
32/*
33 * A parsing sequence of a file (which may just be <stdin>).
34 */
35struct parse {
36 struct cert *res; /* result */
37 const char *fn; /* currently-parsed file */
38};
39
40extern ASN1_OBJECT *certpol_oid; /* id-cp-ipAddr-asNumber cert policy */
41extern ASN1_OBJECT *carepo_oid; /* 1.3.6.1.5.5.7.48.5 (caRepository) */
42extern ASN1_OBJECT *manifest_oid; /* 1.3.6.1.5.5.7.48.10 (rpkiManifest) */
43extern ASN1_OBJECT *notify_oid; /* 1.3.6.1.5.5.7.48.13 (rpkiNotify) */
44
45/*
46 * Append an IP address structure to our list of results.
47 * This will also constrain us to having at most one inheritance
48 * statement per AFI and also not have overlapping ranges (as prohibited
49 * in section 2.2.3.6).
50 * It does not make sure that ranges can't coalesce, that is, that any
51 * two ranges abut each other.
52 * This is warned against in section 2.2.3.6, but doesn't change the
53 * semantics of the system.
54 * Returns zero on failure (IP overlap) non-zero on success.
55 */
56static int
57append_ip(const char *fn, struct cert_ip *ips, size_t *ipsz,
58 const struct cert_ip *ip)
59{
60 if (!ip_addr_check_overlap(ip, fn, ips, *ipsz, 0))
61 return 0;
62 ips[(*ipsz)++] = *ip;
63 return 1;
64}
65
66/*
67 * Append an AS identifier structure to our list of results.
68 * Makes sure that the identifiers do not overlap or improperly inherit
69 * as defined by RFC 3779 section 3.3.
70 */
71static int
72append_as(const char *fn, struct cert_as *ases, size_t *asz,
73 const struct cert_as *as)
74{
75 if (!as_check_overlap(as, fn, ases, *asz, 0))
76 return 0;
77 ases[(*asz)++] = *as;
78 return 1;
79}
80
81/*
82 * Parse a range of AS identifiers as in 3.2.3.8.
83 * Returns zero on failure, non-zero on success.
84 */
85int
86sbgp_as_range(const char *fn, struct cert_as *ases, size_t *asz,
87 const ASRange *range)
88{
89 struct cert_as as;
90
91 memset(&as, 0, sizeof(struct cert_as));
92 as.type = CERT_AS_RANGE;
93
94 if (!as_id_parse(range->min, &as.range.min)) {
95 warnx("%s: RFC 3779 section 3.2.3.8 (via RFC 1930): "
96 "malformed AS identifier", fn);
97 return 0;
98 }
99
100 if (!as_id_parse(range->max, &as.range.max)) {
101 warnx("%s: RFC 3779 section 3.2.3.8 (via RFC 1930): "
102 "malformed AS identifier", fn);
103 return 0;
104 }
105
106 if (as.range.max == as.range.min) {
107 warnx("%s: RFC 3379 section 3.2.3.8: ASRange: "
108 "range is singular", fn);
109 return 0;
110 } else if (as.range.max < as.range.min) {
111 warnx("%s: RFC 3379 section 3.2.3.8: ASRange: "
112 "range is out of order", fn);
113 return 0;
114 }
115
116 return append_as(fn, ases, asz, &as);
117}
118
119/*
120 * Parse an entire 3.2.3.10 integer type.
121 */
122int
123sbgp_as_id(const char *fn, struct cert_as *ases, size_t *asz,
124 const ASN1_INTEGER *i)
125{
126 struct cert_as as;
127
128 memset(&as, 0, sizeof(struct cert_as));
129 as.type = CERT_AS_ID;
130
131 if (!as_id_parse(i, &as.id)) {
132 warnx("%s: RFC 3779 section 3.2.3.10 (via RFC 1930): "
133 "malformed AS identifier", fn);
134 return 0;
135 }
136 if (as.id == 0) {
137 warnx("%s: RFC 3779 section 3.2.3.10 (via RFC 1930): "
138 "AS identifier zero is reserved", fn);
139 return 0;
140 }
141
142 return append_as(fn, ases, asz, &as);
143}
144
145static int
146sbgp_as_inherit(const char *fn, struct cert_as *ases, size_t *asz)
147{
148 struct cert_as as;
149
150 memset(&as, 0, sizeof(struct cert_as));
151 as.type = CERT_AS_INHERIT;
152
153 return append_as(fn, ases, asz, &as);
154}
155
156int
157sbgp_parse_assysnum(const char *fn, const ASIdentifiers *asidentifiers,
158 struct cert_as **out_as, size_t *out_asz)
159{
160 const ASIdOrRanges *aors = NULL((void *)0);
161 struct cert_as *as = NULL((void *)0);
162 size_t asz = 0, sz;
163 int i;
164
165 assert(*out_as == NULL && *out_asz == 0)((*out_as == ((void *)0) && *out_asz == 0) ? (void)0 :
__assert2("/usr/src/usr.sbin/rpki-client/cert.c", 165, __func__
, "*out_as == NULL && *out_asz == 0"))
;
166
167 if (asidentifiers->rdi != NULL((void *)0)) {
168 warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
169 "should not have RDI values", fn);
170 goto out;
171 }
172
173 if (asidentifiers->asnum == NULL((void *)0)) {
174 warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
175 "no AS number resource set", fn);
176 goto out;
177 }
178
179 switch (asidentifiers->asnum->type) {
180 case ASIdentifierChoice_inherit0:
181 sz = 1;
182 break;
183 case ASIdentifierChoice_asIdsOrRanges1:
184 aors = asidentifiers->asnum->u.asIdsOrRanges;
185 sz = sk_ASIdOrRange_num(aors)sk_num(((_STACK*) (1 ? (aors) : (struct stack_st_ASIdOrRange*
)0)))
;
186 break;
187 default:
188 warnx("%s: RFC 3779 section 3.2.3.2: ASIdentifierChoice: "
189 "unknown type %d", fn, asidentifiers->asnum->type);
190 goto out;
191 }
192
193 if (sz == 0) {
194 warnx("%s: RFC 6487 section 4.8.11: empty asIdsOrRanges", fn);
195 goto out;
196 }
197 if (sz >= MAX_AS_SIZE200000) {
198 warnx("%s: too many AS number entries: limit %d",
199 fn, MAX_AS_SIZE200000);
200 goto out;
201 }
202 as = calloc(sz, sizeof(struct cert_as));
203 if (as == NULL((void *)0))
204 err(1, NULL((void *)0));
205
206 if (aors == NULL((void *)0)) {
207 if (!sbgp_as_inherit(fn, as, &asz))
208 goto out;
209 }
210
211 for (i = 0; i < sk_ASIdOrRange_num(aors)sk_num(((_STACK*) (1 ? (aors) : (struct stack_st_ASIdOrRange*
)0)))
; i++) {
212 const ASIdOrRange *aor;
213
214 aor = sk_ASIdOrRange_value(aors, i)((ASIdOrRange *)sk_value(((_STACK*) (1 ? (aors) : (struct stack_st_ASIdOrRange
*)0)), (i)))
;
215 switch (aor->type) {
216 case ASIdOrRange_id0:
217 if (!sbgp_as_id(fn, as, &asz, aor->u.id))
218 goto out;
219 break;
220 case ASIdOrRange_range1:
221 if (!sbgp_as_range(fn, as, &asz, aor->u.range))
222 goto out;
223 break;
224 default:
225 warnx("%s: RFC 3779 section 3.2.3.5: ASIdOrRange: "
226 "unknown type %d", fn, aor->type);
227 goto out;
228 }
229 }
230
231 *out_as = as;
232 *out_asz = asz;
233
234 return 1;
235
236 out:
237 free(as);
238
239 return 0;
240}
241
242/*
243 * Parse RFC 6487 4.8.11 X509v3 extension, with syntax documented in RFC
244 * 3779 starting in section 3.2.
245 * Returns zero on failure, non-zero on success.
246 */
247static int
248sbgp_assysnum(struct parse *p, X509_EXTENSION *ext)
249{
250 ASIdentifiers *asidentifiers = NULL((void *)0);
251 int rc = 0;
252
253 if (!X509_EXTENSION_get_critical(ext)) {
254 warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
255 "extension not critical", p->fn);
256 goto out;
257 }
258
259 if ((asidentifiers = X509V3_EXT_d2i(ext)) == NULL((void *)0)) {
260 warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
261 "failed extension parse", p->fn);
262 goto out;
263 }
264
265 if (!sbgp_parse_assysnum(p->fn, asidentifiers,
266 &p->res->as, &p->res->asz))
267 goto out;
268
269 rc = 1;
270 out:
271 ASIdentifiers_free(asidentifiers);
272 return rc;
273}
274
275/*
276 * Construct a RFC 3779 2.2.3.8 range from its bit string.
277 * Returns zero on failure, non-zero on success.
278 */
279int
280sbgp_addr(const char *fn, struct cert_ip *ips, size_t *ipsz, enum afi afi,
281 const ASN1_BIT_STRING *bs)
282{
283 struct cert_ip ip;
284
285 memset(&ip, 0, sizeof(struct cert_ip));
286
287 ip.afi = afi;
288 ip.type = CERT_IP_ADDR;
289
290 if (!ip_addr_parse(bs, afi, fn, &ip.ip)) {
291 warnx("%s: RFC 3779 section 2.2.3.8: IPAddress: "
292 "invalid IP address", fn);
293 return 0;
294 }
295
296 if (!ip_cert_compose_ranges(&ip)) {
297 warnx("%s: RFC 3779 section 2.2.3.8: IPAddress: "
298 "IP address range reversed", fn);
299 return 0;
300 }
301
302 return append_ip(fn, ips, ipsz, &ip);
303}
304
305/*
306 * Parse RFC 3779 2.2.3.9 range of addresses.
307 * Returns zero on failure, non-zero on success.
308 */
309int
310sbgp_addr_range(const char *fn, struct cert_ip *ips, size_t *ipsz,
311 enum afi afi, const IPAddressRange *range)
312{
313 struct cert_ip ip;
314
315 memset(&ip, 0, sizeof(struct cert_ip));
316
317 ip.afi = afi;
318 ip.type = CERT_IP_RANGE;
319
320 if (!ip_addr_parse(range->min, afi, fn, &ip.range.min)) {
321 warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
322 "invalid IP address", fn);
323 return 0;
324 }
325
326 if (!ip_addr_parse(range->max, afi, fn, &ip.range.max)) {
327 warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
328 "invalid IP address", fn);
329 return 0;
330 }
331
332 if (!ip_cert_compose_ranges(&ip)) {
333 warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
334 "IP address range reversed", fn);
335 return 0;
336 }
337
338 return append_ip(fn, ips, ipsz, &ip);
339}
340
341static int
342sbgp_addr_inherit(const char *fn, struct cert_ip *ips, size_t *ipsz,
343 enum afi afi)
344{
345 struct cert_ip ip;
346
347 memset(&ip, 0, sizeof(struct cert_ip));
348
349 ip.afi = afi;
350 ip.type = CERT_IP_INHERIT;
351
352 return append_ip(fn, ips, ipsz, &ip);
353}
354
355int
356sbgp_parse_ipaddrblk(const char *fn, const IPAddrBlocks *addrblk,
357 struct cert_ip **out_ips, size_t *out_ipsz)
358{
359 const IPAddressFamily *af;
360 const IPAddressOrRanges *aors;
361 const IPAddressOrRange *aor;
362 enum afi afi;
363 struct cert_ip *ips = NULL((void *)0);
364 size_t ipsz = 0, sz;
365 int ipv4_seen = 0, ipv6_seen = 0;
366 int i, j, ipaddrblocksz;
367
368 assert(*out_ips == NULL && *out_ipsz == 0)((*out_ips == ((void *)0) && *out_ipsz == 0) ? (void)
0 : __assert2("/usr/src/usr.sbin/rpki-client/cert.c", 368, __func__
, "*out_ips == NULL && *out_ipsz == 0"))
;
369
370 ipaddrblocksz = sk_IPAddressFamily_num(addrblk)sk_num(((_STACK*) (1 ? (addrblk) : (struct stack_st_IPAddressFamily
*)0)))
;
371 if (ipaddrblocksz != 1 && ipaddrblocksz != 2) {
372 warnx("%s: RFC 6487 section 4.8.10: unexpected number of "
373 "ipAddrBlocks (got %d, expected 1 or 2)",
374 fn, ipaddrblocksz);
375 goto out;
376 }
377
378 for (i = 0; i < ipaddrblocksz; i++) {
379 af = sk_IPAddressFamily_value(addrblk, i)((IPAddressFamily *)sk_value(((_STACK*) (1 ? (addrblk) : (struct
stack_st_IPAddressFamily*)0)), (i)))
;
380
381 switch (af->ipAddressChoice->type) {
382 case IPAddressChoice_inherit0:
383 aors = NULL((void *)0);
384 sz = ipsz + 1;
385 break;
386 case IPAddressChoice_addressesOrRanges1:
387 aors = af->ipAddressChoice->u.addressesOrRanges;
388 sz = ipsz + sk_IPAddressOrRange_num(aors)sk_num(((_STACK*) (1 ? (aors) : (struct stack_st_IPAddressOrRange
*)0)))
;
389 break;
390 default:
391 warnx("%s: RFC 3779: IPAddressChoice: unknown type %d",
392 fn, af->ipAddressChoice->type);
393 goto out;
394 }
395 if (sz == ipsz) {
396 warnx("%s: RFC 6487 section 4.8.10: "
397 "empty ipAddressesOrRanges", fn);
398 goto out;
399 }
400
401 if (sz >= MAX_IP_SIZE200000)
402 goto out;
403 ips = recallocarray(ips, ipsz, sz, sizeof(struct cert_ip));
404 if (ips == NULL((void *)0))
405 err(1, NULL((void *)0));
406
407 if (!ip_addr_afi_parse(fn, af->addressFamily, &afi)) {
408 warnx("%s: RFC 3779: invalid AFI", fn);
409 goto out;
410 }
411
412 switch(afi) {
413 case AFI_IPV4:
414 if (ipv4_seen++ > 0) {
415 warnx("%s: RFC 6487 section 4.8.10: "
416 "IPv4 appears twice", fn);
417 goto out;
418 }
419 break;
420 case AFI_IPV6:
421 if (ipv6_seen++ > 0) {
422 warnx("%s: RFC 6487 section 4.8.10: "
423 "IPv6 appears twice", fn);
424 goto out;
425 }
426 break;
427 }
428
429 if (aors == NULL((void *)0)) {
430 if (!sbgp_addr_inherit(fn, ips, &ipsz, afi))
431 goto out;
432 continue;
433 }
434
435 for (j = 0; j < sk_IPAddressOrRange_num(aors)sk_num(((_STACK*) (1 ? (aors) : (struct stack_st_IPAddressOrRange
*)0)))
; j++) {
436 aor = sk_IPAddressOrRange_value(aors, j)((IPAddressOrRange *)sk_value(((_STACK*) (1 ? (aors) : (struct
stack_st_IPAddressOrRange*)0)), (j)))
;
437 switch (aor->type) {
438 case IPAddressOrRange_addressPrefix0:
439 if (!sbgp_addr(fn, ips, &ipsz, afi,
440 aor->u.addressPrefix))
441 goto out;
442 break;
443 case IPAddressOrRange_addressRange1:
444 if (!sbgp_addr_range(fn, ips, &ipsz, afi,
445 aor->u.addressRange))
446 goto out;
447 break;
448 default:
449 warnx("%s: RFC 3779: IPAddressOrRange: "
450 "unknown type %d", fn, aor->type);
451 goto out;
452 }
453 }
454 }
455
456 *out_ips = ips;
457 *out_ipsz = ipsz;
458
459 return 1;
460
461 out:
462 free(ips);
463
464 return 0;
465}
466
467/*
468 * Parse an sbgp-ipAddrBlock X509 extension, RFC 6487 4.8.10, with
469 * syntax documented in RFC 3779 starting in section 2.2.
470 * Returns zero on failure, non-zero on success.
471 */
472static int
473sbgp_ipaddrblk(struct parse *p, X509_EXTENSION *ext)
474{
475 IPAddrBlocks *addrblk = NULL((void *)0);
476 int rc = 0;
477
478 if (!X509_EXTENSION_get_critical(ext)) {
479 warnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: "
480 "extension not critical", p->fn);
481 goto out;
482 }
483
484 if ((addrblk = X509V3_EXT_d2i(ext)) == NULL((void *)0)) {
485 warnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: "
486 "failed extension parse", p->fn);
487 goto out;
488 }
489
490 if (!sbgp_parse_ipaddrblk(p->fn, addrblk, &p->res->ips, &p->res->ipsz))
491 goto out;
492
493 if (p->res->ipsz == 0) {
494 warnx("%s: RFC 6487 section 4.8.10: empty ipAddrBlock", p->fn);
495 goto out;
496 }
497
498 rc = 1;
499 out:
500 IPAddrBlocks_free(addrblk);
501 return rc;
502}
503
504/*
505 * Parse "Subject Information Access" extension, RFC 6487 4.8.8.
506 * Returns zero on failure, non-zero on success.
507 */
508static int
509sbgp_sia(struct parse *p, X509_EXTENSION *ext)
510{
511 AUTHORITY_INFO_ACCESS *sia = NULL((void *)0);
512 ACCESS_DESCRIPTION *ad;
513 ASN1_OBJECT *oid;
514 const char *mftfilename;
515 int i, rc = 0;
516
517 if (X509_EXTENSION_get_critical(ext)) {
518 warnx("%s: RFC 6487 section 4.8.8: SIA: "
519 "extension not non-critical", p->fn);
520 goto out;
521 }
522
523 if ((sia = X509V3_EXT_d2i(ext)) == NULL((void *)0)) {
524 warnx("%s: RFC 6487 section 4.8.8: SIA: failed extension parse",
525 p->fn);
526 goto out;
527 }
528
529 for (i = 0; i < sk_ACCESS_DESCRIPTION_num(sia)sk_num(((_STACK*) (1 ? (sia) : (struct stack_st_ACCESS_DESCRIPTION
*)0)))
; i++) {
530 ad = sk_ACCESS_DESCRIPTION_value(sia, i)((ACCESS_DESCRIPTION *)sk_value(((_STACK*) (1 ? (sia) : (struct
stack_st_ACCESS_DESCRIPTION*)0)), (i)))
;
531
532 oid = ad->method;
533
534 if (OBJ_cmp(oid, carepo_oid) == 0) {
535 if (!x509_location(p->fn, "SIA: caRepository",
536 "rsync://", ad->location, &p->res->repo))
537 goto out;
538 } else if (OBJ_cmp(oid, manifest_oid) == 0) {
539 if (!x509_location(p->fn, "SIA: rpkiManifest",
540 "rsync://", ad->location, &p->res->mft))
541 goto out;
542 } else if (OBJ_cmp(oid, notify_oid) == 0) {
543 if (!x509_location(p->fn, "SIA: rpkiNotify",
544 "https://", ad->location, &p->res->notify))
545 goto out;
546 }
547 }
548
549 if (p->res->mft == NULL((void *)0) || p->res->repo == NULL((void *)0)) {
550 warnx("%s: RFC 6487 section 4.8.8: SIA: missing caRepository "
551 "or rpkiManifest", p->fn);
552 goto out;
553 }
554
555 mftfilename = strrchr(p->res->mft, '/');
556 if (mftfilename == NULL((void *)0)) {
557 warnx("%s: SIA: invalid rpkiManifest entry", p->fn);
558 goto out;
559 }
560 mftfilename++;
561 if (!valid_filename(mftfilename, strlen(mftfilename))) {
562 warnx("%s: SIA: rpkiManifest filename contains invalid "
563 "characters", p->fn);
564 goto out;
565 }
566
567 if (strstr(p->res->mft, p->res->repo) != p->res->mft) {
568 warnx("%s: RFC 6487 section 4.8.8: SIA: "
569 "conflicting URIs for caRepository and rpkiManifest",
570 p->fn);
571 goto out;
572 }
573
574 if (rtype_from_file_extension(p->res->mft) != RTYPE_MFT) {
575 warnx("%s: RFC 6487 section 4.8.8: SIA: "
576 "not an MFT file", p->fn);
577 goto out;
578 }
579
580 rc = 1;
581 out:
582 AUTHORITY_INFO_ACCESS_free(sia);
583 return rc;
584}
585
586/*
587 * Parse the certificate policies extension and check that it follows RFC 7318.
588 * Returns zero on failure, non-zero on success.
589 */
590static int
591certificate_policies(struct parse *p, X509_EXTENSION *ext)
592{
593 STACK_OF(POLICYINFO)struct stack_st_POLICYINFO *policies = NULL((void *)0);
594 POLICYINFO *policy;
595 STACK_OF(POLICYQUALINFO)struct stack_st_POLICYQUALINFO *qualifiers;
596 POLICYQUALINFO *qualifier;
597 int nid;
598 int rc = 0;
599
600 if (!X509_EXTENSION_get_critical(ext)) {
601 warnx("%s: RFC 6487 section 4.8.9: certificatePolicies: "
602 "extension not critical", p->fn);
603 goto out;
604 }
605
606 if ((policies = X509V3_EXT_d2i(ext)) == NULL((void *)0)) {
607 warnx("%s: RFC 6487 section 4.8.9: certificatePolicies: "
608 "failed extension parse", p->fn);
609 goto out;
610 }
611
612 if (sk_POLICYINFO_num(policies)sk_num(((_STACK*) (1 ? (policies) : (struct stack_st_POLICYINFO
*)0)))
!= 1) {
613 warnx("%s: RFC 6487 section 4.8.9: certificatePolicies: "
614 "want 1 policy, got %d", p->fn,
615 sk_POLICYINFO_num(policies)sk_num(((_STACK*) (1 ? (policies) : (struct stack_st_POLICYINFO
*)0)))
);
616 goto out;
617 }
618
619 policy = sk_POLICYINFO_value(policies, 0)((POLICYINFO *)sk_value(((_STACK*) (1 ? (policies) : (struct stack_st_POLICYINFO
*)0)), (0)))
;
620 assert(policy != NULL && policy->policyid != NULL)((policy != ((void *)0) && policy->policyid != ((void
*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/rpki-client/cert.c"
, 620, __func__, "policy != NULL && policy->policyid != NULL"
))
;
621
622 if (OBJ_cmp(policy->policyid, certpol_oid) != 0) {
623 char pbuf[128], cbuf[128];
624
625 OBJ_obj2txt(pbuf, sizeof(pbuf), policy->policyid, 1);
626 OBJ_obj2txt(cbuf, sizeof(cbuf), certpol_oid, 1);
627 warnx("%s: RFC 7318 section 2: certificatePolicies: "
628 "unexpected OID: %s, want %s", p->fn, pbuf, cbuf);
629 goto out;
630 }
631
632 /* Policy qualifiers are optional. If they're absent, we're done. */
633 if ((qualifiers = policy->qualifiers) == NULL((void *)0)) {
634 rc = 1;
635 goto out;
636 }
637
638 if (sk_POLICYQUALINFO_num(qualifiers)sk_num(((_STACK*) (1 ? (qualifiers) : (struct stack_st_POLICYQUALINFO
*)0)))
!= 1) {
639 warnx("%s: RFC 7318 section 2: certificatePolicies: "
640 "want 1 policy qualifier, got %d", p->fn,
641 sk_POLICYQUALINFO_num(qualifiers)sk_num(((_STACK*) (1 ? (qualifiers) : (struct stack_st_POLICYQUALINFO
*)0)))
);
642 goto out;
643 }
644
645 qualifier = sk_POLICYQUALINFO_value(qualifiers, 0)((POLICYQUALINFO *)sk_value(((_STACK*) (1 ? (qualifiers) : (struct
stack_st_POLICYQUALINFO*)0)), (0)))
;
646 assert(qualifier != NULL && qualifier->pqualid != NULL)((qualifier != ((void *)0) && qualifier->pqualid !=
((void *)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/rpki-client/cert.c"
, 646, __func__, "qualifier != NULL && qualifier->pqualid != NULL"
))
;
647
648 if ((nid = OBJ_obj2nid(qualifier->pqualid)) != NID_id_qt_cps164) {
649 warnx("%s: RFC 7318 section 2: certificatePolicies: "
650 "want CPS, got %d (%s)", p->fn, nid, OBJ_nid2sn(nid));
651 goto out;
652 }
653
654 if (verbose > 1 && !filemode)
655 warnx("%s: CPS %.*s", p->fn, qualifier->d.cpsuri->length,
656 qualifier->d.cpsuri->data);
657
658 rc = 1;
659 out:
660 sk_POLICYINFO_pop_free(policies, POLICYINFO_free)sk_pop_free(((_STACK*) (1 ? (policies) : (struct stack_st_POLICYINFO
*)0)), ((void (*)(void *)) ((1 ? (POLICYINFO_free) : (void (*
)(POLICYINFO *))0))))
;
661 return rc;
662}
663
664/*
665 * Lightweight version of cert_parse_pre() for EE certs.
666 * Parses the two RFC 3779 extensions, and performs some sanity checks.
667 * Returns cert on success and NULL on failure.
668 */
669struct cert *
670cert_parse_ee_cert(const char *fn, int talid, X509 *x)
671{
672 struct parse p;
673 X509_EXTENSION *ext;
674 int index;
675
676 memset(&p, 0, sizeof(struct parse));
677 p.fn = fn;
678 if ((p.res = calloc(1, sizeof(struct cert))) == NULL((void *)0))
679 err(1, NULL((void *)0));
680
681 if (X509_get_version(x) != 2) {
682 warnx("%s: RFC 6487 4.1: X.509 version must be v3", fn);
683 goto out;
684 }
685
686 if (!x509_valid_subject(fn, x))
687 goto out;
688
689 if (X509_get_key_usage(x) != KU_DIGITAL_SIGNATURE0x0080) {
690 warnx("%s: RFC 6487 section 4.8.4: KU must be digitalSignature",
691 fn);
692 goto out;
693 }
694
695 /* EKU may be allowed for some purposes in the future. */
696 if (X509_get_extended_key_usage(x) != UINT32_MAX0xffffffffU) {
697 warnx("%s: RFC 6487 section 4.8.5: EKU not allowed", fn);
698 goto out;
699 }
700
701 index = X509_get_ext_by_NID(x, NID_sbgp_ipAddrBlock290, -1);
702 if ((ext = X509_get_ext(x, index)) != NULL((void *)0)) {
703 if (!sbgp_ipaddrblk(&p, ext))
704 goto out;
705 }
706
707 index = X509_get_ext_by_NID(x, NID_sbgp_autonomousSysNum291, -1);
708 if ((ext = X509_get_ext(x, index)) != NULL((void *)0)) {
709 if (!sbgp_assysnum(&p, ext))
710 goto out;
711 }
712
713 if (!X509_up_ref(x)) {
714 warnx("%s: X509_up_ref failed", fn);
715 goto out;
716 }
717
718 p.res->x509 = x;
719 p.res->talid = talid;
720
721 if (!constraints_validate(fn, p.res))
722 goto out;
723
724 return p.res;
725
726 out:
727 cert_free(p.res);
728 return NULL((void *)0);
729}
730
731/*
732 * Parse and partially validate an RPKI X509 certificate (either a trust
733 * anchor or a certificate) as defined in RFC 6487.
734 * Returns the parse results or NULL on failure.
735 */
736struct cert *
737cert_parse_pre(const char *fn, const unsigned char *der, size_t len)
738{
739 const unsigned char *oder;
740 int extsz;
741 size_t i;
742 X509 *x = NULL((void *)0);
743 X509_EXTENSION *ext = NULL((void *)0);
744 const X509_ALGOR *palg;
745 const ASN1_BIT_STRING *piuid = NULL((void *)0), *psuid = NULL((void *)0);
746 const ASN1_OBJECT *cobj;
747 ASN1_OBJECT *obj;
748 EVP_PKEY *pkey;
749 struct parse p;
750 int nid, ip, as, sia, cp, crldp, aia, aki, ski,
751 eku, bc, ku;
752
753 nid = ip = as = sia = cp = crldp = aia = aki = ski = eku = bc = ku = 0;
Value stored to 'nid' is never read
754
755 /* just fail for empty buffers, the warning was printed elsewhere */
756 if (der == NULL((void *)0))
757 return NULL((void *)0);
758
759 memset(&p, 0, sizeof(struct parse));
760 p.fn = fn;
761 if ((p.res = calloc(1, sizeof(struct cert))) == NULL((void *)0))
762 err(1, NULL((void *)0));
763
764 oder = der;
765 if ((x = d2i_X509(NULL((void *)0), &der, len)) == NULL((void *)0)) {
766 warnx("%s: d2i_X509", p.fn);
767 goto out;
768 }
769 if (der != oder + len) {
770 warnx("%s: %td bytes trailing garbage", fn, oder + len - der);
771 goto out;
772 }
773
774 /* Cache X509v3 extensions, see X509_check_ca(3). */
775 if (X509_check_purpose(x, -1, -1) <= 0) {
776 warnx("%s: could not cache X509v3 extensions", p.fn);
777 goto out;
778 }
779
780 if (X509_get_version(x) != 2) {
781 warnx("%s: RFC 6487 4.1: X.509 version must be v3", fn);
782 goto out;
783 }
784
785 X509_get0_signature(NULL((void *)0), &palg, x);
786 if (palg == NULL((void *)0)) {
787 warnx("%s: X509_get0_signature", p.fn);
788 goto out;
789 }
790 X509_ALGOR_get0(&cobj, NULL((void *)0), NULL((void *)0), palg);
791 nid = OBJ_obj2nid(cobj);
792 if (nid == NID_ecdsa_with_SHA256794) {
793 if (verbose)
794 warnx("%s: P-256 support is experimental", fn);
795 } else if (nid != NID_sha256WithRSAEncryption668) {
796 warnx("%s: RFC 7935: wrong signature algorithm %s, want %s",
797 fn, OBJ_nid2ln(nid),
798 OBJ_nid2ln(NID_sha256WithRSAEncryption668));
799 goto out;
800 }
801
802 X509_get0_uids(x, &piuid, &psuid);
803 if (piuid != NULL((void *)0) || psuid != NULL((void *)0)) {
804 warnx("%s: issuer or subject unique identifiers not allowed",
805 fn);
806 goto out;
807 }
808
809 if (!x509_valid_subject(p.fn, x))
810 goto out;
811
812 /* Look for X509v3 extensions. */
813
814 if ((extsz = X509_get_ext_count(x)) < 0)
815 errx(1, "X509_get_ext_count");
816
817 for (i = 0; i < (size_t)extsz; i++) {
818 ext = X509_get_ext(x, i);
819 assert(ext != NULL)((ext != ((void *)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/rpki-client/cert.c"
, 819, __func__, "ext != NULL"))
;
820 obj = X509_EXTENSION_get_object(ext);
821 assert(obj != NULL)((obj != ((void *)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/rpki-client/cert.c"
, 821, __func__, "obj != NULL"))
;
822
823 switch (nid = OBJ_obj2nid(obj)) {
824 case NID_sbgp_ipAddrBlock290:
825 if (ip++ > 0)
826 goto dup;
827 if (!sbgp_ipaddrblk(&p, ext))
828 goto out;
829 break;
830 case NID_sbgp_autonomousSysNum291:
831 if (as++ > 0)
832 goto dup;
833 if (!sbgp_assysnum(&p, ext))
834 goto out;
835 break;
836 case NID_sinfo_access398:
837 if (sia++ > 0)
838 goto dup;
839 if (!sbgp_sia(&p, ext))
840 goto out;
841 break;
842 case NID_certificate_policies89:
843 if (cp++ > 0)
844 goto dup;
845 if (!certificate_policies(&p, ext))
846 goto out;
847 break;
848 case NID_crl_distribution_points103:
849 if (crldp++ > 0)
850 goto dup;
851 break;
852 case NID_info_access177:
853 if (aia++ > 0)
854 goto dup;
855 break;
856 case NID_authority_key_identifier90:
857 if (aki++ > 0)
858 goto dup;
859 break;
860 case NID_subject_key_identifier82:
861 if (ski++ > 0)
862 goto dup;
863 break;
864 case NID_ext_key_usage126:
865 if (eku++ > 0)
866 goto dup;
867 break;
868 case NID_basic_constraints87:
869 if (bc++ > 0)
870 goto dup;
871 break;
872 case NID_key_usage83:
873 if (ku++ > 0)
874 goto dup;
875 break;
876 default:
877 /* unexpected extensions warrant investigation */
878 {
879 char objn[64];
880 OBJ_obj2txt(objn, sizeof(objn), obj, 0);
881 warnx("%s: ignoring %s (NID %d)",
882 p.fn, objn, OBJ_obj2nid(obj));
883 }
884 break;
885 }
886 }
887
888 if (!x509_get_aki(x, p.fn, &p.res->aki))
889 goto out;
890 if (!x509_get_ski(x, p.fn, &p.res->ski))
891 goto out;
892 if (!x509_get_aia(x, p.fn, &p.res->aia))
893 goto out;
894 if (!x509_get_crl(x, p.fn, &p.res->crl))
895 goto out;
896 if (!x509_get_notbefore(x, p.fn, &p.res->notbefore))
897 goto out;
898 if (!x509_get_notafter(x, p.fn, &p.res->notafter))
899 goto out;
900 p.res->purpose = x509_get_purpose(x, p.fn);
901
902 /* Validation on required fields. */
903
904 switch (p.res->purpose) {
905 case CERT_PURPOSE_CA:
906 if ((pkey = X509_get0_pubkey(x)) == NULL((void *)0)) {
907 warnx("%s: X509_get0_pubkey failed", p.fn);
908 goto out;
909 }
910 if (!valid_ca_pkey(p.fn, pkey))
911 goto out;
912
913 if (X509_get_key_usage(x) != (KU_KEY_CERT_SIGN0x0004 | KU_CRL_SIGN0x0002)) {
914 warnx("%s: RFC 6487 section 4.8.4: key usage violation",
915 p.fn);
916 goto out;
917 }
918
919 /* EKU may be allowed for some purposes in the future. */
920 if (X509_get_extended_key_usage(x) != UINT32_MAX0xffffffffU) {
921 warnx("%s: RFC 6487 section 4.8.5: EKU not allowed",
922 fn);
923 goto out;
924 }
925
926 if (p.res->mft == NULL((void *)0)) {
927 warnx("%s: RFC 6487 section 4.8.8: missing SIA", p.fn);
928 goto out;
929 }
930 if (p.res->asz == 0 && p.res->ipsz == 0) {
931 warnx("%s: missing IP or AS resources", p.fn);
932 goto out;
933 }
934 break;
935 case CERT_PURPOSE_BGPSEC_ROUTER:
936 p.res->pubkey = x509_get_pubkey(x, p.fn);
937 if (p.res->pubkey == NULL((void *)0)) {
938 warnx("%s: x509_get_pubkey failed", p.fn);
939 goto out;
940 }
941 if (p.res->ipsz > 0) {
942 warnx("%s: unexpected IP resources in BGPsec cert",
943 p.fn);
944 goto out;
945 }
946 for (i = 0; i < p.res->asz; i++) {
947 if (p.res->as[i].type == CERT_AS_INHERIT) {
948 warnx("%s: inherit elements not allowed in EE"
949 " cert", p.fn);
950 goto out;
951 }
952 }
953 if (sia) {
954 warnx("%s: unexpected SIA extension in BGPsec cert",
955 p.fn);
956 goto out;
957 }
958 break;
959 default:
960 warnx("%s: x509_get_purpose failed in %s", p.fn, __func__);
961 goto out;
962 }
963
964 if (p.res->ski == NULL((void *)0)) {
965 warnx("%s: RFC 6487 section 8.4.2: missing SKI", p.fn);
966 goto out;
967 }
968
969 p.res->x509 = x;
970 return p.res;
971
972 dup:
973 warnx("%s: RFC 5280 section 4.2: duplicate %s extension", fn,
974 OBJ_nid2sn(nid));
975 out:
976 cert_free(p.res);
977 X509_free(x);
978 return NULL((void *)0);
979}
980
981struct cert *
982cert_parse(const char *fn, struct cert *p)
983{
984 if (p == NULL((void *)0))
985 return NULL((void *)0);
986
987 if (p->aki == NULL((void *)0)) {
988 warnx("%s: RFC 6487 section 8.4.2: "
989 "non-trust anchor missing AKI", fn);
990 goto badcert;
991 }
992 if (strcmp(p->aki, p->ski) == 0) {
993 warnx("%s: RFC 6487 section 8.4.2: "
994 "non-trust anchor AKI may not match SKI", fn);
995 goto badcert;
996 }
997 if (p->aia == NULL((void *)0)) {
998 warnx("%s: RFC 6487 section 8.4.7: AIA: extension missing", fn);
999 goto badcert;
1000 }
1001 if (p->crl == NULL((void *)0)) {
1002 warnx("%s: RFC 6487 section 4.8.6: CRL: "
1003 "no CRL distribution point extension", fn);
1004 goto badcert;
1005 }
1006 return p;
1007
1008badcert:
1009 cert_free(p);
1010 return NULL((void *)0);
1011}
1012
1013struct cert *
1014ta_parse(const char *fn, struct cert *p, const unsigned char *pkey,
1015 size_t pkeysz)
1016{
1017 ASN1_TIME *notBefore, *notAfter;
1018 EVP_PKEY *pk, *opk;
1019
1020 if (p == NULL((void *)0))
1021 return NULL((void *)0);
1022
1023 /* first check pubkey against the one from the TAL */
1024 pk = d2i_PUBKEY(NULL((void *)0), &pkey, pkeysz);
1025 if (pk == NULL((void *)0)) {
1026 warnx("%s: RFC 6487 (trust anchor): bad TAL pubkey", fn);
1027 goto badcert;
1028 }
1029 if ((opk = X509_get0_pubkey(p->x509)) == NULL((void *)0)) {
1030 warnx("%s: RFC 6487 (trust anchor): missing pubkey", fn);
1031 goto badcert;
1032 }
1033 if (EVP_PKEY_cmp(pk, opk) != 1) {
1034 warnx("%s: RFC 6487 (trust anchor): "
1035 "pubkey does not match TAL pubkey", fn);
1036 goto badcert;
1037 }
1038
1039 if ((notBefore = X509_get_notBeforeX509_getm_notBefore(p->x509)) == NULL((void *)0)) {
1040 warnx("%s: certificate has invalid notBefore", fn);
1041 goto badcert;
1042 }
1043 if ((notAfter = X509_get_notAfterX509_getm_notAfter(p->x509)) == NULL((void *)0)) {
1044 warnx("%s: certificate has invalid notAfter", fn);
1045 goto badcert;
1046 }
1047 if (X509_cmp_current_time(notBefore) != -1) {
1048 warnx("%s: certificate not yet valid", fn);
1049 goto badcert;
1050 }
1051 if (X509_cmp_current_time(notAfter) != 1) {
1052 warnx("%s: certificate has expired", fn);
1053 goto badcert;
1054 }
1055 if (p->aki != NULL((void *)0) && strcmp(p->aki, p->ski)) {
1056 warnx("%s: RFC 6487 section 8.4.2: "
1057 "trust anchor AKI, if specified, must match SKI", fn);
1058 goto badcert;
1059 }
1060 if (p->aia != NULL((void *)0)) {
1061 warnx("%s: RFC 6487 section 8.4.7: "
1062 "trust anchor must not have AIA", fn);
1063 goto badcert;
1064 }
1065 if (p->crl != NULL((void *)0)) {
1066 warnx("%s: RFC 6487 section 8.4.2: "
1067 "trust anchor may not specify CRL resource", fn);
1068 goto badcert;
1069 }
1070 if (p->purpose == CERT_PURPOSE_BGPSEC_ROUTER) {
1071 warnx("%s: BGPsec cert cannot be a trust anchor", fn);
1072 goto badcert;
1073 }
1074 if (x509_any_inherits(p->x509)) {
1075 warnx("%s: Trust anchor IP/AS resources may not inherit", fn);
1076 goto badcert;
1077 }
1078
1079 EVP_PKEY_free(pk);
1080 return p;
1081
1082badcert:
1083 EVP_PKEY_free(pk);
1084 cert_free(p);
1085 return NULL((void *)0);
1086}
1087
1088/*
1089 * Free parsed certificate contents.
1090 * Passing NULL is a noop.
1091 */
1092void
1093cert_free(struct cert *p)
1094{
1095 if (p == NULL((void *)0))
1096 return;
1097
1098 free(p->crl);
1099 free(p->repo);
1100 free(p->mft);
1101 free(p->notify);
1102 free(p->ips);
1103 free(p->as);
1104 free(p->aia);
1105 free(p->aki);
1106 free(p->ski);
1107 free(p->pubkey);
1108 X509_free(p->x509);
1109 free(p);
1110}
1111
1112/*
1113 * Write certificate parsed content into buffer.
1114 * See cert_read() for the other side of the pipe.
1115 */
1116void
1117cert_buffer(struct ibuf *b, const struct cert *p)
1118{
1119 io_simple_buffer(b, &p->notafter, sizeof(p->notafter));
1120 io_simple_buffer(b, &p->purpose, sizeof(p->purpose));
1121 io_simple_buffer(b, &p->talid, sizeof(p->talid));
1122 io_simple_buffer(b, &p->repoid, sizeof(p->repoid));
1123 io_simple_buffer(b, &p->ipsz, sizeof(p->ipsz));
1124 io_simple_buffer(b, &p->asz, sizeof(p->asz));
1125
1126 io_simple_buffer(b, p->ips, p->ipsz * sizeof(p->ips[0]));
1127 io_simple_buffer(b, p->as, p->asz * sizeof(p->as[0]));
1128
1129 io_str_buffer(b, p->mft);
1130 io_str_buffer(b, p->notify);
1131 io_str_buffer(b, p->repo);
1132 io_str_buffer(b, p->crl);
1133 io_str_buffer(b, p->aia);
1134 io_str_buffer(b, p->aki);
1135 io_str_buffer(b, p->ski);
1136 io_str_buffer(b, p->pubkey);
1137}
1138
1139/*
1140 * Allocate and read parsed certificate content from descriptor.
1141 * The pointer must be freed with cert_free().
1142 * Always returns a valid pointer.
1143 */
1144struct cert *
1145cert_read(struct ibuf *b)
1146{
1147 struct cert *p;
1148
1149 if ((p = calloc(1, sizeof(struct cert))) == NULL((void *)0))
1150 err(1, NULL((void *)0));
1151
1152 io_read_buf(b, &p->notafter, sizeof(p->notafter));
1153 io_read_buf(b, &p->purpose, sizeof(p->purpose));
1154 io_read_buf(b, &p->talid, sizeof(p->talid));
1155 io_read_buf(b, &p->repoid, sizeof(p->repoid));
1156 io_read_buf(b, &p->ipsz, sizeof(p->ipsz));
1157 io_read_buf(b, &p->asz, sizeof(p->asz));
1158
1159 p->ips = calloc(p->ipsz, sizeof(struct cert_ip));
1160 if (p->ips == NULL((void *)0))
1161 err(1, NULL((void *)0));
1162 io_read_buf(b, p->ips, p->ipsz * sizeof(p->ips[0]));
1163
1164 p->as = calloc(p->asz, sizeof(struct cert_as));
1165 if (p->as == NULL((void *)0))
1166 err(1, NULL((void *)0));
1167 io_read_buf(b, p->as, p->asz * sizeof(p->as[0]));
1168
1169 io_read_str(b, &p->mft);
1170 io_read_str(b, &p->notify);
1171 io_read_str(b, &p->repo);
1172 io_read_str(b, &p->crl);
1173 io_read_str(b, &p->aia);
1174 io_read_str(b, &p->aki);
1175 io_read_str(b, &p->ski);
1176 io_read_str(b, &p->pubkey);
1177
1178 assert(p->mft != NULL || p->purpose == CERT_PURPOSE_BGPSEC_ROUTER)((p->mft != ((void *)0) || p->purpose == CERT_PURPOSE_BGPSEC_ROUTER
) ? (void)0 : __assert2("/usr/src/usr.sbin/rpki-client/cert.c"
, 1178, __func__, "p->mft != NULL || p->purpose == CERT_PURPOSE_BGPSEC_ROUTER"
))
;
1179 assert(p->ski)((p->ski) ? (void)0 : __assert2("/usr/src/usr.sbin/rpki-client/cert.c"
, 1179, __func__, "p->ski"))
;
1180 return p;
1181}
1182
1183static inline int
1184authcmp(struct auth *a, struct auth *b)
1185{
1186 return strcmp(a->cert->ski, b->cert->ski);
1187}
1188
1189RB_GENERATE_STATIC(auth_tree, auth, entry, authcmp)__attribute__((__unused__)) static void auth_tree_RB_INSERT_COLOR
(struct auth_tree *head, struct auth *elm) { struct auth *parent
, *gparent, *tmp; while ((parent = (elm)->entry.rbe_parent
) && (parent)->entry.rbe_color == 1) { gparent = (
parent)->entry.rbe_parent; if (parent == (gparent)->entry
.rbe_left) { tmp = (gparent)->entry.rbe_right; if (tmp &&
(tmp)->entry.rbe_color == 1) { (tmp)->entry.rbe_color =
0; do { (parent)->entry.rbe_color = 0; (gparent)->entry
.rbe_color = 1; } while (0); elm = gparent; continue; } if ((
parent)->entry.rbe_right == elm) { do { (tmp) = (parent)->
entry.rbe_right; if (((parent)->entry.rbe_right = (tmp)->
entry.rbe_left)) { ((tmp)->entry.rbe_left)->entry.rbe_parent
= (parent); } do {} while (0); if (((tmp)->entry.rbe_parent
= (parent)->entry.rbe_parent)) { if ((parent) == ((parent
)->entry.rbe_parent)->entry.rbe_left) ((parent)->entry
.rbe_parent)->entry.rbe_left = (tmp); else ((parent)->entry
.rbe_parent)->entry.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->entry.rbe_left = (parent); (parent)->entry
.rbe_parent = (tmp); do {} while (0); if (((tmp)->entry.rbe_parent
)) do {} while (0); } while (0); tmp = parent; parent = elm; elm
= tmp; } do { (parent)->entry.rbe_color = 0; (gparent)->
entry.rbe_color = 1; } while (0); do { (tmp) = (gparent)->
entry.rbe_left; if (((gparent)->entry.rbe_left = (tmp)->
entry.rbe_right)) { ((tmp)->entry.rbe_right)->entry.rbe_parent
= (gparent); } do {} while (0); if (((tmp)->entry.rbe_parent
= (gparent)->entry.rbe_parent)) { if ((gparent) == ((gparent
)->entry.rbe_parent)->entry.rbe_left) ((gparent)->entry
.rbe_parent)->entry.rbe_left = (tmp); else ((gparent)->
entry.rbe_parent)->entry.rbe_right = (tmp); } else (head)->
rbh_root = (tmp); (tmp)->entry.rbe_right = (gparent); (gparent
)->entry.rbe_parent = (tmp); do {} while (0); if (((tmp)->
entry.rbe_parent)) do {} while (0); } while (0); } else { tmp
= (gparent)->entry.rbe_left; if (tmp && (tmp)->
entry.rbe_color == 1) { (tmp)->entry.rbe_color = 0; do { (
parent)->entry.rbe_color = 0; (gparent)->entry.rbe_color
= 1; } while (0); elm = gparent; continue; } if ((parent)->
entry.rbe_left == elm) { do { (tmp) = (parent)->entry.rbe_left
; if (((parent)->entry.rbe_left = (tmp)->entry.rbe_right
)) { ((tmp)->entry.rbe_right)->entry.rbe_parent = (parent
); } do {} while (0); if (((tmp)->entry.rbe_parent = (parent
)->entry.rbe_parent)) { if ((parent) == ((parent)->entry
.rbe_parent)->entry.rbe_left) ((parent)->entry.rbe_parent
)->entry.rbe_left = (tmp); else ((parent)->entry.rbe_parent
)->entry.rbe_right = (tmp); } else (head)->rbh_root = (
tmp); (tmp)->entry.rbe_right = (parent); (parent)->entry
.rbe_parent = (tmp); do {} while (0); if (((tmp)->entry.rbe_parent
)) do {} while (0); } while (0); tmp = parent; parent = elm; elm
= tmp; } do { (parent)->entry.rbe_color = 0; (gparent)->
entry.rbe_color = 1; } while (0); do { (tmp) = (gparent)->
entry.rbe_right; if (((gparent)->entry.rbe_right = (tmp)->
entry.rbe_left)) { ((tmp)->entry.rbe_left)->entry.rbe_parent
= (gparent); } do {} while (0); if (((tmp)->entry.rbe_parent
= (gparent)->entry.rbe_parent)) { if ((gparent) == ((gparent
)->entry.rbe_parent)->entry.rbe_left) ((gparent)->entry
.rbe_parent)->entry.rbe_left = (tmp); else ((gparent)->
entry.rbe_parent)->entry.rbe_right = (tmp); } else (head)->
rbh_root = (tmp); (tmp)->entry.rbe_left = (gparent); (gparent
)->entry.rbe_parent = (tmp); do {} while (0); if (((tmp)->
entry.rbe_parent)) do {} while (0); } while (0); } } (head->
rbh_root)->entry.rbe_color = 0; } __attribute__((__unused__
)) static void auth_tree_RB_REMOVE_COLOR(struct auth_tree *head
, struct auth *parent, struct auth *elm) { struct auth *tmp; while
((elm == ((void *)0) || (elm)->entry.rbe_color == 0) &&
elm != (head)->rbh_root) { if ((parent)->entry.rbe_left
== elm) { tmp = (parent)->entry.rbe_right; if ((tmp)->
entry.rbe_color == 1) { do { (tmp)->entry.rbe_color = 0; (
parent)->entry.rbe_color = 1; } while (0); do { (tmp) = (parent
)->entry.rbe_right; if (((parent)->entry.rbe_right = (tmp
)->entry.rbe_left)) { ((tmp)->entry.rbe_left)->entry
.rbe_parent = (parent); } do {} while (0); if (((tmp)->entry
.rbe_parent = (parent)->entry.rbe_parent)) { if ((parent) ==
((parent)->entry.rbe_parent)->entry.rbe_left) ((parent
)->entry.rbe_parent)->entry.rbe_left = (tmp); else ((parent
)->entry.rbe_parent)->entry.rbe_right = (tmp); } else (
head)->rbh_root = (tmp); (tmp)->entry.rbe_left = (parent
); (parent)->entry.rbe_parent = (tmp); do {} while (0); if
(((tmp)->entry.rbe_parent)) do {} while (0); } while (0);
tmp = (parent)->entry.rbe_right; } if (((tmp)->entry.rbe_left
== ((void *)0) || ((tmp)->entry.rbe_left)->entry.rbe_color
== 0) && ((tmp)->entry.rbe_right == ((void *)0) ||
((tmp)->entry.rbe_right)->entry.rbe_color == 0)) { (tmp
)->entry.rbe_color = 1; elm = parent; parent = (elm)->entry
.rbe_parent; } else { if ((tmp)->entry.rbe_right == ((void
*)0) || ((tmp)->entry.rbe_right)->entry.rbe_color == 0
) { struct auth *oleft; if ((oleft = (tmp)->entry.rbe_left
)) (oleft)->entry.rbe_color = 0; (tmp)->entry.rbe_color
= 1; do { (oleft) = (tmp)->entry.rbe_left; if (((tmp)->
entry.rbe_left = (oleft)->entry.rbe_right)) { ((oleft)->
entry.rbe_right)->entry.rbe_parent = (tmp); } do {} while (
0); if (((oleft)->entry.rbe_parent = (tmp)->entry.rbe_parent
)) { if ((tmp) == ((tmp)->entry.rbe_parent)->entry.rbe_left
) ((tmp)->entry.rbe_parent)->entry.rbe_left = (oleft); else
((tmp)->entry.rbe_parent)->entry.rbe_right = (oleft); }
else (head)->rbh_root = (oleft); (oleft)->entry.rbe_right
= (tmp); (tmp)->entry.rbe_parent = (oleft); do {} while (
0); if (((oleft)->entry.rbe_parent)) do {} while (0); } while
(0); tmp = (parent)->entry.rbe_right; } (tmp)->entry.rbe_color
= (parent)->entry.rbe_color; (parent)->entry.rbe_color
= 0; if ((tmp)->entry.rbe_right) ((tmp)->entry.rbe_right
)->entry.rbe_color = 0; do { (tmp) = (parent)->entry.rbe_right
; if (((parent)->entry.rbe_right = (tmp)->entry.rbe_left
)) { ((tmp)->entry.rbe_left)->entry.rbe_parent = (parent
); } do {} while (0); if (((tmp)->entry.rbe_parent = (parent
)->entry.rbe_parent)) { if ((parent) == ((parent)->entry
.rbe_parent)->entry.rbe_left) ((parent)->entry.rbe_parent
)->entry.rbe_left = (tmp); else ((parent)->entry.rbe_parent
)->entry.rbe_right = (tmp); } else (head)->rbh_root = (
tmp); (tmp)->entry.rbe_left = (parent); (parent)->entry
.rbe_parent = (tmp); do {} while (0); if (((tmp)->entry.rbe_parent
)) do {} while (0); } while (0); elm = (head)->rbh_root; break
; } } else { tmp = (parent)->entry.rbe_left; if ((tmp)->
entry.rbe_color == 1) { do { (tmp)->entry.rbe_color = 0; (
parent)->entry.rbe_color = 1; } while (0); do { (tmp) = (parent
)->entry.rbe_left; if (((parent)->entry.rbe_left = (tmp
)->entry.rbe_right)) { ((tmp)->entry.rbe_right)->entry
.rbe_parent = (parent); } do {} while (0); if (((tmp)->entry
.rbe_parent = (parent)->entry.rbe_parent)) { if ((parent) ==
((parent)->entry.rbe_parent)->entry.rbe_left) ((parent
)->entry.rbe_parent)->entry.rbe_left = (tmp); else ((parent
)->entry.rbe_parent)->entry.rbe_right = (tmp); } else (
head)->rbh_root = (tmp); (tmp)->entry.rbe_right = (parent
); (parent)->entry.rbe_parent = (tmp); do {} while (0); if
(((tmp)->entry.rbe_parent)) do {} while (0); } while (0);
tmp = (parent)->entry.rbe_left; } if (((tmp)->entry.rbe_left
== ((void *)0) || ((tmp)->entry.rbe_left)->entry.rbe_color
== 0) && ((tmp)->entry.rbe_right == ((void *)0) ||
((tmp)->entry.rbe_right)->entry.rbe_color == 0)) { (tmp
)->entry.rbe_color = 1; elm = parent; parent = (elm)->entry
.rbe_parent; } else { if ((tmp)->entry.rbe_left == ((void *
)0) || ((tmp)->entry.rbe_left)->entry.rbe_color == 0) {
struct auth *oright; if ((oright = (tmp)->entry.rbe_right
)) (oright)->entry.rbe_color = 0; (tmp)->entry.rbe_color
= 1; do { (oright) = (tmp)->entry.rbe_right; if (((tmp)->
entry.rbe_right = (oright)->entry.rbe_left)) { ((oright)->
entry.rbe_left)->entry.rbe_parent = (tmp); } do {} while (
0); if (((oright)->entry.rbe_parent = (tmp)->entry.rbe_parent
)) { if ((tmp) == ((tmp)->entry.rbe_parent)->entry.rbe_left
) ((tmp)->entry.rbe_parent)->entry.rbe_left = (oright);
else ((tmp)->entry.rbe_parent)->entry.rbe_right = (oright
); } else (head)->rbh_root = (oright); (oright)->entry.
rbe_left = (tmp); (tmp)->entry.rbe_parent = (oright); do {
} while (0); if (((oright)->entry.rbe_parent)) do {} while
(0); } while (0); tmp = (parent)->entry.rbe_left; } (tmp)
->entry.rbe_color = (parent)->entry.rbe_color; (parent)
->entry.rbe_color = 0; if ((tmp)->entry.rbe_left) ((tmp
)->entry.rbe_left)->entry.rbe_color = 0; do { (tmp) = (
parent)->entry.rbe_left; if (((parent)->entry.rbe_left =
(tmp)->entry.rbe_right)) { ((tmp)->entry.rbe_right)->
entry.rbe_parent = (parent); } do {} while (0); if (((tmp)->
entry.rbe_parent = (parent)->entry.rbe_parent)) { if ((parent
) == ((parent)->entry.rbe_parent)->entry.rbe_left) ((parent
)->entry.rbe_parent)->entry.rbe_left = (tmp); else ((parent
)->entry.rbe_parent)->entry.rbe_right = (tmp); } else (
head)->rbh_root = (tmp); (tmp)->entry.rbe_right = (parent
); (parent)->entry.rbe_parent = (tmp); do {} while (0); if
(((tmp)->entry.rbe_parent)) do {} while (0); } while (0);
elm = (head)->rbh_root; break; } } } if (elm) (elm)->entry
.rbe_color = 0; } __attribute__((__unused__)) static struct auth
* auth_tree_RB_REMOVE(struct auth_tree *head, struct auth *elm
) { struct auth *child, *parent, *old = elm; int color; if ((
elm)->entry.rbe_left == ((void *)0)) child = (elm)->entry
.rbe_right; else if ((elm)->entry.rbe_right == ((void *)0)
) child = (elm)->entry.rbe_left; else { struct auth *left;
elm = (elm)->entry.rbe_right; while ((left = (elm)->entry
.rbe_left)) elm = left; child = (elm)->entry.rbe_right; parent
= (elm)->entry.rbe_parent; color = (elm)->entry.rbe_color
; if (child) (child)->entry.rbe_parent = parent; if (parent
) { if ((parent)->entry.rbe_left == elm) (parent)->entry
.rbe_left = child; else (parent)->entry.rbe_right = child;
do {} while (0); } else (head)->rbh_root = child; if ((elm
)->entry.rbe_parent == old) parent = elm; (elm)->entry =
(old)->entry; if ((old)->entry.rbe_parent) { if (((old
)->entry.rbe_parent)->entry.rbe_left == old) ((old)->
entry.rbe_parent)->entry.rbe_left = elm; else ((old)->entry
.rbe_parent)->entry.rbe_right = elm; do {} while (0); } else
(head)->rbh_root = elm; ((old)->entry.rbe_left)->entry
.rbe_parent = elm; if ((old)->entry.rbe_right) ((old)->
entry.rbe_right)->entry.rbe_parent = elm; if (parent) { left
= parent; do { do {} while (0); } while ((left = (left)->
entry.rbe_parent)); } goto color; } parent = (elm)->entry.
rbe_parent; color = (elm)->entry.rbe_color; if (child) (child
)->entry.rbe_parent = parent; if (parent) { if ((parent)->
entry.rbe_left == elm) (parent)->entry.rbe_left = child; else
(parent)->entry.rbe_right = child; do {} while (0); } else
(head)->rbh_root = child; color: if (color == 0) auth_tree_RB_REMOVE_COLOR
(head, parent, child); return (old); } __attribute__((__unused__
)) static struct auth * auth_tree_RB_INSERT(struct auth_tree *
head, struct auth *elm) { struct auth *tmp; struct auth *parent
= ((void *)0); int comp = 0; tmp = (head)->rbh_root; while
(tmp) { parent = tmp; comp = (authcmp)(elm, parent); if (comp
< 0) tmp = (tmp)->entry.rbe_left; else if (comp > 0
) tmp = (tmp)->entry.rbe_right; else return (tmp); } do { (
elm)->entry.rbe_parent = parent; (elm)->entry.rbe_left =
(elm)->entry.rbe_right = ((void *)0); (elm)->entry.rbe_color
= 1; } while (0); if (parent != ((void *)0)) { if (comp <
0) (parent)->entry.rbe_left = elm; else (parent)->entry
.rbe_right = elm; do {} while (0); } else (head)->rbh_root
= elm; auth_tree_RB_INSERT_COLOR(head, elm); return (((void *
)0)); } __attribute__((__unused__)) static struct auth * auth_tree_RB_FIND
(struct auth_tree *head, struct auth *elm) { struct auth *tmp
= (head)->rbh_root; int comp; while (tmp) { comp = authcmp
(elm, tmp); if (comp < 0) tmp = (tmp)->entry.rbe_left; else
if (comp > 0) tmp = (tmp)->entry.rbe_right; else return
(tmp); } return (((void *)0)); } __attribute__((__unused__))
static struct auth * auth_tree_RB_NFIND(struct auth_tree *head
, struct auth *elm) { struct auth *tmp = (head)->rbh_root;
struct auth *res = ((void *)0); int comp; while (tmp) { comp
= authcmp(elm, tmp); if (comp < 0) { res = tmp; tmp = (tmp
)->entry.rbe_left; } else if (comp > 0) tmp = (tmp)->
entry.rbe_right; else return (tmp); } return (res); } __attribute__
((__unused__)) static struct auth * auth_tree_RB_NEXT(struct auth
*elm) { if ((elm)->entry.rbe_right) { elm = (elm)->entry
.rbe_right; while ((elm)->entry.rbe_left) elm = (elm)->
entry.rbe_left; } else { if ((elm)->entry.rbe_parent &&
(elm == ((elm)->entry.rbe_parent)->entry.rbe_left)) elm
= (elm)->entry.rbe_parent; else { while ((elm)->entry.
rbe_parent && (elm == ((elm)->entry.rbe_parent)->
entry.rbe_right)) elm = (elm)->entry.rbe_parent; elm = (elm
)->entry.rbe_parent; } } return (elm); } __attribute__((__unused__
)) static struct auth * auth_tree_RB_PREV(struct auth *elm) {
if ((elm)->entry.rbe_left) { elm = (elm)->entry.rbe_left
; while ((elm)->entry.rbe_right) elm = (elm)->entry.rbe_right
; } else { if ((elm)->entry.rbe_parent && (elm == (
(elm)->entry.rbe_parent)->entry.rbe_right)) elm = (elm)
->entry.rbe_parent; else { while ((elm)->entry.rbe_parent
&& (elm == ((elm)->entry.rbe_parent)->entry.rbe_left
)) elm = (elm)->entry.rbe_parent; elm = (elm)->entry.rbe_parent
; } } return (elm); } __attribute__((__unused__)) static struct
auth * auth_tree_RB_MINMAX(struct auth_tree *head, int val) {
struct auth *tmp = (head)->rbh_root; struct auth *parent =
((void *)0); while (tmp) { parent = tmp; if (val < 0) tmp
= (tmp)->entry.rbe_left; else tmp = (tmp)->entry.rbe_right
; } return (parent); }
;
1190
1191void
1192auth_tree_free(struct auth_tree *auths)
1193{
1194 struct auth *auth, *tauth;
1195
1196 RB_FOREACH_SAFE(auth, auth_tree, auths, tauth)for ((auth) = auth_tree_RB_MINMAX(auths, -1); ((auth) != ((void
*)0)) && ((tauth) = auth_tree_RB_NEXT(auth), 1); (auth
) = (tauth))
{
1197 RB_REMOVE(auth_tree, auths, auth)auth_tree_RB_REMOVE(auths, auth);
1198 cert_free(auth->cert);
1199 free(auth);
1200 }
1201}
1202
1203struct auth *
1204auth_find(struct auth_tree *auths, const char *aki)
1205{
1206 struct auth a;
1207 struct cert c;
1208
1209 /* we look up the cert where the ski == aki */
1210 c.ski = (char *)aki;
1211 a.cert = &c;
1212
1213 return RB_FIND(auth_tree, auths, &a)auth_tree_RB_FIND(auths, &a);
1214}
1215
1216struct auth *
1217auth_insert(struct auth_tree *auths, struct cert *cert, struct auth *parent)
1218{
1219 struct auth *na;
1220
1221 na = malloc(sizeof(*na));
1222 if (na == NULL((void *)0))
1223 err(1, NULL((void *)0));
1224
1225 na->parent = parent;
1226 na->cert = cert;
1227 na->any_inherits = x509_any_inherits(cert->x509);
1228
1229 if (RB_INSERT(auth_tree, auths, na)auth_tree_RB_INSERT(auths, na) != NULL((void *)0))
1230 err(1, "auth tree corrupted");
1231
1232 return na;
1233}
1234
1235static void
1236insert_brk(struct brk_tree *tree, struct cert *cert, int asid)
1237{
1238 struct brk *b, *found;
1239
1240 if ((b = calloc(1, sizeof(*b))) == NULL((void *)0))
1241 err(1, NULL((void *)0));
1242
1243 b->asid = asid;
1244 b->expires = cert->notafter;
1245 b->talid = cert->talid;
1246 if ((b->ski = strdup(cert->ski)) == NULL((void *)0))
1247 err(1, NULL((void *)0));
1248 if ((b->pubkey = strdup(cert->pubkey)) == NULL((void *)0))
1249 err(1, NULL((void *)0));
1250
1251 /*
1252 * Check if a similar BRK already exists in the tree. If the found BRK
1253 * expires sooner, update it to this BRK's later expiry moment.
1254 */
1255 if ((found = RB_INSERT(brk_tree, tree, b)brk_tree_RB_INSERT(tree, b)) != NULL((void *)0)) {
1256 if (found->expires < b->expires) {
1257 found->expires = b->expires;
1258 found->talid = b->talid;
1259 }
1260 free(b->ski);
1261 free(b->pubkey);
1262 free(b);
1263 }
1264}
1265
1266/*
1267 * Add each BGPsec Router Key into the BRK tree.
1268 */
1269void
1270cert_insert_brks(struct brk_tree *tree, struct cert *cert)
1271{
1272 size_t i, asid;
1273
1274 for (i = 0; i < cert->asz; i++) {
1275 switch (cert->as[i].type) {
1276 case CERT_AS_ID:
1277 insert_brk(tree, cert, cert->as[i].id);
1278 break;
1279 case CERT_AS_RANGE:
1280 for (asid = cert->as[i].range.min;
1281 asid <= cert->as[i].range.max; asid++)
1282 insert_brk(tree, cert, asid);
1283 break;
1284 default:
1285 warnx("invalid AS identifier type");
1286 continue;
1287 }
1288 }
1289}
1290
1291static inline int
1292brkcmp(struct brk *a, struct brk *b)
1293{
1294 int rv;
1295
1296 if (a->asid > b->asid)
1297 return 1;
1298 if (a->asid < b->asid)
1299 return -1;
1300
1301 rv = strcmp(a->ski, b->ski);
1302 if (rv > 0)
1303 return 1;
1304 if (rv < 0)
1305 return -1;
1306
1307 return strcmp(a->pubkey, b->pubkey);
1308}
1309
1310RB_GENERATE(brk_tree, brk, entry, brkcmp)void brk_tree_RB_INSERT_COLOR(struct brk_tree *head, struct brk
*elm) { struct brk *parent, *gparent, *tmp; while ((parent =
(elm)->entry.rbe_parent) && (parent)->entry.rbe_color
== 1) { gparent = (parent)->entry.rbe_parent; if (parent ==
(gparent)->entry.rbe_left) { tmp = (gparent)->entry.rbe_right
; if (tmp && (tmp)->entry.rbe_color == 1) { (tmp)->
entry.rbe_color = 0; do { (parent)->entry.rbe_color = 0; (
gparent)->entry.rbe_color = 1; } while (0); elm = gparent;
continue; } if ((parent)->entry.rbe_right == elm) { do { (
tmp) = (parent)->entry.rbe_right; if (((parent)->entry.
rbe_right = (tmp)->entry.rbe_left)) { ((tmp)->entry.rbe_left
)->entry.rbe_parent = (parent); } do {} while (0); if (((tmp
)->entry.rbe_parent = (parent)->entry.rbe_parent)) { if
((parent) == ((parent)->entry.rbe_parent)->entry.rbe_left
) ((parent)->entry.rbe_parent)->entry.rbe_left = (tmp);
else ((parent)->entry.rbe_parent)->entry.rbe_right = (
tmp); } else (head)->rbh_root = (tmp); (tmp)->entry.rbe_left
= (parent); (parent)->entry.rbe_parent = (tmp); do {} while
(0); if (((tmp)->entry.rbe_parent)) do {} while (0); } while
(0); tmp = parent; parent = elm; elm = tmp; } do { (parent)->
entry.rbe_color = 0; (gparent)->entry.rbe_color = 1; } while
(0); do { (tmp) = (gparent)->entry.rbe_left; if (((gparent
)->entry.rbe_left = (tmp)->entry.rbe_right)) { ((tmp)->
entry.rbe_right)->entry.rbe_parent = (gparent); } do {} while
(0); if (((tmp)->entry.rbe_parent = (gparent)->entry.rbe_parent
)) { if ((gparent) == ((gparent)->entry.rbe_parent)->entry
.rbe_left) ((gparent)->entry.rbe_parent)->entry.rbe_left
= (tmp); else ((gparent)->entry.rbe_parent)->entry.rbe_right
= (tmp); } else (head)->rbh_root = (tmp); (tmp)->entry
.rbe_right = (gparent); (gparent)->entry.rbe_parent = (tmp
); do {} while (0); if (((tmp)->entry.rbe_parent)) do {} while
(0); } while (0); } else { tmp = (gparent)->entry.rbe_left
; if (tmp && (tmp)->entry.rbe_color == 1) { (tmp)->
entry.rbe_color = 0; do { (parent)->entry.rbe_color = 0; (
gparent)->entry.rbe_color = 1; } while (0); elm = gparent;
continue; } if ((parent)->entry.rbe_left == elm) { do { (
tmp) = (parent)->entry.rbe_left; if (((parent)->entry.rbe_left
= (tmp)->entry.rbe_right)) { ((tmp)->entry.rbe_right)->
entry.rbe_parent = (parent); } do {} while (0); if (((tmp)->
entry.rbe_parent = (parent)->entry.rbe_parent)) { if ((parent
) == ((parent)->entry.rbe_parent)->entry.rbe_left) ((parent
)->entry.rbe_parent)->entry.rbe_left = (tmp); else ((parent
)->entry.rbe_parent)->entry.rbe_right = (tmp); } else (
head)->rbh_root = (tmp); (tmp)->entry.rbe_right = (parent
); (parent)->entry.rbe_parent = (tmp); do {} while (0); if
(((tmp)->entry.rbe_parent)) do {} while (0); } while (0);
tmp = parent; parent = elm; elm = tmp; } do { (parent)->entry
.rbe_color = 0; (gparent)->entry.rbe_color = 1; } while (0
); do { (tmp) = (gparent)->entry.rbe_right; if (((gparent)
->entry.rbe_right = (tmp)->entry.rbe_left)) { ((tmp)->
entry.rbe_left)->entry.rbe_parent = (gparent); } do {} while
(0); if (((tmp)->entry.rbe_parent = (gparent)->entry.rbe_parent
)) { if ((gparent) == ((gparent)->entry.rbe_parent)->entry
.rbe_left) ((gparent)->entry.rbe_parent)->entry.rbe_left
= (tmp); else ((gparent)->entry.rbe_parent)->entry.rbe_right
= (tmp); } else (head)->rbh_root = (tmp); (tmp)->entry
.rbe_left = (gparent); (gparent)->entry.rbe_parent = (tmp)
; do {} while (0); if (((tmp)->entry.rbe_parent)) do {} while
(0); } while (0); } } (head->rbh_root)->entry.rbe_color
= 0; } void brk_tree_RB_REMOVE_COLOR(struct brk_tree *head, struct
brk *parent, struct brk *elm) { struct brk *tmp; while ((elm
== ((void *)0) || (elm)->entry.rbe_color == 0) &&
elm != (head)->rbh_root) { if ((parent)->entry.rbe_left
== elm) { tmp = (parent)->entry.rbe_right; if ((tmp)->
entry.rbe_color == 1) { do { (tmp)->entry.rbe_color = 0; (
parent)->entry.rbe_color = 1; } while (0); do { (tmp) = (parent
)->entry.rbe_right; if (((parent)->entry.rbe_right = (tmp
)->entry.rbe_left)) { ((tmp)->entry.rbe_left)->entry
.rbe_parent = (parent); } do {} while (0); if (((tmp)->entry
.rbe_parent = (parent)->entry.rbe_parent)) { if ((parent) ==
((parent)->entry.rbe_parent)->entry.rbe_left) ((parent
)->entry.rbe_parent)->entry.rbe_left = (tmp); else ((parent
)->entry.rbe_parent)->entry.rbe_right = (tmp); } else (
head)->rbh_root = (tmp); (tmp)->entry.rbe_left = (parent
); (parent)->entry.rbe_parent = (tmp); do {} while (0); if
(((tmp)->entry.rbe_parent)) do {} while (0); } while (0);
tmp = (parent)->entry.rbe_right; } if (((tmp)->entry.rbe_left
== ((void *)0) || ((tmp)->entry.rbe_left)->entry.rbe_color
== 0) && ((tmp)->entry.rbe_right == ((void *)0) ||
((tmp)->entry.rbe_right)->entry.rbe_color == 0)) { (tmp
)->entry.rbe_color = 1; elm = parent; parent = (elm)->entry
.rbe_parent; } else { if ((tmp)->entry.rbe_right == ((void
*)0) || ((tmp)->entry.rbe_right)->entry.rbe_color == 0
) { struct brk *oleft; if ((oleft = (tmp)->entry.rbe_left)
) (oleft)->entry.rbe_color = 0; (tmp)->entry.rbe_color =
1; do { (oleft) = (tmp)->entry.rbe_left; if (((tmp)->entry
.rbe_left = (oleft)->entry.rbe_right)) { ((oleft)->entry
.rbe_right)->entry.rbe_parent = (tmp); } do {} while (0); if
(((oleft)->entry.rbe_parent = (tmp)->entry.rbe_parent)
) { if ((tmp) == ((tmp)->entry.rbe_parent)->entry.rbe_left
) ((tmp)->entry.rbe_parent)->entry.rbe_left = (oleft); else
((tmp)->entry.rbe_parent)->entry.rbe_right = (oleft); }
else (head)->rbh_root = (oleft); (oleft)->entry.rbe_right
= (tmp); (tmp)->entry.rbe_parent = (oleft); do {} while (
0); if (((oleft)->entry.rbe_parent)) do {} while (0); } while
(0); tmp = (parent)->entry.rbe_right; } (tmp)->entry.rbe_color
= (parent)->entry.rbe_color; (parent)->entry.rbe_color
= 0; if ((tmp)->entry.rbe_right) ((tmp)->entry.rbe_right
)->entry.rbe_color = 0; do { (tmp) = (parent)->entry.rbe_right
; if (((parent)->entry.rbe_right = (tmp)->entry.rbe_left
)) { ((tmp)->entry.rbe_left)->entry.rbe_parent = (parent
); } do {} while (0); if (((tmp)->entry.rbe_parent = (parent
)->entry.rbe_parent)) { if ((parent) == ((parent)->entry
.rbe_parent)->entry.rbe_left) ((parent)->entry.rbe_parent
)->entry.rbe_left = (tmp); else ((parent)->entry.rbe_parent
)->entry.rbe_right = (tmp); } else (head)->rbh_root = (
tmp); (tmp)->entry.rbe_left = (parent); (parent)->entry
.rbe_parent = (tmp); do {} while (0); if (((tmp)->entry.rbe_parent
)) do {} while (0); } while (0); elm = (head)->rbh_root; break
; } } else { tmp = (parent)->entry.rbe_left; if ((tmp)->
entry.rbe_color == 1) { do { (tmp)->entry.rbe_color = 0; (
parent)->entry.rbe_color = 1; } while (0); do { (tmp) = (parent
)->entry.rbe_left; if (((parent)->entry.rbe_left = (tmp
)->entry.rbe_right)) { ((tmp)->entry.rbe_right)->entry
.rbe_parent = (parent); } do {} while (0); if (((tmp)->entry
.rbe_parent = (parent)->entry.rbe_parent)) { if ((parent) ==
((parent)->entry.rbe_parent)->entry.rbe_left) ((parent
)->entry.rbe_parent)->entry.rbe_left = (tmp); else ((parent
)->entry.rbe_parent)->entry.rbe_right = (tmp); } else (
head)->rbh_root = (tmp); (tmp)->entry.rbe_right = (parent
); (parent)->entry.rbe_parent = (tmp); do {} while (0); if
(((tmp)->entry.rbe_parent)) do {} while (0); } while (0);
tmp = (parent)->entry.rbe_left; } if (((tmp)->entry.rbe_left
== ((void *)0) || ((tmp)->entry.rbe_left)->entry.rbe_color
== 0) && ((tmp)->entry.rbe_right == ((void *)0) ||
((tmp)->entry.rbe_right)->entry.rbe_color == 0)) { (tmp
)->entry.rbe_color = 1; elm = parent; parent = (elm)->entry
.rbe_parent; } else { if ((tmp)->entry.rbe_left == ((void *
)0) || ((tmp)->entry.rbe_left)->entry.rbe_color == 0) {
struct brk *oright; if ((oright = (tmp)->entry.rbe_right)
) (oright)->entry.rbe_color = 0; (tmp)->entry.rbe_color
= 1; do { (oright) = (tmp)->entry.rbe_right; if (((tmp)->
entry.rbe_right = (oright)->entry.rbe_left)) { ((oright)->
entry.rbe_left)->entry.rbe_parent = (tmp); } do {} while (
0); if (((oright)->entry.rbe_parent = (tmp)->entry.rbe_parent
)) { if ((tmp) == ((tmp)->entry.rbe_parent)->entry.rbe_left
) ((tmp)->entry.rbe_parent)->entry.rbe_left = (oright);
else ((tmp)->entry.rbe_parent)->entry.rbe_right = (oright
); } else (head)->rbh_root = (oright); (oright)->entry.
rbe_left = (tmp); (tmp)->entry.rbe_parent = (oright); do {
} while (0); if (((oright)->entry.rbe_parent)) do {} while
(0); } while (0); tmp = (parent)->entry.rbe_left; } (tmp)
->entry.rbe_color = (parent)->entry.rbe_color; (parent)
->entry.rbe_color = 0; if ((tmp)->entry.rbe_left) ((tmp
)->entry.rbe_left)->entry.rbe_color = 0; do { (tmp) = (
parent)->entry.rbe_left; if (((parent)->entry.rbe_left =
(tmp)->entry.rbe_right)) { ((tmp)->entry.rbe_right)->
entry.rbe_parent = (parent); } do {} while (0); if (((tmp)->
entry.rbe_parent = (parent)->entry.rbe_parent)) { if ((parent
) == ((parent)->entry.rbe_parent)->entry.rbe_left) ((parent
)->entry.rbe_parent)->entry.rbe_left = (tmp); else ((parent
)->entry.rbe_parent)->entry.rbe_right = (tmp); } else (
head)->rbh_root = (tmp); (tmp)->entry.rbe_right = (parent
); (parent)->entry.rbe_parent = (tmp); do {} while (0); if
(((tmp)->entry.rbe_parent)) do {} while (0); } while (0);
elm = (head)->rbh_root; break; } } } if (elm) (elm)->entry
.rbe_color = 0; } struct brk * brk_tree_RB_REMOVE(struct brk_tree
*head, struct brk *elm) { struct brk *child, *parent, *old =
elm; int color; if ((elm)->entry.rbe_left == ((void *)0))
child = (elm)->entry.rbe_right; else if ((elm)->entry.
rbe_right == ((void *)0)) child = (elm)->entry.rbe_left; else
{ struct brk *left; elm = (elm)->entry.rbe_right; while (
(left = (elm)->entry.rbe_left)) elm = left; child = (elm)->
entry.rbe_right; parent = (elm)->entry.rbe_parent; color =
(elm)->entry.rbe_color; if (child) (child)->entry.rbe_parent
= parent; if (parent) { if ((parent)->entry.rbe_left == elm
) (parent)->entry.rbe_left = child; else (parent)->entry
.rbe_right = child; do {} while (0); } else (head)->rbh_root
= child; if ((elm)->entry.rbe_parent == old) parent = elm
; (elm)->entry = (old)->entry; if ((old)->entry.rbe_parent
) { if (((old)->entry.rbe_parent)->entry.rbe_left == old
) ((old)->entry.rbe_parent)->entry.rbe_left = elm; else
((old)->entry.rbe_parent)->entry.rbe_right = elm; do {
} while (0); } else (head)->rbh_root = elm; ((old)->entry
.rbe_left)->entry.rbe_parent = elm; if ((old)->entry.rbe_right
) ((old)->entry.rbe_right)->entry.rbe_parent = elm; if (
parent) { left = parent; do { do {} while (0); } while ((left
= (left)->entry.rbe_parent)); } goto color; } parent = (elm
)->entry.rbe_parent; color = (elm)->entry.rbe_color; if
(child) (child)->entry.rbe_parent = parent; if (parent) {
if ((parent)->entry.rbe_left == elm) (parent)->entry.rbe_left
= child; else (parent)->entry.rbe_right = child; do {} while
(0); } else (head)->rbh_root = child; color: if (color ==
0) brk_tree_RB_REMOVE_COLOR(head, parent, child); return (old
); } struct brk * brk_tree_RB_INSERT(struct brk_tree *head, struct
brk *elm) { struct brk *tmp; struct brk *parent = ((void *)0
); int comp = 0; tmp = (head)->rbh_root; while (tmp) { parent
= tmp; comp = (brkcmp)(elm, parent); if (comp < 0) tmp = (
tmp)->entry.rbe_left; else if (comp > 0) tmp = (tmp)->
entry.rbe_right; else return (tmp); } do { (elm)->entry.rbe_parent
= parent; (elm)->entry.rbe_left = (elm)->entry.rbe_right
= ((void *)0); (elm)->entry.rbe_color = 1; } while (0); if
(parent != ((void *)0)) { if (comp < 0) (parent)->entry
.rbe_left = elm; else (parent)->entry.rbe_right = elm; do {
} while (0); } else (head)->rbh_root = elm; brk_tree_RB_INSERT_COLOR
(head, elm); return (((void *)0)); } struct brk * brk_tree_RB_FIND
(struct brk_tree *head, struct brk *elm) { struct brk *tmp = (
head)->rbh_root; int comp; while (tmp) { comp = brkcmp(elm
, tmp); if (comp < 0) tmp = (tmp)->entry.rbe_left; else
if (comp > 0) tmp = (tmp)->entry.rbe_right; else return
(tmp); } return (((void *)0)); } struct brk * brk_tree_RB_NFIND
(struct brk_tree *head, struct brk *elm) { struct brk *tmp = (
head)->rbh_root; struct brk *res = ((void *)0); int comp; while
(tmp) { comp = brkcmp(elm, tmp); if (comp < 0) { res = tmp
; tmp = (tmp)->entry.rbe_left; } else if (comp > 0) tmp
= (tmp)->entry.rbe_right; else return (tmp); } return (res
); } struct brk * brk_tree_RB_NEXT(struct brk *elm) { if ((elm
)->entry.rbe_right) { elm = (elm)->entry.rbe_right; while
((elm)->entry.rbe_left) elm = (elm)->entry.rbe_left; }
else { if ((elm)->entry.rbe_parent && (elm == ((elm
)->entry.rbe_parent)->entry.rbe_left)) elm = (elm)->
entry.rbe_parent; else { while ((elm)->entry.rbe_parent &&
(elm == ((elm)->entry.rbe_parent)->entry.rbe_right)) elm
= (elm)->entry.rbe_parent; elm = (elm)->entry.rbe_parent
; } } return (elm); } struct brk * brk_tree_RB_PREV(struct brk
*elm) { if ((elm)->entry.rbe_left) { elm = (elm)->entry
.rbe_left; while ((elm)->entry.rbe_right) elm = (elm)->
entry.rbe_right; } else { if ((elm)->entry.rbe_parent &&
(elm == ((elm)->entry.rbe_parent)->entry.rbe_right)) elm
= (elm)->entry.rbe_parent; else { while ((elm)->entry.
rbe_parent && (elm == ((elm)->entry.rbe_parent)->
entry.rbe_left)) elm = (elm)->entry.rbe_parent; elm = (elm
)->entry.rbe_parent; } } return (elm); } struct brk * brk_tree_RB_MINMAX
(struct brk_tree *head, int val) { struct brk *tmp = (head)->
rbh_root; struct brk *parent = ((void *)0); while (tmp) { parent
= tmp; if (val < 0) tmp = (tmp)->entry.rbe_left; else tmp
= (tmp)->entry.rbe_right; } return (parent); }
;