]>
Commit | Line | Data |
---|---|---|
96ea4ae9 | 1 | /* |
454afd98 | 2 | * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved. |
96ea4ae9 | 3 | * |
4286ca47 | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
d2e9e320 RS |
5 | * this file except in compliance with the License. You can obtain a copy |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
96ea4ae9 BL |
8 | */ |
9 | ||
10 | /* | |
11 | * Implementation of RFC 3779 section 2.2. | |
12 | */ | |
13 | ||
14 | #include <stdio.h> | |
15 | #include <stdlib.h> | |
a0b76569 | 16 | |
b39fc560 | 17 | #include "internal/cryptlib.h" |
96ea4ae9 BL |
18 | #include <openssl/conf.h> |
19 | #include <openssl/asn1.h> | |
20 | #include <openssl/asn1t.h> | |
ea46f5e0 | 21 | #include <openssl/buffer.h> |
96ea4ae9 | 22 | #include <openssl/x509v3.h> |
25f2138b | 23 | #include "crypto/x509.h" |
df2ee0e2 | 24 | #include "ext_dat.h" |
c90c4693 | 25 | #include "x509_local.h" |
96ea4ae9 | 26 | |
47bbaa5b | 27 | #ifndef OPENSSL_NO_RFC3779 |
96ea4ae9 BL |
28 | |
29 | /* | |
30 | * OpenSSL ASN.1 template translation of RFC 3779 2.2.3. | |
31 | */ | |
32 | ||
33 | ASN1_SEQUENCE(IPAddressRange) = { | |
34 | ASN1_SIMPLE(IPAddressRange, min, ASN1_BIT_STRING), | |
35 | ASN1_SIMPLE(IPAddressRange, max, ASN1_BIT_STRING) | |
36 | } ASN1_SEQUENCE_END(IPAddressRange) | |
37 | ||
38 | ASN1_CHOICE(IPAddressOrRange) = { | |
39 | ASN1_SIMPLE(IPAddressOrRange, u.addressPrefix, ASN1_BIT_STRING), | |
40 | ASN1_SIMPLE(IPAddressOrRange, u.addressRange, IPAddressRange) | |
41 | } ASN1_CHOICE_END(IPAddressOrRange) | |
42 | ||
43 | ASN1_CHOICE(IPAddressChoice) = { | |
44 | ASN1_SIMPLE(IPAddressChoice, u.inherit, ASN1_NULL), | |
45 | ASN1_SEQUENCE_OF(IPAddressChoice, u.addressesOrRanges, IPAddressOrRange) | |
46 | } ASN1_CHOICE_END(IPAddressChoice) | |
47 | ||
48 | ASN1_SEQUENCE(IPAddressFamily) = { | |
49 | ASN1_SIMPLE(IPAddressFamily, addressFamily, ASN1_OCTET_STRING), | |
50 | ASN1_SIMPLE(IPAddressFamily, ipAddressChoice, IPAddressChoice) | |
51 | } ASN1_SEQUENCE_END(IPAddressFamily) | |
52 | ||
0f113f3e | 53 | ASN1_ITEM_TEMPLATE(IPAddrBlocks) = |
96ea4ae9 | 54 | ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, |
0f113f3e | 55 | IPAddrBlocks, IPAddressFamily) |
df2ee0e2 | 56 | static_ASN1_ITEM_TEMPLATE_END(IPAddrBlocks) |
96ea4ae9 BL |
57 | |
58 | IMPLEMENT_ASN1_FUNCTIONS(IPAddressRange) | |
59 | IMPLEMENT_ASN1_FUNCTIONS(IPAddressOrRange) | |
60 | IMPLEMENT_ASN1_FUNCTIONS(IPAddressChoice) | |
61 | IMPLEMENT_ASN1_FUNCTIONS(IPAddressFamily) | |
62 | ||
63 | /* | |
64 | * How much buffer space do we need for a raw address? | |
65 | */ | |
c73ad690 | 66 | #define ADDR_RAW_BUF_LEN 16 |
96ea4ae9 BL |
67 | |
68 | /* | |
69 | * What's the address length associated with this AFI? | |
70 | */ | |
71 | static int length_from_afi(const unsigned afi) | |
72 | { | |
0f113f3e MC |
73 | switch (afi) { |
74 | case IANA_AFI_IPV4: | |
75 | return 4; | |
76 | case IANA_AFI_IPV6: | |
77 | return 16; | |
78 | default: | |
79 | return 0; | |
80 | } | |
96ea4ae9 BL |
81 | } |
82 | ||
83 | /* | |
84 | * Extract the AFI from an IPAddressFamily. | |
85 | */ | |
9021a5df | 86 | unsigned int X509v3_addr_get_afi(const IPAddressFamily *f) |
96ea4ae9 | 87 | { |
b2317174 RS |
88 | if (f == NULL |
89 | || f->addressFamily == NULL | |
90 | || f->addressFamily->data == NULL | |
91 | || f->addressFamily->length < 2) | |
92 | return 0; | |
93 | return (f->addressFamily->data[0] << 8) | f->addressFamily->data[1]; | |
96ea4ae9 BL |
94 | } |
95 | ||
96 | /* | |
97 | * Expand the bitstring form of an address into a raw byte array. | |
98 | * At the moment this is coded for simplicity, not speed. | |
99 | */ | |
be71c372 | 100 | static int addr_expand(unsigned char *addr, |
0f113f3e MC |
101 | const ASN1_BIT_STRING *bs, |
102 | const int length, const unsigned char fill) | |
96ea4ae9 | 103 | { |
0f113f3e MC |
104 | if (bs->length < 0 || bs->length > length) |
105 | return 0; | |
106 | if (bs->length > 0) { | |
107 | memcpy(addr, bs->data, bs->length); | |
108 | if ((bs->flags & 7) != 0) { | |
109 | unsigned char mask = 0xFF >> (8 - (bs->flags & 7)); | |
110 | if (fill == 0) | |
111 | addr[bs->length - 1] &= ~mask; | |
112 | else | |
113 | addr[bs->length - 1] |= mask; | |
114 | } | |
96ea4ae9 | 115 | } |
0f113f3e MC |
116 | memset(addr + bs->length, fill, length - bs->length); |
117 | return 1; | |
96ea4ae9 BL |
118 | } |
119 | ||
120 | /* | |
121 | * Extract the prefix length from a bitstring. | |
122 | */ | |
c73ad690 | 123 | #define addr_prefixlen(bs) ((int) ((bs)->length * 8 - ((bs)->flags & 7))) |
96ea4ae9 BL |
124 | |
125 | /* | |
126 | * i2r handler for one address bitstring. | |
127 | */ | |
128 | static int i2r_address(BIO *out, | |
0f113f3e MC |
129 | const unsigned afi, |
130 | const unsigned char fill, const ASN1_BIT_STRING *bs) | |
96ea4ae9 | 131 | { |
0f113f3e MC |
132 | unsigned char addr[ADDR_RAW_BUF_LEN]; |
133 | int i, n; | |
96ea4ae9 | 134 | |
0f113f3e MC |
135 | if (bs->length < 0) |
136 | return 0; | |
137 | switch (afi) { | |
138 | case IANA_AFI_IPV4: | |
139 | if (!addr_expand(addr, bs, 4, fill)) | |
140 | return 0; | |
141 | BIO_printf(out, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); | |
142 | break; | |
278260bf | 143 | /* TODO possibly combine with ipaddr_to_asc() */ |
0f113f3e MC |
144 | case IANA_AFI_IPV6: |
145 | if (!addr_expand(addr, bs, 16, fill)) | |
146 | return 0; | |
147 | for (n = 16; n > 1 && addr[n - 1] == 0x00 && addr[n - 2] == 0x00; | |
148 | n -= 2) ; | |
149 | for (i = 0; i < n; i += 2) | |
150 | BIO_printf(out, "%x%s", (addr[i] << 8) | addr[i + 1], | |
151 | (i < 14 ? ":" : "")); | |
152 | if (i < 16) | |
153 | BIO_puts(out, ":"); | |
154 | if (i == 0) | |
155 | BIO_puts(out, ":"); | |
156 | break; | |
157 | default: | |
158 | for (i = 0; i < bs->length; i++) | |
159 | BIO_printf(out, "%s%02x", (i > 0 ? ":" : ""), bs->data[i]); | |
160 | BIO_printf(out, "[%d]", (int)(bs->flags & 7)); | |
161 | break; | |
162 | } | |
163 | return 1; | |
96ea4ae9 BL |
164 | } |
165 | ||
166 | /* | |
167 | * i2r handler for a sequence of addresses and ranges. | |
168 | */ | |
169 | static int i2r_IPAddressOrRanges(BIO *out, | |
0f113f3e MC |
170 | const int indent, |
171 | const IPAddressOrRanges *aors, | |
172 | const unsigned afi) | |
96ea4ae9 | 173 | { |
0f113f3e MC |
174 | int i; |
175 | for (i = 0; i < sk_IPAddressOrRange_num(aors); i++) { | |
176 | const IPAddressOrRange *aor = sk_IPAddressOrRange_value(aors, i); | |
177 | BIO_printf(out, "%*s", indent, ""); | |
178 | switch (aor->type) { | |
179 | case IPAddressOrRange_addressPrefix: | |
180 | if (!i2r_address(out, afi, 0x00, aor->u.addressPrefix)) | |
181 | return 0; | |
182 | BIO_printf(out, "/%d\n", addr_prefixlen(aor->u.addressPrefix)); | |
183 | continue; | |
184 | case IPAddressOrRange_addressRange: | |
185 | if (!i2r_address(out, afi, 0x00, aor->u.addressRange->min)) | |
186 | return 0; | |
187 | BIO_puts(out, "-"); | |
188 | if (!i2r_address(out, afi, 0xFF, aor->u.addressRange->max)) | |
189 | return 0; | |
190 | BIO_puts(out, "\n"); | |
191 | continue; | |
192 | } | |
96ea4ae9 | 193 | } |
0f113f3e | 194 | return 1; |
96ea4ae9 BL |
195 | } |
196 | ||
197 | /* | |
198 | * i2r handler for an IPAddrBlocks extension. | |
199 | */ | |
2e6a7b3e | 200 | static int i2r_IPAddrBlocks(const X509V3_EXT_METHOD *method, |
0f113f3e | 201 | void *ext, BIO *out, int indent) |
96ea4ae9 | 202 | { |
0f113f3e MC |
203 | const IPAddrBlocks *addr = ext; |
204 | int i; | |
205 | for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { | |
206 | IPAddressFamily *f = sk_IPAddressFamily_value(addr, i); | |
9021a5df | 207 | const unsigned int afi = X509v3_addr_get_afi(f); |
0f113f3e MC |
208 | switch (afi) { |
209 | case IANA_AFI_IPV4: | |
210 | BIO_printf(out, "%*sIPv4", indent, ""); | |
211 | break; | |
212 | case IANA_AFI_IPV6: | |
213 | BIO_printf(out, "%*sIPv6", indent, ""); | |
214 | break; | |
215 | default: | |
216 | BIO_printf(out, "%*sUnknown AFI %u", indent, "", afi); | |
217 | break; | |
218 | } | |
219 | if (f->addressFamily->length > 2) { | |
220 | switch (f->addressFamily->data[2]) { | |
221 | case 1: | |
222 | BIO_puts(out, " (Unicast)"); | |
223 | break; | |
224 | case 2: | |
225 | BIO_puts(out, " (Multicast)"); | |
226 | break; | |
227 | case 3: | |
228 | BIO_puts(out, " (Unicast/Multicast)"); | |
229 | break; | |
230 | case 4: | |
231 | BIO_puts(out, " (MPLS)"); | |
232 | break; | |
233 | case 64: | |
234 | BIO_puts(out, " (Tunnel)"); | |
235 | break; | |
236 | case 65: | |
237 | BIO_puts(out, " (VPLS)"); | |
238 | break; | |
239 | case 66: | |
240 | BIO_puts(out, " (BGP MDT)"); | |
241 | break; | |
242 | case 128: | |
243 | BIO_puts(out, " (MPLS-labeled VPN)"); | |
244 | break; | |
245 | default: | |
246 | BIO_printf(out, " (Unknown SAFI %u)", | |
247 | (unsigned)f->addressFamily->data[2]); | |
248 | break; | |
249 | } | |
250 | } | |
251 | switch (f->ipAddressChoice->type) { | |
252 | case IPAddressChoice_inherit: | |
253 | BIO_puts(out, ": inherit\n"); | |
254 | break; | |
255 | case IPAddressChoice_addressesOrRanges: | |
256 | BIO_puts(out, ":\n"); | |
257 | if (!i2r_IPAddressOrRanges(out, | |
258 | indent + 2, | |
259 | f->ipAddressChoice-> | |
260 | u.addressesOrRanges, afi)) | |
261 | return 0; | |
262 | break; | |
263 | } | |
96ea4ae9 | 264 | } |
0f113f3e | 265 | return 1; |
96ea4ae9 BL |
266 | } |
267 | ||
268 | /* | |
269 | * Sort comparison function for a sequence of IPAddressOrRange | |
270 | * elements. | |
be71c372 DSH |
271 | * |
272 | * There's no sane answer we can give if addr_expand() fails, and an | |
273 | * assertion failure on externally supplied data is seriously uncool, | |
274 | * so we just arbitrarily declare that if given invalid inputs this | |
275 | * function returns -1. If this messes up your preferred sort order | |
276 | * for garbage input, tough noogies. | |
96ea4ae9 BL |
277 | */ |
278 | static int IPAddressOrRange_cmp(const IPAddressOrRange *a, | |
0f113f3e | 279 | const IPAddressOrRange *b, const int length) |
96ea4ae9 | 280 | { |
0f113f3e MC |
281 | unsigned char addr_a[ADDR_RAW_BUF_LEN], addr_b[ADDR_RAW_BUF_LEN]; |
282 | int prefixlen_a = 0, prefixlen_b = 0; | |
283 | int r; | |
284 | ||
285 | switch (a->type) { | |
286 | case IPAddressOrRange_addressPrefix: | |
287 | if (!addr_expand(addr_a, a->u.addressPrefix, length, 0x00)) | |
288 | return -1; | |
289 | prefixlen_a = addr_prefixlen(a->u.addressPrefix); | |
290 | break; | |
291 | case IPAddressOrRange_addressRange: | |
292 | if (!addr_expand(addr_a, a->u.addressRange->min, length, 0x00)) | |
293 | return -1; | |
294 | prefixlen_a = length * 8; | |
295 | break; | |
296 | } | |
297 | ||
298 | switch (b->type) { | |
299 | case IPAddressOrRange_addressPrefix: | |
300 | if (!addr_expand(addr_b, b->u.addressPrefix, length, 0x00)) | |
301 | return -1; | |
302 | prefixlen_b = addr_prefixlen(b->u.addressPrefix); | |
303 | break; | |
304 | case IPAddressOrRange_addressRange: | |
305 | if (!addr_expand(addr_b, b->u.addressRange->min, length, 0x00)) | |
306 | return -1; | |
307 | prefixlen_b = length * 8; | |
308 | break; | |
309 | } | |
310 | ||
311 | if ((r = memcmp(addr_a, addr_b, length)) != 0) | |
312 | return r; | |
313 | else | |
314 | return prefixlen_a - prefixlen_b; | |
96ea4ae9 BL |
315 | } |
316 | ||
317 | /* | |
318 | * IPv4-specific closure over IPAddressOrRange_cmp, since sk_sort() | |
0d4fb843 | 319 | * comparison routines are only allowed two arguments. |
96ea4ae9 | 320 | */ |
0f113f3e MC |
321 | static int v4IPAddressOrRange_cmp(const IPAddressOrRange *const *a, |
322 | const IPAddressOrRange *const *b) | |
96ea4ae9 | 323 | { |
0f113f3e | 324 | return IPAddressOrRange_cmp(*a, *b, 4); |
96ea4ae9 BL |
325 | } |
326 | ||
327 | /* | |
328 | * IPv6-specific closure over IPAddressOrRange_cmp, since sk_sort() | |
0d4fb843 | 329 | * comparison routines are only allowed two arguments. |
96ea4ae9 | 330 | */ |
0f113f3e MC |
331 | static int v6IPAddressOrRange_cmp(const IPAddressOrRange *const *a, |
332 | const IPAddressOrRange *const *b) | |
96ea4ae9 | 333 | { |
0f113f3e | 334 | return IPAddressOrRange_cmp(*a, *b, 16); |
96ea4ae9 BL |
335 | } |
336 | ||
337 | /* | |
338 | * Calculate whether a range collapses to a prefix. | |
339 | * See last paragraph of RFC 3779 2.2.3.7. | |
340 | */ | |
341 | static int range_should_be_prefix(const unsigned char *min, | |
0f113f3e | 342 | const unsigned char *max, const int length) |
96ea4ae9 | 343 | { |
0f113f3e MC |
344 | unsigned char mask; |
345 | int i, j; | |
346 | ||
42d7d7dd MC |
347 | if (memcmp(min, max, length) <= 0) |
348 | return -1; | |
0f113f3e MC |
349 | for (i = 0; i < length && min[i] == max[i]; i++) ; |
350 | for (j = length - 1; j >= 0 && min[j] == 0x00 && max[j] == 0xFF; j--) ; | |
351 | if (i < j) | |
352 | return -1; | |
353 | if (i > j) | |
354 | return i * 8; | |
355 | mask = min[i] ^ max[i]; | |
356 | switch (mask) { | |
357 | case 0x01: | |
358 | j = 7; | |
359 | break; | |
360 | case 0x03: | |
361 | j = 6; | |
362 | break; | |
363 | case 0x07: | |
364 | j = 5; | |
365 | break; | |
366 | case 0x0F: | |
367 | j = 4; | |
368 | break; | |
369 | case 0x1F: | |
370 | j = 3; | |
371 | break; | |
372 | case 0x3F: | |
373 | j = 2; | |
374 | break; | |
375 | case 0x7F: | |
376 | j = 1; | |
377 | break; | |
378 | default: | |
379 | return -1; | |
380 | } | |
381 | if ((min[i] & mask) != 0 || (max[i] & mask) != mask) | |
382 | return -1; | |
383 | else | |
384 | return i * 8 + j; | |
96ea4ae9 BL |
385 | } |
386 | ||
387 | /* | |
388 | * Construct a prefix. | |
389 | */ | |
390 | static int make_addressPrefix(IPAddressOrRange **result, | |
0f113f3e | 391 | unsigned char *addr, const int prefixlen) |
96ea4ae9 | 392 | { |
0f113f3e MC |
393 | int bytelen = (prefixlen + 7) / 8, bitlen = prefixlen % 8; |
394 | IPAddressOrRange *aor = IPAddressOrRange_new(); | |
395 | ||
396 | if (aor == NULL) | |
397 | return 0; | |
398 | aor->type = IPAddressOrRange_addressPrefix; | |
399 | if (aor->u.addressPrefix == NULL && | |
400 | (aor->u.addressPrefix = ASN1_BIT_STRING_new()) == NULL) | |
401 | goto err; | |
402 | if (!ASN1_BIT_STRING_set(aor->u.addressPrefix, addr, bytelen)) | |
403 | goto err; | |
404 | aor->u.addressPrefix->flags &= ~7; | |
405 | aor->u.addressPrefix->flags |= ASN1_STRING_FLAG_BITS_LEFT; | |
406 | if (bitlen > 0) { | |
407 | aor->u.addressPrefix->data[bytelen - 1] &= ~(0xFF >> bitlen); | |
408 | aor->u.addressPrefix->flags |= 8 - bitlen; | |
409 | } | |
96ea4ae9 | 410 | |
0f113f3e MC |
411 | *result = aor; |
412 | return 1; | |
96ea4ae9 BL |
413 | |
414 | err: | |
0f113f3e MC |
415 | IPAddressOrRange_free(aor); |
416 | return 0; | |
96ea4ae9 BL |
417 | } |
418 | ||
419 | /* | |
420 | * Construct a range. If it can be expressed as a prefix, | |
421 | * return a prefix instead. Doing this here simplifies | |
422 | * the rest of the code considerably. | |
423 | */ | |
424 | static int make_addressRange(IPAddressOrRange **result, | |
0f113f3e MC |
425 | unsigned char *min, |
426 | unsigned char *max, const int length) | |
96ea4ae9 | 427 | { |
0f113f3e MC |
428 | IPAddressOrRange *aor; |
429 | int i, prefixlen; | |
430 | ||
431 | if ((prefixlen = range_should_be_prefix(min, max, length)) >= 0) | |
432 | return make_addressPrefix(result, min, prefixlen); | |
433 | ||
434 | if ((aor = IPAddressOrRange_new()) == NULL) | |
435 | return 0; | |
436 | aor->type = IPAddressOrRange_addressRange; | |
0f113f3e MC |
437 | if ((aor->u.addressRange = IPAddressRange_new()) == NULL) |
438 | goto err; | |
439 | if (aor->u.addressRange->min == NULL && | |
440 | (aor->u.addressRange->min = ASN1_BIT_STRING_new()) == NULL) | |
441 | goto err; | |
442 | if (aor->u.addressRange->max == NULL && | |
443 | (aor->u.addressRange->max = ASN1_BIT_STRING_new()) == NULL) | |
444 | goto err; | |
445 | ||
446 | for (i = length; i > 0 && min[i - 1] == 0x00; --i) ; | |
447 | if (!ASN1_BIT_STRING_set(aor->u.addressRange->min, min, i)) | |
448 | goto err; | |
449 | aor->u.addressRange->min->flags &= ~7; | |
450 | aor->u.addressRange->min->flags |= ASN1_STRING_FLAG_BITS_LEFT; | |
451 | if (i > 0) { | |
452 | unsigned char b = min[i - 1]; | |
453 | int j = 1; | |
454 | while ((b & (0xFFU >> j)) != 0) | |
455 | ++j; | |
456 | aor->u.addressRange->min->flags |= 8 - j; | |
457 | } | |
96ea4ae9 | 458 | |
0f113f3e MC |
459 | for (i = length; i > 0 && max[i - 1] == 0xFF; --i) ; |
460 | if (!ASN1_BIT_STRING_set(aor->u.addressRange->max, max, i)) | |
461 | goto err; | |
462 | aor->u.addressRange->max->flags &= ~7; | |
463 | aor->u.addressRange->max->flags |= ASN1_STRING_FLAG_BITS_LEFT; | |
464 | if (i > 0) { | |
465 | unsigned char b = max[i - 1]; | |
466 | int j = 1; | |
467 | while ((b & (0xFFU >> j)) != (0xFFU >> j)) | |
468 | ++j; | |
469 | aor->u.addressRange->max->flags |= 8 - j; | |
470 | } | |
96ea4ae9 | 471 | |
0f113f3e MC |
472 | *result = aor; |
473 | return 1; | |
96ea4ae9 BL |
474 | |
475 | err: | |
0f113f3e MC |
476 | IPAddressOrRange_free(aor); |
477 | return 0; | |
96ea4ae9 BL |
478 | } |
479 | ||
480 | /* | |
481 | * Construct a new address family or find an existing one. | |
482 | */ | |
483 | static IPAddressFamily *make_IPAddressFamily(IPAddrBlocks *addr, | |
0f113f3e MC |
484 | const unsigned afi, |
485 | const unsigned *safi) | |
96ea4ae9 | 486 | { |
0f113f3e MC |
487 | IPAddressFamily *f; |
488 | unsigned char key[3]; | |
537bf438 | 489 | int keylen; |
0f113f3e MC |
490 | int i; |
491 | ||
492 | key[0] = (afi >> 8) & 0xFF; | |
493 | key[1] = afi & 0xFF; | |
494 | if (safi != NULL) { | |
495 | key[2] = *safi & 0xFF; | |
496 | keylen = 3; | |
497 | } else { | |
498 | keylen = 2; | |
499 | } | |
500 | ||
501 | for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { | |
502 | f = sk_IPAddressFamily_value(addr, i); | |
0f113f3e MC |
503 | if (f->addressFamily->length == keylen && |
504 | !memcmp(f->addressFamily->data, key, keylen)) | |
505 | return f; | |
506 | } | |
507 | ||
508 | if ((f = IPAddressFamily_new()) == NULL) | |
509 | goto err; | |
510 | if (f->ipAddressChoice == NULL && | |
511 | (f->ipAddressChoice = IPAddressChoice_new()) == NULL) | |
512 | goto err; | |
513 | if (f->addressFamily == NULL && | |
514 | (f->addressFamily = ASN1_OCTET_STRING_new()) == NULL) | |
515 | goto err; | |
516 | if (!ASN1_OCTET_STRING_set(f->addressFamily, key, keylen)) | |
517 | goto err; | |
518 | if (!sk_IPAddressFamily_push(addr, f)) | |
519 | goto err; | |
520 | ||
521 | return f; | |
96ea4ae9 BL |
522 | |
523 | err: | |
0f113f3e MC |
524 | IPAddressFamily_free(f); |
525 | return NULL; | |
96ea4ae9 BL |
526 | } |
527 | ||
528 | /* | |
529 | * Add an inheritance element. | |
530 | */ | |
9021a5df RS |
531 | int X509v3_addr_add_inherit(IPAddrBlocks *addr, |
532 | const unsigned afi, const unsigned *safi) | |
96ea4ae9 | 533 | { |
0f113f3e MC |
534 | IPAddressFamily *f = make_IPAddressFamily(addr, afi, safi); |
535 | if (f == NULL || | |
536 | f->ipAddressChoice == NULL || | |
537 | (f->ipAddressChoice->type == IPAddressChoice_addressesOrRanges && | |
538 | f->ipAddressChoice->u.addressesOrRanges != NULL)) | |
539 | return 0; | |
540 | if (f->ipAddressChoice->type == IPAddressChoice_inherit && | |
541 | f->ipAddressChoice->u.inherit != NULL) | |
542 | return 1; | |
543 | if (f->ipAddressChoice->u.inherit == NULL && | |
544 | (f->ipAddressChoice->u.inherit = ASN1_NULL_new()) == NULL) | |
545 | return 0; | |
546 | f->ipAddressChoice->type = IPAddressChoice_inherit; | |
96ea4ae9 | 547 | return 1; |
96ea4ae9 BL |
548 | } |
549 | ||
550 | /* | |
551 | * Construct an IPAddressOrRange sequence, or return an existing one. | |
552 | */ | |
553 | static IPAddressOrRanges *make_prefix_or_range(IPAddrBlocks *addr, | |
0f113f3e MC |
554 | const unsigned afi, |
555 | const unsigned *safi) | |
96ea4ae9 | 556 | { |
0f113f3e MC |
557 | IPAddressFamily *f = make_IPAddressFamily(addr, afi, safi); |
558 | IPAddressOrRanges *aors = NULL; | |
559 | ||
560 | if (f == NULL || | |
561 | f->ipAddressChoice == NULL || | |
562 | (f->ipAddressChoice->type == IPAddressChoice_inherit && | |
563 | f->ipAddressChoice->u.inherit != NULL)) | |
564 | return NULL; | |
565 | if (f->ipAddressChoice->type == IPAddressChoice_addressesOrRanges) | |
566 | aors = f->ipAddressChoice->u.addressesOrRanges; | |
567 | if (aors != NULL) | |
568 | return aors; | |
569 | if ((aors = sk_IPAddressOrRange_new_null()) == NULL) | |
570 | return NULL; | |
571 | switch (afi) { | |
572 | case IANA_AFI_IPV4: | |
573 | (void)sk_IPAddressOrRange_set_cmp_func(aors, v4IPAddressOrRange_cmp); | |
574 | break; | |
575 | case IANA_AFI_IPV6: | |
576 | (void)sk_IPAddressOrRange_set_cmp_func(aors, v6IPAddressOrRange_cmp); | |
577 | break; | |
578 | } | |
579 | f->ipAddressChoice->type = IPAddressChoice_addressesOrRanges; | |
580 | f->ipAddressChoice->u.addressesOrRanges = aors; | |
96ea4ae9 | 581 | return aors; |
96ea4ae9 BL |
582 | } |
583 | ||
584 | /* | |
585 | * Add a prefix. | |
586 | */ | |
9021a5df RS |
587 | int X509v3_addr_add_prefix(IPAddrBlocks *addr, |
588 | const unsigned afi, | |
589 | const unsigned *safi, | |
590 | unsigned char *a, const int prefixlen) | |
96ea4ae9 | 591 | { |
0f113f3e MC |
592 | IPAddressOrRanges *aors = make_prefix_or_range(addr, afi, safi); |
593 | IPAddressOrRange *aor; | |
594 | if (aors == NULL || !make_addressPrefix(&aor, a, prefixlen)) | |
595 | return 0; | |
596 | if (sk_IPAddressOrRange_push(aors, aor)) | |
597 | return 1; | |
598 | IPAddressOrRange_free(aor); | |
96ea4ae9 | 599 | return 0; |
96ea4ae9 BL |
600 | } |
601 | ||
602 | /* | |
603 | * Add a range. | |
604 | */ | |
9021a5df RS |
605 | int X509v3_addr_add_range(IPAddrBlocks *addr, |
606 | const unsigned afi, | |
607 | const unsigned *safi, | |
608 | unsigned char *min, unsigned char *max) | |
96ea4ae9 | 609 | { |
0f113f3e MC |
610 | IPAddressOrRanges *aors = make_prefix_or_range(addr, afi, safi); |
611 | IPAddressOrRange *aor; | |
612 | int length = length_from_afi(afi); | |
613 | if (aors == NULL) | |
614 | return 0; | |
615 | if (!make_addressRange(&aor, min, max, length)) | |
616 | return 0; | |
617 | if (sk_IPAddressOrRange_push(aors, aor)) | |
618 | return 1; | |
619 | IPAddressOrRange_free(aor); | |
96ea4ae9 | 620 | return 0; |
96ea4ae9 BL |
621 | } |
622 | ||
623 | /* | |
624 | * Extract min and max values from an IPAddressOrRange. | |
625 | */ | |
be71c372 | 626 | static int extract_min_max(IPAddressOrRange *aor, |
0f113f3e | 627 | unsigned char *min, unsigned char *max, int length) |
96ea4ae9 | 628 | { |
0f113f3e MC |
629 | if (aor == NULL || min == NULL || max == NULL) |
630 | return 0; | |
631 | switch (aor->type) { | |
632 | case IPAddressOrRange_addressPrefix: | |
633 | return (addr_expand(min, aor->u.addressPrefix, length, 0x00) && | |
634 | addr_expand(max, aor->u.addressPrefix, length, 0xFF)); | |
635 | case IPAddressOrRange_addressRange: | |
636 | return (addr_expand(min, aor->u.addressRange->min, length, 0x00) && | |
637 | addr_expand(max, aor->u.addressRange->max, length, 0xFF)); | |
638 | } | |
be71c372 | 639 | return 0; |
96ea4ae9 BL |
640 | } |
641 | ||
642 | /* | |
643 | * Public wrapper for extract_min_max(). | |
644 | */ | |
9021a5df RS |
645 | int X509v3_addr_get_range(IPAddressOrRange *aor, |
646 | const unsigned afi, | |
647 | unsigned char *min, | |
648 | unsigned char *max, const int length) | |
96ea4ae9 | 649 | { |
0f113f3e MC |
650 | int afi_length = length_from_afi(afi); |
651 | if (aor == NULL || min == NULL || max == NULL || | |
652 | afi_length == 0 || length < afi_length || | |
653 | (aor->type != IPAddressOrRange_addressPrefix && | |
654 | aor->type != IPAddressOrRange_addressRange) || | |
655 | !extract_min_max(aor, min, max, afi_length)) | |
656 | return 0; | |
657 | ||
658 | return afi_length; | |
96ea4ae9 BL |
659 | } |
660 | ||
661 | /* | |
0d4fb843 | 662 | * Sort comparison function for a sequence of IPAddressFamily. |
96ea4ae9 BL |
663 | * |
664 | * The last paragraph of RFC 3779 2.2.3.3 is slightly ambiguous about | |
665 | * the ordering: I can read it as meaning that IPv6 without a SAFI | |
666 | * comes before IPv4 with a SAFI, which seems pretty weird. The | |
667 | * examples in appendix B suggest that the author intended the | |
668 | * null-SAFI rule to apply only within a single AFI, which is what I | |
669 | * would have expected and is what the following code implements. | |
670 | */ | |
0f113f3e MC |
671 | static int IPAddressFamily_cmp(const IPAddressFamily *const *a_, |
672 | const IPAddressFamily *const *b_) | |
96ea4ae9 | 673 | { |
0f113f3e MC |
674 | const ASN1_OCTET_STRING *a = (*a_)->addressFamily; |
675 | const ASN1_OCTET_STRING *b = (*b_)->addressFamily; | |
676 | int len = ((a->length <= b->length) ? a->length : b->length); | |
677 | int cmp = memcmp(a->data, b->data, len); | |
678 | return cmp ? cmp : a->length - b->length; | |
96ea4ae9 BL |
679 | } |
680 | ||
681 | /* | |
682 | * Check whether an IPAddrBLocks is in canonical form. | |
683 | */ | |
9021a5df | 684 | int X509v3_addr_is_canonical(IPAddrBlocks *addr) |
96ea4ae9 | 685 | { |
0f113f3e MC |
686 | unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; |
687 | unsigned char b_min[ADDR_RAW_BUF_LEN], b_max[ADDR_RAW_BUF_LEN]; | |
688 | IPAddressOrRanges *aors; | |
689 | int i, j, k; | |
96ea4ae9 BL |
690 | |
691 | /* | |
9d22666e | 692 | * Empty extension is canonical. |
96ea4ae9 | 693 | */ |
0f113f3e MC |
694 | if (addr == NULL) |
695 | return 1; | |
96ea4ae9 BL |
696 | |
697 | /* | |
0f113f3e | 698 | * Check whether the top-level list is in order. |
96ea4ae9 | 699 | */ |
0f113f3e MC |
700 | for (i = 0; i < sk_IPAddressFamily_num(addr) - 1; i++) { |
701 | const IPAddressFamily *a = sk_IPAddressFamily_value(addr, i); | |
702 | const IPAddressFamily *b = sk_IPAddressFamily_value(addr, i + 1); | |
703 | if (IPAddressFamily_cmp(&a, &b) >= 0) | |
704 | return 0; | |
96ea4ae9 BL |
705 | } |
706 | ||
707 | /* | |
0f113f3e | 708 | * Top level's ok, now check each address family. |
96ea4ae9 | 709 | */ |
0f113f3e MC |
710 | for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { |
711 | IPAddressFamily *f = sk_IPAddressFamily_value(addr, i); | |
9021a5df | 712 | int length = length_from_afi(X509v3_addr_get_afi(f)); |
0f113f3e MC |
713 | |
714 | /* | |
715 | * Inheritance is canonical. Anything other than inheritance or | |
716 | * a SEQUENCE OF IPAddressOrRange is an ASN.1 error or something. | |
717 | */ | |
718 | if (f == NULL || f->ipAddressChoice == NULL) | |
719 | return 0; | |
720 | switch (f->ipAddressChoice->type) { | |
721 | case IPAddressChoice_inherit: | |
722 | continue; | |
723 | case IPAddressChoice_addressesOrRanges: | |
724 | break; | |
725 | default: | |
726 | return 0; | |
727 | } | |
728 | ||
729 | /* | |
730 | * It's an IPAddressOrRanges sequence, check it. | |
731 | */ | |
732 | aors = f->ipAddressChoice->u.addressesOrRanges; | |
733 | if (sk_IPAddressOrRange_num(aors) == 0) | |
734 | return 0; | |
735 | for (j = 0; j < sk_IPAddressOrRange_num(aors) - 1; j++) { | |
736 | IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); | |
737 | IPAddressOrRange *b = sk_IPAddressOrRange_value(aors, j + 1); | |
738 | ||
739 | if (!extract_min_max(a, a_min, a_max, length) || | |
740 | !extract_min_max(b, b_min, b_max, length)) | |
741 | return 0; | |
742 | ||
743 | /* | |
744 | * Punt misordered list, overlapping start, or inverted range. | |
745 | */ | |
746 | if (memcmp(a_min, b_min, length) >= 0 || | |
747 | memcmp(a_min, a_max, length) > 0 || | |
748 | memcmp(b_min, b_max, length) > 0) | |
749 | return 0; | |
750 | ||
751 | /* | |
752 | * Punt if adjacent or overlapping. Check for adjacency by | |
753 | * subtracting one from b_min first. | |
754 | */ | |
755 | for (k = length - 1; k >= 0 && b_min[k]-- == 0x00; k--) ; | |
756 | if (memcmp(a_max, b_min, length) >= 0) | |
757 | return 0; | |
758 | ||
759 | /* | |
760 | * Check for range that should be expressed as a prefix. | |
761 | */ | |
762 | if (a->type == IPAddressOrRange_addressRange && | |
763 | range_should_be_prefix(a_min, a_max, length) >= 0) | |
764 | return 0; | |
765 | } | |
766 | ||
767 | /* | |
768 | * Check range to see if it's inverted or should be a | |
769 | * prefix. | |
770 | */ | |
771 | j = sk_IPAddressOrRange_num(aors) - 1; | |
772 | { | |
773 | IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); | |
774 | if (a != NULL && a->type == IPAddressOrRange_addressRange) { | |
775 | if (!extract_min_max(a, a_min, a_max, length)) | |
776 | return 0; | |
777 | if (memcmp(a_min, a_max, length) > 0 || | |
778 | range_should_be_prefix(a_min, a_max, length) >= 0) | |
779 | return 0; | |
780 | } | |
781 | } | |
96ea4ae9 | 782 | } |
96ea4ae9 | 783 | |
0f113f3e MC |
784 | /* |
785 | * If we made it through all that, we're happy. | |
786 | */ | |
787 | return 1; | |
96ea4ae9 BL |
788 | } |
789 | ||
790 | /* | |
791 | * Whack an IPAddressOrRanges into canonical form. | |
792 | */ | |
793 | static int IPAddressOrRanges_canonize(IPAddressOrRanges *aors, | |
0f113f3e | 794 | const unsigned afi) |
96ea4ae9 | 795 | { |
0f113f3e | 796 | int i, j, length = length_from_afi(afi); |
96ea4ae9 | 797 | |
58b75e9c | 798 | /* |
0f113f3e | 799 | * Sort the IPAddressOrRanges sequence. |
58b75e9c | 800 | */ |
0f113f3e | 801 | sk_IPAddressOrRange_sort(aors); |
58b75e9c | 802 | |
96ea4ae9 | 803 | /* |
0f113f3e | 804 | * Clean up representation issues, punt on duplicates or overlaps. |
96ea4ae9 | 805 | */ |
0f113f3e MC |
806 | for (i = 0; i < sk_IPAddressOrRange_num(aors) - 1; i++) { |
807 | IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, i); | |
808 | IPAddressOrRange *b = sk_IPAddressOrRange_value(aors, i + 1); | |
809 | unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; | |
810 | unsigned char b_min[ADDR_RAW_BUF_LEN], b_max[ADDR_RAW_BUF_LEN]; | |
811 | ||
812 | if (!extract_min_max(a, a_min, a_max, length) || | |
813 | !extract_min_max(b, b_min, b_max, length)) | |
814 | return 0; | |
815 | ||
816 | /* | |
817 | * Punt inverted ranges. | |
818 | */ | |
819 | if (memcmp(a_min, a_max, length) > 0 || | |
820 | memcmp(b_min, b_max, length) > 0) | |
821 | return 0; | |
822 | ||
823 | /* | |
824 | * Punt overlaps. | |
825 | */ | |
826 | if (memcmp(a_max, b_min, length) >= 0) | |
827 | return 0; | |
828 | ||
829 | /* | |
830 | * Merge if a and b are adjacent. We check for | |
831 | * adjacency by subtracting one from b_min first. | |
832 | */ | |
833 | for (j = length - 1; j >= 0 && b_min[j]-- == 0x00; j--) ; | |
834 | if (memcmp(a_max, b_min, length) == 0) { | |
835 | IPAddressOrRange *merged; | |
836 | if (!make_addressRange(&merged, a_min, b_max, length)) | |
837 | return 0; | |
838 | (void)sk_IPAddressOrRange_set(aors, i, merged); | |
839 | (void)sk_IPAddressOrRange_delete(aors, i + 1); | |
840 | IPAddressOrRange_free(a); | |
841 | IPAddressOrRange_free(b); | |
842 | --i; | |
843 | continue; | |
844 | } | |
845 | } | |
96ea4ae9 BL |
846 | |
847 | /* | |
0f113f3e | 848 | * Check for inverted final range. |
96ea4ae9 | 849 | */ |
0f113f3e MC |
850 | j = sk_IPAddressOrRange_num(aors) - 1; |
851 | { | |
852 | IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); | |
853 | if (a != NULL && a->type == IPAddressOrRange_addressRange) { | |
854 | unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; | |
dfefe7ec MC |
855 | if (!extract_min_max(a, a_min, a_max, length)) |
856 | return 0; | |
0f113f3e MC |
857 | if (memcmp(a_min, a_max, length) > 0) |
858 | return 0; | |
859 | } | |
58b75e9c | 860 | } |
58b75e9c | 861 | |
0f113f3e | 862 | return 1; |
96ea4ae9 BL |
863 | } |
864 | ||
865 | /* | |
866 | * Whack an IPAddrBlocks extension into canonical form. | |
867 | */ | |
9021a5df | 868 | int X509v3_addr_canonize(IPAddrBlocks *addr) |
96ea4ae9 | 869 | { |
0f113f3e MC |
870 | int i; |
871 | for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { | |
872 | IPAddressFamily *f = sk_IPAddressFamily_value(addr, i); | |
873 | if (f->ipAddressChoice->type == IPAddressChoice_addressesOrRanges && | |
874 | !IPAddressOrRanges_canonize(f->ipAddressChoice-> | |
875 | u.addressesOrRanges, | |
9021a5df | 876 | X509v3_addr_get_afi(f))) |
0f113f3e MC |
877 | return 0; |
878 | } | |
879 | (void)sk_IPAddressFamily_set_cmp_func(addr, IPAddressFamily_cmp); | |
880 | sk_IPAddressFamily_sort(addr); | |
42d7d7dd MC |
881 | if (!ossl_assert(X509v3_addr_is_canonical(addr))) |
882 | return 0; | |
0f113f3e | 883 | return 1; |
96ea4ae9 BL |
884 | } |
885 | ||
886 | /* | |
887 | * v2i handler for the IPAddrBlocks extension. | |
888 | */ | |
2e6a7b3e | 889 | static void *v2i_IPAddrBlocks(const struct v3_ext_method *method, |
0f113f3e MC |
890 | struct v3_ext_ctx *ctx, |
891 | STACK_OF(CONF_VALUE) *values) | |
96ea4ae9 | 892 | { |
0f113f3e MC |
893 | static const char v4addr_chars[] = "0123456789."; |
894 | static const char v6addr_chars[] = "0123456789.:abcdefABCDEF"; | |
895 | IPAddrBlocks *addr = NULL; | |
896 | char *s = NULL, *t; | |
897 | int i; | |
898 | ||
899 | if ((addr = sk_IPAddressFamily_new(IPAddressFamily_cmp)) == NULL) { | |
9311d0c4 | 900 | ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); |
0f113f3e | 901 | return NULL; |
96ea4ae9 BL |
902 | } |
903 | ||
0f113f3e MC |
904 | for (i = 0; i < sk_CONF_VALUE_num(values); i++) { |
905 | CONF_VALUE *val = sk_CONF_VALUE_value(values, i); | |
906 | unsigned char min[ADDR_RAW_BUF_LEN], max[ADDR_RAW_BUF_LEN]; | |
907 | unsigned afi, *safi = NULL, safi_; | |
4c9b0a03 | 908 | const char *addr_chars = NULL; |
0f113f3e MC |
909 | int prefixlen, i1, i2, delim, length; |
910 | ||
5f5edd7d | 911 | if (!v3_name_cmp(val->name, "IPv4")) { |
0f113f3e | 912 | afi = IANA_AFI_IPV4; |
5f5edd7d | 913 | } else if (!v3_name_cmp(val->name, "IPv6")) { |
0f113f3e | 914 | afi = IANA_AFI_IPV6; |
5f5edd7d | 915 | } else if (!v3_name_cmp(val->name, "IPv4-SAFI")) { |
0f113f3e MC |
916 | afi = IANA_AFI_IPV4; |
917 | safi = &safi_; | |
5f5edd7d | 918 | } else if (!v3_name_cmp(val->name, "IPv6-SAFI")) { |
0f113f3e MC |
919 | afi = IANA_AFI_IPV6; |
920 | safi = &safi_; | |
921 | } else { | |
a150f8e1 RL |
922 | ERR_raise_data(ERR_LIB_X509V3, X509V3_R_EXTENSION_NAME_ERROR, |
923 | "%s", val->name); | |
0f113f3e MC |
924 | goto err; |
925 | } | |
926 | ||
927 | switch (afi) { | |
928 | case IANA_AFI_IPV4: | |
929 | addr_chars = v4addr_chars; | |
930 | break; | |
931 | case IANA_AFI_IPV6: | |
932 | addr_chars = v6addr_chars; | |
933 | break; | |
934 | } | |
935 | ||
936 | length = length_from_afi(afi); | |
937 | ||
938 | /* | |
7644a9ae | 939 | * Handle SAFI, if any, and OPENSSL_strdup() so we can null-terminate |
0f113f3e MC |
940 | * the other input values. |
941 | */ | |
942 | if (safi != NULL) { | |
943 | *safi = strtoul(val->value, &t, 0); | |
944 | t += strspn(t, " \t"); | |
945 | if (*safi > 0xFF || *t++ != ':') { | |
9311d0c4 | 946 | ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_SAFI); |
c90c4693 | 947 | X509V3_conf_add_error_name_value(val); |
0f113f3e MC |
948 | goto err; |
949 | } | |
950 | t += strspn(t, " \t"); | |
7644a9ae | 951 | s = OPENSSL_strdup(t); |
0f113f3e | 952 | } else { |
7644a9ae | 953 | s = OPENSSL_strdup(val->value); |
0f113f3e MC |
954 | } |
955 | if (s == NULL) { | |
9311d0c4 | 956 | ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); |
0f113f3e MC |
957 | goto err; |
958 | } | |
959 | ||
960 | /* | |
961 | * Check for inheritance. Not worth additional complexity to | |
962 | * optimize this (seldom-used) case. | |
963 | */ | |
86885c28 | 964 | if (strcmp(s, "inherit") == 0) { |
9021a5df | 965 | if (!X509v3_addr_add_inherit(addr, afi, safi)) { |
9311d0c4 | 966 | ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_INHERITANCE); |
c90c4693 | 967 | X509V3_conf_add_error_name_value(val); |
0f113f3e MC |
968 | goto err; |
969 | } | |
970 | OPENSSL_free(s); | |
971 | s = NULL; | |
972 | continue; | |
973 | } | |
974 | ||
975 | i1 = strspn(s, addr_chars); | |
976 | i2 = i1 + strspn(s + i1, " \t"); | |
977 | delim = s[i2++]; | |
978 | s[i1] = '\0'; | |
979 | ||
980 | if (a2i_ipadd(min, s) != length) { | |
9311d0c4 | 981 | ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_IPADDRESS); |
c90c4693 | 982 | X509V3_conf_add_error_name_value(val); |
0f113f3e MC |
983 | goto err; |
984 | } | |
985 | ||
986 | switch (delim) { | |
987 | case '/': | |
988 | prefixlen = (int)strtoul(s + i2, &t, 10); | |
989 | if (t == s + i2 || *t != '\0') { | |
9311d0c4 | 990 | ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_VALUE_ERROR); |
c90c4693 | 991 | X509V3_conf_add_error_name_value(val); |
0f113f3e MC |
992 | goto err; |
993 | } | |
9021a5df | 994 | if (!X509v3_addr_add_prefix(addr, afi, safi, min, prefixlen)) { |
9311d0c4 | 995 | ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); |
0f113f3e MC |
996 | goto err; |
997 | } | |
998 | break; | |
999 | case '-': | |
1000 | i1 = i2 + strspn(s + i2, " \t"); | |
1001 | i2 = i1 + strspn(s + i1, addr_chars); | |
1002 | if (i1 == i2 || s[i2] != '\0') { | |
9311d0c4 | 1003 | ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_VALUE_ERROR); |
c90c4693 | 1004 | X509V3_conf_add_error_name_value(val); |
0f113f3e MC |
1005 | goto err; |
1006 | } | |
1007 | if (a2i_ipadd(max, s + i1) != length) { | |
9311d0c4 | 1008 | ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_IPADDRESS); |
c90c4693 | 1009 | X509V3_conf_add_error_name_value(val); |
0f113f3e MC |
1010 | goto err; |
1011 | } | |
1012 | if (memcmp(min, max, length_from_afi(afi)) > 0) { | |
9311d0c4 | 1013 | ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_VALUE_ERROR); |
c90c4693 | 1014 | X509V3_conf_add_error_name_value(val); |
0f113f3e MC |
1015 | goto err; |
1016 | } | |
9021a5df | 1017 | if (!X509v3_addr_add_range(addr, afi, safi, min, max)) { |
9311d0c4 | 1018 | ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); |
0f113f3e MC |
1019 | goto err; |
1020 | } | |
1021 | break; | |
1022 | case '\0': | |
9021a5df | 1023 | if (!X509v3_addr_add_prefix(addr, afi, safi, min, length * 8)) { |
9311d0c4 | 1024 | ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); |
0f113f3e MC |
1025 | goto err; |
1026 | } | |
1027 | break; | |
1028 | default: | |
9311d0c4 | 1029 | ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_VALUE_ERROR); |
c90c4693 | 1030 | X509V3_conf_add_error_name_value(val); |
0f113f3e MC |
1031 | goto err; |
1032 | } | |
1033 | ||
1034 | OPENSSL_free(s); | |
1035 | s = NULL; | |
96ea4ae9 BL |
1036 | } |
1037 | ||
1038 | /* | |
0f113f3e | 1039 | * Canonize the result, then we're done. |
96ea4ae9 | 1040 | */ |
9021a5df | 1041 | if (!X509v3_addr_canonize(addr)) |
0f113f3e MC |
1042 | goto err; |
1043 | return addr; | |
96ea4ae9 BL |
1044 | |
1045 | err: | |
0f113f3e MC |
1046 | OPENSSL_free(s); |
1047 | sk_IPAddressFamily_pop_free(addr, IPAddressFamily_free); | |
1048 | return NULL; | |
96ea4ae9 BL |
1049 | } |
1050 | ||
1051 | /* | |
1052 | * OpenSSL dispatch | |
1053 | */ | |
560b79cb | 1054 | const X509V3_EXT_METHOD v3_addr = { |
0f113f3e MC |
1055 | NID_sbgp_ipAddrBlock, /* nid */ |
1056 | 0, /* flags */ | |
1057 | ASN1_ITEM_ref(IPAddrBlocks), /* template */ | |
1058 | 0, 0, 0, 0, /* old functions, ignored */ | |
1059 | 0, /* i2s */ | |
1060 | 0, /* s2i */ | |
1061 | 0, /* i2v */ | |
1062 | v2i_IPAddrBlocks, /* v2i */ | |
1063 | i2r_IPAddrBlocks, /* i2r */ | |
1064 | 0, /* r2i */ | |
1065 | NULL /* extension-specific data */ | |
96ea4ae9 BL |
1066 | }; |
1067 | ||
1068 | /* | |
1069 | * Figure out whether extension sues inheritance. | |
1070 | */ | |
9021a5df | 1071 | int X509v3_addr_inherits(IPAddrBlocks *addr) |
96ea4ae9 | 1072 | { |
0f113f3e MC |
1073 | int i; |
1074 | if (addr == NULL) | |
1075 | return 0; | |
1076 | for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { | |
1077 | IPAddressFamily *f = sk_IPAddressFamily_value(addr, i); | |
1078 | if (f->ipAddressChoice->type == IPAddressChoice_inherit) | |
1079 | return 1; | |
1080 | } | |
96ea4ae9 | 1081 | return 0; |
96ea4ae9 BL |
1082 | } |
1083 | ||
1084 | /* | |
1085 | * Figure out whether parent contains child. | |
1086 | */ | |
1087 | static int addr_contains(IPAddressOrRanges *parent, | |
0f113f3e | 1088 | IPAddressOrRanges *child, int length) |
96ea4ae9 | 1089 | { |
0f113f3e MC |
1090 | unsigned char p_min[ADDR_RAW_BUF_LEN], p_max[ADDR_RAW_BUF_LEN]; |
1091 | unsigned char c_min[ADDR_RAW_BUF_LEN], c_max[ADDR_RAW_BUF_LEN]; | |
1092 | int p, c; | |
1093 | ||
1094 | if (child == NULL || parent == child) | |
1095 | return 1; | |
1096 | if (parent == NULL) | |
1097 | return 0; | |
1098 | ||
1099 | p = 0; | |
1100 | for (c = 0; c < sk_IPAddressOrRange_num(child); c++) { | |
1101 | if (!extract_min_max(sk_IPAddressOrRange_value(child, c), | |
1102 | c_min, c_max, length)) | |
1103 | return -1; | |
1104 | for (;; p++) { | |
1105 | if (p >= sk_IPAddressOrRange_num(parent)) | |
1106 | return 0; | |
1107 | if (!extract_min_max(sk_IPAddressOrRange_value(parent, p), | |
1108 | p_min, p_max, length)) | |
1109 | return 0; | |
1110 | if (memcmp(p_max, c_max, length) < 0) | |
1111 | continue; | |
1112 | if (memcmp(p_min, c_min, length) > 0) | |
1113 | return 0; | |
1114 | break; | |
1115 | } | |
96ea4ae9 | 1116 | } |
96ea4ae9 | 1117 | |
0f113f3e | 1118 | return 1; |
96ea4ae9 BL |
1119 | } |
1120 | ||
1121 | /* | |
1122 | * Test whether a is a subset of b. | |
1123 | */ | |
9021a5df | 1124 | int X509v3_addr_subset(IPAddrBlocks *a, IPAddrBlocks *b) |
96ea4ae9 | 1125 | { |
0f113f3e MC |
1126 | int i; |
1127 | if (a == NULL || a == b) | |
1128 | return 1; | |
9021a5df | 1129 | if (b == NULL || X509v3_addr_inherits(a) || X509v3_addr_inherits(b)) |
0f113f3e MC |
1130 | return 0; |
1131 | (void)sk_IPAddressFamily_set_cmp_func(b, IPAddressFamily_cmp); | |
1132 | for (i = 0; i < sk_IPAddressFamily_num(a); i++) { | |
1133 | IPAddressFamily *fa = sk_IPAddressFamily_value(a, i); | |
1134 | int j = sk_IPAddressFamily_find(b, fa); | |
1135 | IPAddressFamily *fb; | |
1136 | fb = sk_IPAddressFamily_value(b, j); | |
1137 | if (fb == NULL) | |
1138 | return 0; | |
1139 | if (!addr_contains(fb->ipAddressChoice->u.addressesOrRanges, | |
1140 | fa->ipAddressChoice->u.addressesOrRanges, | |
9021a5df | 1141 | length_from_afi(X509v3_addr_get_afi(fb)))) |
0f113f3e MC |
1142 | return 0; |
1143 | } | |
96ea4ae9 | 1144 | return 1; |
96ea4ae9 BL |
1145 | } |
1146 | ||
1147 | /* | |
1148 | * Validation error handling via callback. | |
1149 | */ | |
c73ad690 | 1150 | #define validation_err(_err_) \ |
0f113f3e MC |
1151 | do { \ |
1152 | if (ctx != NULL) { \ | |
1153 | ctx->error = _err_; \ | |
1154 | ctx->error_depth = i; \ | |
1155 | ctx->current_cert = x; \ | |
1156 | ret = ctx->verify_cb(0, ctx); \ | |
1157 | } else { \ | |
1158 | ret = 0; \ | |
1159 | } \ | |
1160 | if (!ret) \ | |
1161 | goto done; \ | |
96ea4ae9 BL |
1162 | } while (0) |
1163 | ||
1164 | /* | |
1165 | * Core code for RFC 3779 2.3 path validation. | |
f3e235ed VD |
1166 | * |
1167 | * Returns 1 for success, 0 on error. | |
1168 | * | |
1169 | * When returning 0, ctx->error MUST be set to an appropriate value other than | |
1170 | * X509_V_OK. | |
96ea4ae9 | 1171 | */ |
9021a5df RS |
1172 | static int addr_validate_path_internal(X509_STORE_CTX *ctx, |
1173 | STACK_OF(X509) *chain, | |
1174 | IPAddrBlocks *ext) | |
96ea4ae9 | 1175 | { |
0f113f3e MC |
1176 | IPAddrBlocks *child = NULL; |
1177 | int i, j, ret = 1; | |
1178 | X509 *x; | |
1179 | ||
42d7d7dd MC |
1180 | if (!ossl_assert(chain != NULL && sk_X509_num(chain) > 0) |
1181 | || !ossl_assert(ctx != NULL || ext != NULL) | |
1182 | || !ossl_assert(ctx == NULL || ctx->verify_cb != NULL)) { | |
1183 | if (ctx != NULL) | |
1184 | ctx->error = X509_V_ERR_UNSPECIFIED; | |
1185 | return 0; | |
1186 | } | |
0f113f3e MC |
1187 | |
1188 | /* | |
1189 | * Figure out where to start. If we don't have an extension to | |
1190 | * check, we're done. Otherwise, check canonical form and | |
1191 | * set up for walking up the chain. | |
1192 | */ | |
1193 | if (ext != NULL) { | |
1194 | i = -1; | |
1195 | x = NULL; | |
1196 | } else { | |
1197 | i = 0; | |
1198 | x = sk_X509_value(chain, i); | |
0f113f3e MC |
1199 | if ((ext = x->rfc3779_addr) == NULL) |
1200 | goto done; | |
96ea4ae9 | 1201 | } |
9021a5df | 1202 | if (!X509v3_addr_is_canonical(ext)) |
0f113f3e MC |
1203 | validation_err(X509_V_ERR_INVALID_EXTENSION); |
1204 | (void)sk_IPAddressFamily_set_cmp_func(ext, IPAddressFamily_cmp); | |
1205 | if ((child = sk_IPAddressFamily_dup(ext)) == NULL) { | |
9311d0c4 | 1206 | ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); |
42d7d7dd MC |
1207 | if (ctx != NULL) |
1208 | ctx->error = X509_V_ERR_OUT_OF_MEM; | |
0f113f3e MC |
1209 | ret = 0; |
1210 | goto done; | |
1211 | } | |
1212 | ||
1213 | /* | |
1214 | * Now walk up the chain. No cert may list resources that its | |
1215 | * parent doesn't list. | |
1216 | */ | |
1217 | for (i++; i < sk_X509_num(chain); i++) { | |
1218 | x = sk_X509_value(chain, i); | |
9021a5df | 1219 | if (!X509v3_addr_is_canonical(x->rfc3779_addr)) |
0f113f3e MC |
1220 | validation_err(X509_V_ERR_INVALID_EXTENSION); |
1221 | if (x->rfc3779_addr == NULL) { | |
1222 | for (j = 0; j < sk_IPAddressFamily_num(child); j++) { | |
1223 | IPAddressFamily *fc = sk_IPAddressFamily_value(child, j); | |
1224 | if (fc->ipAddressChoice->type != IPAddressChoice_inherit) { | |
1225 | validation_err(X509_V_ERR_UNNESTED_RESOURCE); | |
1226 | break; | |
1227 | } | |
1228 | } | |
1229 | continue; | |
1230 | } | |
1231 | (void)sk_IPAddressFamily_set_cmp_func(x->rfc3779_addr, | |
1232 | IPAddressFamily_cmp); | |
1233 | for (j = 0; j < sk_IPAddressFamily_num(child); j++) { | |
1234 | IPAddressFamily *fc = sk_IPAddressFamily_value(child, j); | |
1235 | int k = sk_IPAddressFamily_find(x->rfc3779_addr, fc); | |
1236 | IPAddressFamily *fp = | |
1237 | sk_IPAddressFamily_value(x->rfc3779_addr, k); | |
1238 | if (fp == NULL) { | |
1239 | if (fc->ipAddressChoice->type == | |
1240 | IPAddressChoice_addressesOrRanges) { | |
1241 | validation_err(X509_V_ERR_UNNESTED_RESOURCE); | |
1242 | break; | |
1243 | } | |
1244 | continue; | |
1245 | } | |
1246 | if (fp->ipAddressChoice->type == | |
1247 | IPAddressChoice_addressesOrRanges) { | |
1248 | if (fc->ipAddressChoice->type == IPAddressChoice_inherit | |
1249 | || addr_contains(fp->ipAddressChoice->u.addressesOrRanges, | |
1250 | fc->ipAddressChoice->u.addressesOrRanges, | |
9021a5df | 1251 | length_from_afi(X509v3_addr_get_afi(fc)))) |
225c9660 | 1252 | (void)sk_IPAddressFamily_set(child, j, fp); |
0f113f3e MC |
1253 | else |
1254 | validation_err(X509_V_ERR_UNNESTED_RESOURCE); | |
1255 | } | |
1256 | } | |
96ea4ae9 | 1257 | } |
0f113f3e MC |
1258 | |
1259 | /* | |
1260 | * Trust anchor can't inherit. | |
1261 | */ | |
0f113f3e MC |
1262 | if (x->rfc3779_addr != NULL) { |
1263 | for (j = 0; j < sk_IPAddressFamily_num(x->rfc3779_addr); j++) { | |
1264 | IPAddressFamily *fp = | |
1265 | sk_IPAddressFamily_value(x->rfc3779_addr, j); | |
1266 | if (fp->ipAddressChoice->type == IPAddressChoice_inherit | |
1267 | && sk_IPAddressFamily_find(child, fp) >= 0) | |
1268 | validation_err(X509_V_ERR_UNNESTED_RESOURCE); | |
1269 | } | |
96ea4ae9 | 1270 | } |
96ea4ae9 BL |
1271 | |
1272 | done: | |
0f113f3e MC |
1273 | sk_IPAddressFamily_free(child); |
1274 | return ret; | |
96ea4ae9 BL |
1275 | } |
1276 | ||
c73ad690 | 1277 | #undef validation_err |
96ea4ae9 BL |
1278 | |
1279 | /* | |
1280 | * RFC 3779 2.3 path validation -- called from X509_verify_cert(). | |
1281 | */ | |
9021a5df | 1282 | int X509v3_addr_validate_path(X509_STORE_CTX *ctx) |
96ea4ae9 | 1283 | { |
42d7d7dd MC |
1284 | if (ctx->chain == NULL |
1285 | || sk_X509_num(ctx->chain) == 0 | |
88809830 MC |
1286 | || ctx->verify_cb == NULL) { |
1287 | ctx->error = X509_V_ERR_UNSPECIFIED; | |
42d7d7dd | 1288 | return 0; |
88809830 | 1289 | } |
9021a5df | 1290 | return addr_validate_path_internal(ctx, ctx->chain, NULL); |
96ea4ae9 BL |
1291 | } |
1292 | ||
1293 | /* | |
1294 | * RFC 3779 2.3 path validation of an extension. | |
1295 | * Test whether chain covers extension. | |
1296 | */ | |
9021a5df | 1297 | int X509v3_addr_validate_resource_set(STACK_OF(X509) *chain, |
0f113f3e | 1298 | IPAddrBlocks *ext, int allow_inheritance) |
96ea4ae9 | 1299 | { |
0f113f3e MC |
1300 | if (ext == NULL) |
1301 | return 1; | |
1302 | if (chain == NULL || sk_X509_num(chain) == 0) | |
1303 | return 0; | |
9021a5df | 1304 | if (!allow_inheritance && X509v3_addr_inherits(ext)) |
0f113f3e | 1305 | return 0; |
9021a5df | 1306 | return addr_validate_path_internal(NULL, chain, ext); |
96ea4ae9 | 1307 | } |
47bbaa5b DW |
1308 | |
1309 | #endif /* OPENSSL_NO_RFC3779 */ |