1167612Ssimon/* 2167612Ssimon * Contributed to the OpenSSL Project by the American Registry for 3167612Ssimon * Internet Numbers ("ARIN"). 4167612Ssimon */ 5167612Ssimon/* ==================================================================== 6167612Ssimon * Copyright (c) 2006 The OpenSSL Project. All rights reserved. 7167612Ssimon * 8167612Ssimon * Redistribution and use in source and binary forms, with or without 9167612Ssimon * modification, are permitted provided that the following conditions 10167612Ssimon * are met: 11167612Ssimon * 12167612Ssimon * 1. Redistributions of source code must retain the above copyright 13280304Sjkim * notice, this list of conditions and the following disclaimer. 14167612Ssimon * 15167612Ssimon * 2. Redistributions in binary form must reproduce the above copyright 16167612Ssimon * notice, this list of conditions and the following disclaimer in 17167612Ssimon * the documentation and/or other materials provided with the 18167612Ssimon * distribution. 19167612Ssimon * 20167612Ssimon * 3. All advertising materials mentioning features or use of this 21167612Ssimon * software must display the following acknowledgment: 22167612Ssimon * "This product includes software developed by the OpenSSL Project 23167612Ssimon * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24167612Ssimon * 25167612Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26167612Ssimon * endorse or promote products derived from this software without 27167612Ssimon * prior written permission. For written permission, please contact 28167612Ssimon * licensing@OpenSSL.org. 29167612Ssimon * 30167612Ssimon * 5. Products derived from this software may not be called "OpenSSL" 31167612Ssimon * nor may "OpenSSL" appear in their names without prior written 32167612Ssimon * permission of the OpenSSL Project. 33167612Ssimon * 34167612Ssimon * 6. Redistributions of any form whatsoever must retain the following 35167612Ssimon * acknowledgment: 36167612Ssimon * "This product includes software developed by the OpenSSL Project 37167612Ssimon * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38167612Ssimon * 39167612Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40167612Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41167612Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42167612Ssimon * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43167612Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44167612Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45167612Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46167612Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47167612Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48167612Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49167612Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50167612Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE. 51167612Ssimon * ==================================================================== 52167612Ssimon * 53167612Ssimon * This product includes cryptographic software written by Eric Young 54167612Ssimon * (eay@cryptsoft.com). This product includes software written by Tim 55167612Ssimon * Hudson (tjh@cryptsoft.com). 56167612Ssimon */ 57167612Ssimon 58167612Ssimon/* 59167612Ssimon * Implementation of RFC 3779 section 2.2. 60167612Ssimon */ 61167612Ssimon 62167612Ssimon#include <stdio.h> 63167612Ssimon#include <stdlib.h> 64194206Ssimon 65167612Ssimon#include "cryptlib.h" 66167612Ssimon#include <openssl/conf.h> 67167612Ssimon#include <openssl/asn1.h> 68167612Ssimon#include <openssl/asn1t.h> 69167612Ssimon#include <openssl/buffer.h> 70167612Ssimon#include <openssl/x509v3.h> 71167612Ssimon 72167612Ssimon#ifndef OPENSSL_NO_RFC3779 73167612Ssimon 74167612Ssimon/* 75167612Ssimon * OpenSSL ASN.1 template translation of RFC 3779 2.2.3. 76167612Ssimon */ 77167612Ssimon 78167612SsimonASN1_SEQUENCE(IPAddressRange) = { 79167612Ssimon ASN1_SIMPLE(IPAddressRange, min, ASN1_BIT_STRING), 80167612Ssimon ASN1_SIMPLE(IPAddressRange, max, ASN1_BIT_STRING) 81167612Ssimon} ASN1_SEQUENCE_END(IPAddressRange) 82167612Ssimon 83167612SsimonASN1_CHOICE(IPAddressOrRange) = { 84167612Ssimon ASN1_SIMPLE(IPAddressOrRange, u.addressPrefix, ASN1_BIT_STRING), 85167612Ssimon ASN1_SIMPLE(IPAddressOrRange, u.addressRange, IPAddressRange) 86167612Ssimon} ASN1_CHOICE_END(IPAddressOrRange) 87167612Ssimon 88167612SsimonASN1_CHOICE(IPAddressChoice) = { 89167612Ssimon ASN1_SIMPLE(IPAddressChoice, u.inherit, ASN1_NULL), 90167612Ssimon ASN1_SEQUENCE_OF(IPAddressChoice, u.addressesOrRanges, IPAddressOrRange) 91167612Ssimon} ASN1_CHOICE_END(IPAddressChoice) 92167612Ssimon 93167612SsimonASN1_SEQUENCE(IPAddressFamily) = { 94167612Ssimon ASN1_SIMPLE(IPAddressFamily, addressFamily, ASN1_OCTET_STRING), 95167612Ssimon ASN1_SIMPLE(IPAddressFamily, ipAddressChoice, IPAddressChoice) 96167612Ssimon} ASN1_SEQUENCE_END(IPAddressFamily) 97167612Ssimon 98280304SjkimASN1_ITEM_TEMPLATE(IPAddrBlocks) = 99167612Ssimon ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, 100280304Sjkim IPAddrBlocks, IPAddressFamily) 101167612SsimonASN1_ITEM_TEMPLATE_END(IPAddrBlocks) 102167612Ssimon 103167612SsimonIMPLEMENT_ASN1_FUNCTIONS(IPAddressRange) 104167612SsimonIMPLEMENT_ASN1_FUNCTIONS(IPAddressOrRange) 105167612SsimonIMPLEMENT_ASN1_FUNCTIONS(IPAddressChoice) 106167612SsimonIMPLEMENT_ASN1_FUNCTIONS(IPAddressFamily) 107167612Ssimon 108167612Ssimon/* 109167612Ssimon * How much buffer space do we need for a raw address? 110167612Ssimon */ 111280304Sjkim# define ADDR_RAW_BUF_LEN 16 112167612Ssimon 113167612Ssimon/* 114167612Ssimon * What's the address length associated with this AFI? 115167612Ssimon */ 116167612Ssimonstatic int length_from_afi(const unsigned afi) 117167612Ssimon{ 118280304Sjkim switch (afi) { 119280304Sjkim case IANA_AFI_IPV4: 120280304Sjkim return 4; 121280304Sjkim case IANA_AFI_IPV6: 122280304Sjkim return 16; 123280304Sjkim default: 124280304Sjkim return 0; 125280304Sjkim } 126167612Ssimon} 127167612Ssimon 128167612Ssimon/* 129167612Ssimon * Extract the AFI from an IPAddressFamily. 130167612Ssimon */ 131194206Ssimonunsigned int v3_addr_get_afi(const IPAddressFamily *f) 132167612Ssimon{ 133326359Sdelphij if (f == NULL 134326359Sdelphij || f->addressFamily == NULL 135326359Sdelphij || f->addressFamily->data == NULL 136326359Sdelphij || f->addressFamily->length < 2) 137326359Sdelphij return 0; 138326359Sdelphij return (f->addressFamily->data[0] << 8) | f->addressFamily->data[1]; 139167612Ssimon} 140167612Ssimon 141167612Ssimon/* 142167612Ssimon * Expand the bitstring form of an address into a raw byte array. 143167612Ssimon * At the moment this is coded for simplicity, not speed. 144167612Ssimon */ 145237657Sjkimstatic int addr_expand(unsigned char *addr, 146280304Sjkim const ASN1_BIT_STRING *bs, 147280304Sjkim const int length, const unsigned char fill) 148167612Ssimon{ 149280304Sjkim if (bs->length < 0 || bs->length > length) 150280304Sjkim return 0; 151280304Sjkim if (bs->length > 0) { 152280304Sjkim memcpy(addr, bs->data, bs->length); 153280304Sjkim if ((bs->flags & 7) != 0) { 154280304Sjkim unsigned char mask = 0xFF >> (8 - (bs->flags & 7)); 155280304Sjkim if (fill == 0) 156280304Sjkim addr[bs->length - 1] &= ~mask; 157280304Sjkim else 158280304Sjkim addr[bs->length - 1] |= mask; 159280304Sjkim } 160167612Ssimon } 161280304Sjkim memset(addr + bs->length, fill, length - bs->length); 162280304Sjkim return 1; 163167612Ssimon} 164167612Ssimon 165167612Ssimon/* 166167612Ssimon * Extract the prefix length from a bitstring. 167167612Ssimon */ 168280304Sjkim# define addr_prefixlen(bs) ((int) ((bs)->length * 8 - ((bs)->flags & 7))) 169167612Ssimon 170167612Ssimon/* 171167612Ssimon * i2r handler for one address bitstring. 172167612Ssimon */ 173167612Ssimonstatic int i2r_address(BIO *out, 174280304Sjkim const unsigned afi, 175280304Sjkim const unsigned char fill, const ASN1_BIT_STRING *bs) 176167612Ssimon{ 177280304Sjkim unsigned char addr[ADDR_RAW_BUF_LEN]; 178280304Sjkim int i, n; 179167612Ssimon 180280304Sjkim if (bs->length < 0) 181280304Sjkim return 0; 182280304Sjkim switch (afi) { 183280304Sjkim case IANA_AFI_IPV4: 184280304Sjkim if (!addr_expand(addr, bs, 4, fill)) 185280304Sjkim return 0; 186280304Sjkim BIO_printf(out, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); 187280304Sjkim break; 188280304Sjkim case IANA_AFI_IPV6: 189280304Sjkim if (!addr_expand(addr, bs, 16, fill)) 190280304Sjkim return 0; 191280304Sjkim for (n = 16; n > 1 && addr[n - 1] == 0x00 && addr[n - 2] == 0x00; 192280304Sjkim n -= 2) ; 193280304Sjkim for (i = 0; i < n; i += 2) 194280304Sjkim BIO_printf(out, "%x%s", (addr[i] << 8) | addr[i + 1], 195280304Sjkim (i < 14 ? ":" : "")); 196280304Sjkim if (i < 16) 197280304Sjkim BIO_puts(out, ":"); 198280304Sjkim if (i == 0) 199280304Sjkim BIO_puts(out, ":"); 200280304Sjkim break; 201280304Sjkim default: 202280304Sjkim for (i = 0; i < bs->length; i++) 203280304Sjkim BIO_printf(out, "%s%02x", (i > 0 ? ":" : ""), bs->data[i]); 204280304Sjkim BIO_printf(out, "[%d]", (int)(bs->flags & 7)); 205280304Sjkim break; 206280304Sjkim } 207280304Sjkim return 1; 208167612Ssimon} 209167612Ssimon 210167612Ssimon/* 211167612Ssimon * i2r handler for a sequence of addresses and ranges. 212167612Ssimon */ 213167612Ssimonstatic int i2r_IPAddressOrRanges(BIO *out, 214280304Sjkim const int indent, 215280304Sjkim const IPAddressOrRanges *aors, 216280304Sjkim const unsigned afi) 217167612Ssimon{ 218280304Sjkim int i; 219280304Sjkim for (i = 0; i < sk_IPAddressOrRange_num(aors); i++) { 220280304Sjkim const IPAddressOrRange *aor = sk_IPAddressOrRange_value(aors, i); 221280304Sjkim BIO_printf(out, "%*s", indent, ""); 222280304Sjkim switch (aor->type) { 223280304Sjkim case IPAddressOrRange_addressPrefix: 224280304Sjkim if (!i2r_address(out, afi, 0x00, aor->u.addressPrefix)) 225280304Sjkim return 0; 226280304Sjkim BIO_printf(out, "/%d\n", addr_prefixlen(aor->u.addressPrefix)); 227280304Sjkim continue; 228280304Sjkim case IPAddressOrRange_addressRange: 229280304Sjkim if (!i2r_address(out, afi, 0x00, aor->u.addressRange->min)) 230280304Sjkim return 0; 231280304Sjkim BIO_puts(out, "-"); 232280304Sjkim if (!i2r_address(out, afi, 0xFF, aor->u.addressRange->max)) 233280304Sjkim return 0; 234280304Sjkim BIO_puts(out, "\n"); 235280304Sjkim continue; 236280304Sjkim } 237167612Ssimon } 238280304Sjkim return 1; 239167612Ssimon} 240167612Ssimon 241167612Ssimon/* 242167612Ssimon * i2r handler for an IPAddrBlocks extension. 243167612Ssimon */ 244238405Sjkimstatic int i2r_IPAddrBlocks(const X509V3_EXT_METHOD *method, 245280304Sjkim void *ext, BIO *out, int indent) 246167612Ssimon{ 247280304Sjkim const IPAddrBlocks *addr = ext; 248280304Sjkim int i; 249280304Sjkim for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { 250280304Sjkim IPAddressFamily *f = sk_IPAddressFamily_value(addr, i); 251280304Sjkim const unsigned int afi = v3_addr_get_afi(f); 252280304Sjkim switch (afi) { 253280304Sjkim case IANA_AFI_IPV4: 254280304Sjkim BIO_printf(out, "%*sIPv4", indent, ""); 255280304Sjkim break; 256280304Sjkim case IANA_AFI_IPV6: 257280304Sjkim BIO_printf(out, "%*sIPv6", indent, ""); 258280304Sjkim break; 259280304Sjkim default: 260280304Sjkim BIO_printf(out, "%*sUnknown AFI %u", indent, "", afi); 261280304Sjkim break; 262280304Sjkim } 263280304Sjkim if (f->addressFamily->length > 2) { 264280304Sjkim switch (f->addressFamily->data[2]) { 265280304Sjkim case 1: 266280304Sjkim BIO_puts(out, " (Unicast)"); 267280304Sjkim break; 268280304Sjkim case 2: 269280304Sjkim BIO_puts(out, " (Multicast)"); 270280304Sjkim break; 271280304Sjkim case 3: 272280304Sjkim BIO_puts(out, " (Unicast/Multicast)"); 273280304Sjkim break; 274280304Sjkim case 4: 275280304Sjkim BIO_puts(out, " (MPLS)"); 276280304Sjkim break; 277280304Sjkim case 64: 278280304Sjkim BIO_puts(out, " (Tunnel)"); 279280304Sjkim break; 280280304Sjkim case 65: 281280304Sjkim BIO_puts(out, " (VPLS)"); 282280304Sjkim break; 283280304Sjkim case 66: 284280304Sjkim BIO_puts(out, " (BGP MDT)"); 285280304Sjkim break; 286280304Sjkim case 128: 287280304Sjkim BIO_puts(out, " (MPLS-labeled VPN)"); 288280304Sjkim break; 289280304Sjkim default: 290280304Sjkim BIO_printf(out, " (Unknown SAFI %u)", 291280304Sjkim (unsigned)f->addressFamily->data[2]); 292280304Sjkim break; 293280304Sjkim } 294280304Sjkim } 295280304Sjkim switch (f->ipAddressChoice->type) { 296280304Sjkim case IPAddressChoice_inherit: 297280304Sjkim BIO_puts(out, ": inherit\n"); 298280304Sjkim break; 299280304Sjkim case IPAddressChoice_addressesOrRanges: 300280304Sjkim BIO_puts(out, ":\n"); 301280304Sjkim if (!i2r_IPAddressOrRanges(out, 302280304Sjkim indent + 2, 303280304Sjkim f->ipAddressChoice-> 304280304Sjkim u.addressesOrRanges, afi)) 305280304Sjkim return 0; 306280304Sjkim break; 307280304Sjkim } 308167612Ssimon } 309280304Sjkim return 1; 310167612Ssimon} 311167612Ssimon 312167612Ssimon/* 313167612Ssimon * Sort comparison function for a sequence of IPAddressOrRange 314167612Ssimon * elements. 315237657Sjkim * 316237657Sjkim * There's no sane answer we can give if addr_expand() fails, and an 317237657Sjkim * assertion failure on externally supplied data is seriously uncool, 318237657Sjkim * so we just arbitrarily declare that if given invalid inputs this 319237657Sjkim * function returns -1. If this messes up your preferred sort order 320237657Sjkim * for garbage input, tough noogies. 321167612Ssimon */ 322167612Ssimonstatic int IPAddressOrRange_cmp(const IPAddressOrRange *a, 323280304Sjkim const IPAddressOrRange *b, const int length) 324167612Ssimon{ 325280304Sjkim unsigned char addr_a[ADDR_RAW_BUF_LEN], addr_b[ADDR_RAW_BUF_LEN]; 326280304Sjkim int prefixlen_a = 0, prefixlen_b = 0; 327280304Sjkim int r; 328167612Ssimon 329280304Sjkim switch (a->type) { 330280304Sjkim case IPAddressOrRange_addressPrefix: 331280304Sjkim if (!addr_expand(addr_a, a->u.addressPrefix, length, 0x00)) 332280304Sjkim return -1; 333280304Sjkim prefixlen_a = addr_prefixlen(a->u.addressPrefix); 334280304Sjkim break; 335280304Sjkim case IPAddressOrRange_addressRange: 336280304Sjkim if (!addr_expand(addr_a, a->u.addressRange->min, length, 0x00)) 337280304Sjkim return -1; 338280304Sjkim prefixlen_a = length * 8; 339280304Sjkim break; 340280304Sjkim } 341167612Ssimon 342280304Sjkim switch (b->type) { 343280304Sjkim case IPAddressOrRange_addressPrefix: 344280304Sjkim if (!addr_expand(addr_b, b->u.addressPrefix, length, 0x00)) 345280304Sjkim return -1; 346280304Sjkim prefixlen_b = addr_prefixlen(b->u.addressPrefix); 347280304Sjkim break; 348280304Sjkim case IPAddressOrRange_addressRange: 349280304Sjkim if (!addr_expand(addr_b, b->u.addressRange->min, length, 0x00)) 350280304Sjkim return -1; 351280304Sjkim prefixlen_b = length * 8; 352280304Sjkim break; 353280304Sjkim } 354167612Ssimon 355280304Sjkim if ((r = memcmp(addr_a, addr_b, length)) != 0) 356280304Sjkim return r; 357280304Sjkim else 358280304Sjkim return prefixlen_a - prefixlen_b; 359167612Ssimon} 360167612Ssimon 361167612Ssimon/* 362167612Ssimon * IPv4-specific closure over IPAddressOrRange_cmp, since sk_sort() 363167612Ssimon * comparision routines are only allowed two arguments. 364167612Ssimon */ 365280304Sjkimstatic int v4IPAddressOrRange_cmp(const IPAddressOrRange *const *a, 366280304Sjkim const IPAddressOrRange *const *b) 367167612Ssimon{ 368280304Sjkim return IPAddressOrRange_cmp(*a, *b, 4); 369167612Ssimon} 370167612Ssimon 371167612Ssimon/* 372167612Ssimon * IPv6-specific closure over IPAddressOrRange_cmp, since sk_sort() 373167612Ssimon * comparision routines are only allowed two arguments. 374167612Ssimon */ 375280304Sjkimstatic int v6IPAddressOrRange_cmp(const IPAddressOrRange *const *a, 376280304Sjkim const IPAddressOrRange *const *b) 377167612Ssimon{ 378280304Sjkim return IPAddressOrRange_cmp(*a, *b, 16); 379167612Ssimon} 380167612Ssimon 381167612Ssimon/* 382167612Ssimon * Calculate whether a range collapses to a prefix. 383167612Ssimon * See last paragraph of RFC 3779 2.2.3.7. 384167612Ssimon */ 385167612Ssimonstatic int range_should_be_prefix(const unsigned char *min, 386280304Sjkim const unsigned char *max, const int length) 387167612Ssimon{ 388280304Sjkim unsigned char mask; 389280304Sjkim int i, j; 390167612Ssimon 391280304Sjkim OPENSSL_assert(memcmp(min, max, length) <= 0); 392280304Sjkim for (i = 0; i < length && min[i] == max[i]; i++) ; 393280304Sjkim for (j = length - 1; j >= 0 && min[j] == 0x00 && max[j] == 0xFF; j--) ; 394280304Sjkim if (i < j) 395280304Sjkim return -1; 396280304Sjkim if (i > j) 397280304Sjkim return i * 8; 398280304Sjkim mask = min[i] ^ max[i]; 399280304Sjkim switch (mask) { 400280304Sjkim case 0x01: 401280304Sjkim j = 7; 402280304Sjkim break; 403280304Sjkim case 0x03: 404280304Sjkim j = 6; 405280304Sjkim break; 406280304Sjkim case 0x07: 407280304Sjkim j = 5; 408280304Sjkim break; 409280304Sjkim case 0x0F: 410280304Sjkim j = 4; 411280304Sjkim break; 412280304Sjkim case 0x1F: 413280304Sjkim j = 3; 414280304Sjkim break; 415280304Sjkim case 0x3F: 416280304Sjkim j = 2; 417280304Sjkim break; 418280304Sjkim case 0x7F: 419280304Sjkim j = 1; 420280304Sjkim break; 421280304Sjkim default: 422280304Sjkim return -1; 423280304Sjkim } 424280304Sjkim if ((min[i] & mask) != 0 || (max[i] & mask) != mask) 425280304Sjkim return -1; 426280304Sjkim else 427280304Sjkim return i * 8 + j; 428167612Ssimon} 429167612Ssimon 430167612Ssimon/* 431167612Ssimon * Construct a prefix. 432167612Ssimon */ 433167612Ssimonstatic int make_addressPrefix(IPAddressOrRange **result, 434280304Sjkim unsigned char *addr, const int prefixlen) 435167612Ssimon{ 436280304Sjkim int bytelen = (prefixlen + 7) / 8, bitlen = prefixlen % 8; 437280304Sjkim IPAddressOrRange *aor = IPAddressOrRange_new(); 438167612Ssimon 439280304Sjkim if (aor == NULL) 440280304Sjkim return 0; 441280304Sjkim aor->type = IPAddressOrRange_addressPrefix; 442280304Sjkim if (aor->u.addressPrefix == NULL && 443280304Sjkim (aor->u.addressPrefix = ASN1_BIT_STRING_new()) == NULL) 444280304Sjkim goto err; 445280304Sjkim if (!ASN1_BIT_STRING_set(aor->u.addressPrefix, addr, bytelen)) 446280304Sjkim goto err; 447280304Sjkim aor->u.addressPrefix->flags &= ~7; 448280304Sjkim aor->u.addressPrefix->flags |= ASN1_STRING_FLAG_BITS_LEFT; 449280304Sjkim if (bitlen > 0) { 450280304Sjkim aor->u.addressPrefix->data[bytelen - 1] &= ~(0xFF >> bitlen); 451280304Sjkim aor->u.addressPrefix->flags |= 8 - bitlen; 452280304Sjkim } 453167612Ssimon 454280304Sjkim *result = aor; 455280304Sjkim return 1; 456280304Sjkim 457167612Ssimon err: 458280304Sjkim IPAddressOrRange_free(aor); 459280304Sjkim return 0; 460167612Ssimon} 461167612Ssimon 462167612Ssimon/* 463167612Ssimon * Construct a range. If it can be expressed as a prefix, 464167612Ssimon * return a prefix instead. Doing this here simplifies 465167612Ssimon * the rest of the code considerably. 466167612Ssimon */ 467167612Ssimonstatic int make_addressRange(IPAddressOrRange **result, 468280304Sjkim unsigned char *min, 469280304Sjkim unsigned char *max, const int length) 470167612Ssimon{ 471280304Sjkim IPAddressOrRange *aor; 472280304Sjkim int i, prefixlen; 473167612Ssimon 474280304Sjkim if ((prefixlen = range_should_be_prefix(min, max, length)) >= 0) 475280304Sjkim return make_addressPrefix(result, min, prefixlen); 476167612Ssimon 477280304Sjkim if ((aor = IPAddressOrRange_new()) == NULL) 478280304Sjkim return 0; 479280304Sjkim aor->type = IPAddressOrRange_addressRange; 480280304Sjkim OPENSSL_assert(aor->u.addressRange == NULL); 481280304Sjkim if ((aor->u.addressRange = IPAddressRange_new()) == NULL) 482280304Sjkim goto err; 483280304Sjkim if (aor->u.addressRange->min == NULL && 484280304Sjkim (aor->u.addressRange->min = ASN1_BIT_STRING_new()) == NULL) 485280304Sjkim goto err; 486280304Sjkim if (aor->u.addressRange->max == NULL && 487280304Sjkim (aor->u.addressRange->max = ASN1_BIT_STRING_new()) == NULL) 488280304Sjkim goto err; 489167612Ssimon 490280304Sjkim for (i = length; i > 0 && min[i - 1] == 0x00; --i) ; 491280304Sjkim if (!ASN1_BIT_STRING_set(aor->u.addressRange->min, min, i)) 492280304Sjkim goto err; 493280304Sjkim aor->u.addressRange->min->flags &= ~7; 494280304Sjkim aor->u.addressRange->min->flags |= ASN1_STRING_FLAG_BITS_LEFT; 495280304Sjkim if (i > 0) { 496280304Sjkim unsigned char b = min[i - 1]; 497280304Sjkim int j = 1; 498280304Sjkim while ((b & (0xFFU >> j)) != 0) 499280304Sjkim ++j; 500280304Sjkim aor->u.addressRange->min->flags |= 8 - j; 501280304Sjkim } 502167612Ssimon 503280304Sjkim for (i = length; i > 0 && max[i - 1] == 0xFF; --i) ; 504280304Sjkim if (!ASN1_BIT_STRING_set(aor->u.addressRange->max, max, i)) 505280304Sjkim goto err; 506280304Sjkim aor->u.addressRange->max->flags &= ~7; 507280304Sjkim aor->u.addressRange->max->flags |= ASN1_STRING_FLAG_BITS_LEFT; 508280304Sjkim if (i > 0) { 509280304Sjkim unsigned char b = max[i - 1]; 510280304Sjkim int j = 1; 511280304Sjkim while ((b & (0xFFU >> j)) != (0xFFU >> j)) 512280304Sjkim ++j; 513280304Sjkim aor->u.addressRange->max->flags |= 8 - j; 514280304Sjkim } 515167612Ssimon 516280304Sjkim *result = aor; 517280304Sjkim return 1; 518167612Ssimon 519167612Ssimon err: 520280304Sjkim IPAddressOrRange_free(aor); 521280304Sjkim return 0; 522167612Ssimon} 523167612Ssimon 524167612Ssimon/* 525167612Ssimon * Construct a new address family or find an existing one. 526167612Ssimon */ 527167612Ssimonstatic IPAddressFamily *make_IPAddressFamily(IPAddrBlocks *addr, 528280304Sjkim const unsigned afi, 529280304Sjkim const unsigned *safi) 530167612Ssimon{ 531280304Sjkim IPAddressFamily *f; 532280304Sjkim unsigned char key[3]; 533280304Sjkim unsigned keylen; 534280304Sjkim int i; 535167612Ssimon 536280304Sjkim key[0] = (afi >> 8) & 0xFF; 537280304Sjkim key[1] = afi & 0xFF; 538280304Sjkim if (safi != NULL) { 539280304Sjkim key[2] = *safi & 0xFF; 540280304Sjkim keylen = 3; 541280304Sjkim } else { 542280304Sjkim keylen = 2; 543280304Sjkim } 544167612Ssimon 545280304Sjkim for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { 546280304Sjkim f = sk_IPAddressFamily_value(addr, i); 547280304Sjkim OPENSSL_assert(f->addressFamily->data != NULL); 548280304Sjkim if (f->addressFamily->length == keylen && 549280304Sjkim !memcmp(f->addressFamily->data, key, keylen)) 550280304Sjkim return f; 551280304Sjkim } 552167612Ssimon 553280304Sjkim if ((f = IPAddressFamily_new()) == NULL) 554280304Sjkim goto err; 555280304Sjkim if (f->ipAddressChoice == NULL && 556280304Sjkim (f->ipAddressChoice = IPAddressChoice_new()) == NULL) 557280304Sjkim goto err; 558280304Sjkim if (f->addressFamily == NULL && 559280304Sjkim (f->addressFamily = ASN1_OCTET_STRING_new()) == NULL) 560280304Sjkim goto err; 561280304Sjkim if (!ASN1_OCTET_STRING_set(f->addressFamily, key, keylen)) 562280304Sjkim goto err; 563280304Sjkim if (!sk_IPAddressFamily_push(addr, f)) 564280304Sjkim goto err; 565167612Ssimon 566280304Sjkim return f; 567167612Ssimon 568167612Ssimon err: 569280304Sjkim IPAddressFamily_free(f); 570280304Sjkim return NULL; 571167612Ssimon} 572167612Ssimon 573167612Ssimon/* 574167612Ssimon * Add an inheritance element. 575167612Ssimon */ 576167612Ssimonint v3_addr_add_inherit(IPAddrBlocks *addr, 577280304Sjkim const unsigned afi, const unsigned *safi) 578167612Ssimon{ 579280304Sjkim IPAddressFamily *f = make_IPAddressFamily(addr, afi, safi); 580280304Sjkim if (f == NULL || 581280304Sjkim f->ipAddressChoice == NULL || 582280304Sjkim (f->ipAddressChoice->type == IPAddressChoice_addressesOrRanges && 583280304Sjkim f->ipAddressChoice->u.addressesOrRanges != NULL)) 584280304Sjkim return 0; 585280304Sjkim if (f->ipAddressChoice->type == IPAddressChoice_inherit && 586280304Sjkim f->ipAddressChoice->u.inherit != NULL) 587280304Sjkim return 1; 588280304Sjkim if (f->ipAddressChoice->u.inherit == NULL && 589280304Sjkim (f->ipAddressChoice->u.inherit = ASN1_NULL_new()) == NULL) 590280304Sjkim return 0; 591280304Sjkim f->ipAddressChoice->type = IPAddressChoice_inherit; 592167612Ssimon return 1; 593167612Ssimon} 594167612Ssimon 595167612Ssimon/* 596167612Ssimon * Construct an IPAddressOrRange sequence, or return an existing one. 597167612Ssimon */ 598167612Ssimonstatic IPAddressOrRanges *make_prefix_or_range(IPAddrBlocks *addr, 599280304Sjkim const unsigned afi, 600280304Sjkim const unsigned *safi) 601167612Ssimon{ 602280304Sjkim IPAddressFamily *f = make_IPAddressFamily(addr, afi, safi); 603280304Sjkim IPAddressOrRanges *aors = NULL; 604167612Ssimon 605280304Sjkim if (f == NULL || 606280304Sjkim f->ipAddressChoice == NULL || 607280304Sjkim (f->ipAddressChoice->type == IPAddressChoice_inherit && 608280304Sjkim f->ipAddressChoice->u.inherit != NULL)) 609280304Sjkim return NULL; 610280304Sjkim if (f->ipAddressChoice->type == IPAddressChoice_addressesOrRanges) 611280304Sjkim aors = f->ipAddressChoice->u.addressesOrRanges; 612280304Sjkim if (aors != NULL) 613280304Sjkim return aors; 614280304Sjkim if ((aors = sk_IPAddressOrRange_new_null()) == NULL) 615280304Sjkim return NULL; 616280304Sjkim switch (afi) { 617280304Sjkim case IANA_AFI_IPV4: 618280304Sjkim (void)sk_IPAddressOrRange_set_cmp_func(aors, v4IPAddressOrRange_cmp); 619280304Sjkim break; 620280304Sjkim case IANA_AFI_IPV6: 621280304Sjkim (void)sk_IPAddressOrRange_set_cmp_func(aors, v6IPAddressOrRange_cmp); 622280304Sjkim break; 623280304Sjkim } 624280304Sjkim f->ipAddressChoice->type = IPAddressChoice_addressesOrRanges; 625280304Sjkim f->ipAddressChoice->u.addressesOrRanges = aors; 626167612Ssimon return aors; 627167612Ssimon} 628167612Ssimon 629167612Ssimon/* 630167612Ssimon * Add a prefix. 631167612Ssimon */ 632167612Ssimonint v3_addr_add_prefix(IPAddrBlocks *addr, 633280304Sjkim const unsigned afi, 634280304Sjkim const unsigned *safi, 635280304Sjkim unsigned char *a, const int prefixlen) 636167612Ssimon{ 637280304Sjkim IPAddressOrRanges *aors = make_prefix_or_range(addr, afi, safi); 638280304Sjkim IPAddressOrRange *aor; 639280304Sjkim if (aors == NULL || !make_addressPrefix(&aor, a, prefixlen)) 640280304Sjkim return 0; 641280304Sjkim if (sk_IPAddressOrRange_push(aors, aor)) 642280304Sjkim return 1; 643280304Sjkim IPAddressOrRange_free(aor); 644167612Ssimon return 0; 645167612Ssimon} 646167612Ssimon 647167612Ssimon/* 648167612Ssimon * Add a range. 649167612Ssimon */ 650167612Ssimonint v3_addr_add_range(IPAddrBlocks *addr, 651280304Sjkim const unsigned afi, 652280304Sjkim const unsigned *safi, 653280304Sjkim unsigned char *min, unsigned char *max) 654167612Ssimon{ 655280304Sjkim IPAddressOrRanges *aors = make_prefix_or_range(addr, afi, safi); 656280304Sjkim IPAddressOrRange *aor; 657280304Sjkim int length = length_from_afi(afi); 658280304Sjkim if (aors == NULL) 659280304Sjkim return 0; 660280304Sjkim if (!make_addressRange(&aor, min, max, length)) 661280304Sjkim return 0; 662280304Sjkim if (sk_IPAddressOrRange_push(aors, aor)) 663280304Sjkim return 1; 664280304Sjkim IPAddressOrRange_free(aor); 665167612Ssimon return 0; 666167612Ssimon} 667167612Ssimon 668167612Ssimon/* 669167612Ssimon * Extract min and max values from an IPAddressOrRange. 670167612Ssimon */ 671237657Sjkimstatic int extract_min_max(IPAddressOrRange *aor, 672280304Sjkim unsigned char *min, unsigned char *max, int length) 673167612Ssimon{ 674280304Sjkim if (aor == NULL || min == NULL || max == NULL) 675280304Sjkim return 0; 676280304Sjkim switch (aor->type) { 677280304Sjkim case IPAddressOrRange_addressPrefix: 678280304Sjkim return (addr_expand(min, aor->u.addressPrefix, length, 0x00) && 679280304Sjkim addr_expand(max, aor->u.addressPrefix, length, 0xFF)); 680280304Sjkim case IPAddressOrRange_addressRange: 681280304Sjkim return (addr_expand(min, aor->u.addressRange->min, length, 0x00) && 682280304Sjkim addr_expand(max, aor->u.addressRange->max, length, 0xFF)); 683280304Sjkim } 684237657Sjkim return 0; 685167612Ssimon} 686167612Ssimon 687167612Ssimon/* 688167612Ssimon * Public wrapper for extract_min_max(). 689167612Ssimon */ 690167612Ssimonint v3_addr_get_range(IPAddressOrRange *aor, 691280304Sjkim const unsigned afi, 692280304Sjkim unsigned char *min, 693280304Sjkim unsigned char *max, const int length) 694167612Ssimon{ 695280304Sjkim int afi_length = length_from_afi(afi); 696280304Sjkim if (aor == NULL || min == NULL || max == NULL || 697280304Sjkim afi_length == 0 || length < afi_length || 698280304Sjkim (aor->type != IPAddressOrRange_addressPrefix && 699280304Sjkim aor->type != IPAddressOrRange_addressRange) || 700280304Sjkim !extract_min_max(aor, min, max, afi_length)) 701280304Sjkim return 0; 702237657Sjkim 703280304Sjkim return afi_length; 704167612Ssimon} 705167612Ssimon 706167612Ssimon/* 707167612Ssimon * Sort comparision function for a sequence of IPAddressFamily. 708167612Ssimon * 709167612Ssimon * The last paragraph of RFC 3779 2.2.3.3 is slightly ambiguous about 710167612Ssimon * the ordering: I can read it as meaning that IPv6 without a SAFI 711167612Ssimon * comes before IPv4 with a SAFI, which seems pretty weird. The 712167612Ssimon * examples in appendix B suggest that the author intended the 713167612Ssimon * null-SAFI rule to apply only within a single AFI, which is what I 714167612Ssimon * would have expected and is what the following code implements. 715167612Ssimon */ 716280304Sjkimstatic int IPAddressFamily_cmp(const IPAddressFamily *const *a_, 717280304Sjkim const IPAddressFamily *const *b_) 718167612Ssimon{ 719280304Sjkim const ASN1_OCTET_STRING *a = (*a_)->addressFamily; 720280304Sjkim const ASN1_OCTET_STRING *b = (*b_)->addressFamily; 721280304Sjkim int len = ((a->length <= b->length) ? a->length : b->length); 722280304Sjkim int cmp = memcmp(a->data, b->data, len); 723280304Sjkim return cmp ? cmp : a->length - b->length; 724167612Ssimon} 725167612Ssimon 726167612Ssimon/* 727167612Ssimon * Check whether an IPAddrBLocks is in canonical form. 728167612Ssimon */ 729167612Ssimonint v3_addr_is_canonical(IPAddrBlocks *addr) 730167612Ssimon{ 731280304Sjkim unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; 732280304Sjkim unsigned char b_min[ADDR_RAW_BUF_LEN], b_max[ADDR_RAW_BUF_LEN]; 733280304Sjkim IPAddressOrRanges *aors; 734280304Sjkim int i, j, k; 735167612Ssimon 736280304Sjkim /* 737280304Sjkim * Empty extension is cannonical. 738280304Sjkim */ 739280304Sjkim if (addr == NULL) 740280304Sjkim return 1; 741167612Ssimon 742167612Ssimon /* 743280304Sjkim * Check whether the top-level list is in order. 744167612Ssimon */ 745280304Sjkim for (i = 0; i < sk_IPAddressFamily_num(addr) - 1; i++) { 746280304Sjkim const IPAddressFamily *a = sk_IPAddressFamily_value(addr, i); 747280304Sjkim const IPAddressFamily *b = sk_IPAddressFamily_value(addr, i + 1); 748280304Sjkim if (IPAddressFamily_cmp(&a, &b) >= 0) 749280304Sjkim return 0; 750167612Ssimon } 751167612Ssimon 752167612Ssimon /* 753280304Sjkim * Top level's ok, now check each address family. 754167612Ssimon */ 755280304Sjkim for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { 756280304Sjkim IPAddressFamily *f = sk_IPAddressFamily_value(addr, i); 757280304Sjkim int length = length_from_afi(v3_addr_get_afi(f)); 758167612Ssimon 759280304Sjkim /* 760280304Sjkim * Inheritance is canonical. Anything other than inheritance or 761280304Sjkim * a SEQUENCE OF IPAddressOrRange is an ASN.1 error or something. 762280304Sjkim */ 763280304Sjkim if (f == NULL || f->ipAddressChoice == NULL) 764280304Sjkim return 0; 765280304Sjkim switch (f->ipAddressChoice->type) { 766280304Sjkim case IPAddressChoice_inherit: 767280304Sjkim continue; 768280304Sjkim case IPAddressChoice_addressesOrRanges: 769280304Sjkim break; 770280304Sjkim default: 771280304Sjkim return 0; 772280304Sjkim } 773167612Ssimon 774280304Sjkim /* 775280304Sjkim * It's an IPAddressOrRanges sequence, check it. 776280304Sjkim */ 777280304Sjkim aors = f->ipAddressChoice->u.addressesOrRanges; 778280304Sjkim if (sk_IPAddressOrRange_num(aors) == 0) 779280304Sjkim return 0; 780280304Sjkim for (j = 0; j < sk_IPAddressOrRange_num(aors) - 1; j++) { 781280304Sjkim IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); 782280304Sjkim IPAddressOrRange *b = sk_IPAddressOrRange_value(aors, j + 1); 783167612Ssimon 784280304Sjkim if (!extract_min_max(a, a_min, a_max, length) || 785280304Sjkim !extract_min_max(b, b_min, b_max, length)) 786280304Sjkim return 0; 787167612Ssimon 788280304Sjkim /* 789280304Sjkim * Punt misordered list, overlapping start, or inverted range. 790280304Sjkim */ 791280304Sjkim if (memcmp(a_min, b_min, length) >= 0 || 792280304Sjkim memcmp(a_min, a_max, length) > 0 || 793280304Sjkim memcmp(b_min, b_max, length) > 0) 794280304Sjkim return 0; 795280304Sjkim 796280304Sjkim /* 797280304Sjkim * Punt if adjacent or overlapping. Check for adjacency by 798280304Sjkim * subtracting one from b_min first. 799280304Sjkim */ 800280304Sjkim for (k = length - 1; k >= 0 && b_min[k]-- == 0x00; k--) ; 801280304Sjkim if (memcmp(a_max, b_min, length) >= 0) 802280304Sjkim return 0; 803280304Sjkim 804280304Sjkim /* 805280304Sjkim * Check for range that should be expressed as a prefix. 806280304Sjkim */ 807280304Sjkim if (a->type == IPAddressOrRange_addressRange && 808280304Sjkim range_should_be_prefix(a_min, a_max, length) >= 0) 809280304Sjkim return 0; 810280304Sjkim } 811280304Sjkim 812280304Sjkim /* 813280304Sjkim * Check range to see if it's inverted or should be a 814280304Sjkim * prefix. 815280304Sjkim */ 816280304Sjkim j = sk_IPAddressOrRange_num(aors) - 1; 817280304Sjkim { 818280304Sjkim IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); 819280304Sjkim if (a != NULL && a->type == IPAddressOrRange_addressRange) { 820280304Sjkim if (!extract_min_max(a, a_min, a_max, length)) 821280304Sjkim return 0; 822280304Sjkim if (memcmp(a_min, a_max, length) > 0 || 823280304Sjkim range_should_be_prefix(a_min, a_max, length) >= 0) 824280304Sjkim return 0; 825280304Sjkim } 826280304Sjkim } 827167612Ssimon } 828167612Ssimon 829167612Ssimon /* 830280304Sjkim * If we made it through all that, we're happy. 831167612Ssimon */ 832280304Sjkim return 1; 833167612Ssimon} 834167612Ssimon 835167612Ssimon/* 836167612Ssimon * Whack an IPAddressOrRanges into canonical form. 837167612Ssimon */ 838167612Ssimonstatic int IPAddressOrRanges_canonize(IPAddressOrRanges *aors, 839280304Sjkim const unsigned afi) 840167612Ssimon{ 841280304Sjkim int i, j, length = length_from_afi(afi); 842167612Ssimon 843167612Ssimon /* 844280304Sjkim * Sort the IPAddressOrRanges sequence. 845237657Sjkim */ 846280304Sjkim sk_IPAddressOrRange_sort(aors); 847237657Sjkim 848237657Sjkim /* 849280304Sjkim * Clean up representation issues, punt on duplicates or overlaps. 850167612Ssimon */ 851280304Sjkim for (i = 0; i < sk_IPAddressOrRange_num(aors) - 1; i++) { 852280304Sjkim IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, i); 853280304Sjkim IPAddressOrRange *b = sk_IPAddressOrRange_value(aors, i + 1); 854280304Sjkim unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; 855280304Sjkim unsigned char b_min[ADDR_RAW_BUF_LEN], b_max[ADDR_RAW_BUF_LEN]; 856167612Ssimon 857280304Sjkim if (!extract_min_max(a, a_min, a_max, length) || 858280304Sjkim !extract_min_max(b, b_min, b_max, length)) 859280304Sjkim return 0; 860280304Sjkim 861280304Sjkim /* 862280304Sjkim * Punt inverted ranges. 863280304Sjkim */ 864280304Sjkim if (memcmp(a_min, a_max, length) > 0 || 865280304Sjkim memcmp(b_min, b_max, length) > 0) 866280304Sjkim return 0; 867280304Sjkim 868280304Sjkim /* 869280304Sjkim * Punt overlaps. 870280304Sjkim */ 871280304Sjkim if (memcmp(a_max, b_min, length) >= 0) 872280304Sjkim return 0; 873280304Sjkim 874280304Sjkim /* 875280304Sjkim * Merge if a and b are adjacent. We check for 876280304Sjkim * adjacency by subtracting one from b_min first. 877280304Sjkim */ 878280304Sjkim for (j = length - 1; j >= 0 && b_min[j]-- == 0x00; j--) ; 879280304Sjkim if (memcmp(a_max, b_min, length) == 0) { 880280304Sjkim IPAddressOrRange *merged; 881280304Sjkim if (!make_addressRange(&merged, a_min, b_max, length)) 882280304Sjkim return 0; 883280304Sjkim (void)sk_IPAddressOrRange_set(aors, i, merged); 884280304Sjkim (void)sk_IPAddressOrRange_delete(aors, i + 1); 885280304Sjkim IPAddressOrRange_free(a); 886280304Sjkim IPAddressOrRange_free(b); 887280304Sjkim --i; 888280304Sjkim continue; 889280304Sjkim } 890280304Sjkim } 891280304Sjkim 892167612Ssimon /* 893280304Sjkim * Check for inverted final range. 894167612Ssimon */ 895280304Sjkim j = sk_IPAddressOrRange_num(aors) - 1; 896280304Sjkim { 897280304Sjkim IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); 898280304Sjkim if (a != NULL && a->type == IPAddressOrRange_addressRange) { 899280304Sjkim unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; 900280304Sjkim extract_min_max(a, a_min, a_max, length); 901280304Sjkim if (memcmp(a_min, a_max, length) > 0) 902280304Sjkim return 0; 903280304Sjkim } 904167612Ssimon } 905167612Ssimon 906280304Sjkim return 1; 907167612Ssimon} 908167612Ssimon 909167612Ssimon/* 910167612Ssimon * Whack an IPAddrBlocks extension into canonical form. 911167612Ssimon */ 912167612Ssimonint v3_addr_canonize(IPAddrBlocks *addr) 913167612Ssimon{ 914280304Sjkim int i; 915280304Sjkim for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { 916280304Sjkim IPAddressFamily *f = sk_IPAddressFamily_value(addr, i); 917280304Sjkim if (f->ipAddressChoice->type == IPAddressChoice_addressesOrRanges && 918280304Sjkim !IPAddressOrRanges_canonize(f->ipAddressChoice-> 919280304Sjkim u.addressesOrRanges, 920280304Sjkim v3_addr_get_afi(f))) 921280304Sjkim return 0; 922280304Sjkim } 923280304Sjkim (void)sk_IPAddressFamily_set_cmp_func(addr, IPAddressFamily_cmp); 924280304Sjkim sk_IPAddressFamily_sort(addr); 925280304Sjkim OPENSSL_assert(v3_addr_is_canonical(addr)); 926280304Sjkim return 1; 927167612Ssimon} 928167612Ssimon 929167612Ssimon/* 930167612Ssimon * v2i handler for the IPAddrBlocks extension. 931167612Ssimon */ 932238405Sjkimstatic void *v2i_IPAddrBlocks(const struct v3_ext_method *method, 933280304Sjkim struct v3_ext_ctx *ctx, 934280304Sjkim STACK_OF(CONF_VALUE) *values) 935167612Ssimon{ 936280304Sjkim static const char v4addr_chars[] = "0123456789."; 937280304Sjkim static const char v6addr_chars[] = "0123456789.:abcdefABCDEF"; 938280304Sjkim IPAddrBlocks *addr = NULL; 939280304Sjkim char *s = NULL, *t; 940280304Sjkim int i; 941167612Ssimon 942280304Sjkim if ((addr = sk_IPAddressFamily_new(IPAddressFamily_cmp)) == NULL) { 943280304Sjkim X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE); 944280304Sjkim return NULL; 945167612Ssimon } 946167612Ssimon 947280304Sjkim for (i = 0; i < sk_CONF_VALUE_num(values); i++) { 948280304Sjkim CONF_VALUE *val = sk_CONF_VALUE_value(values, i); 949280304Sjkim unsigned char min[ADDR_RAW_BUF_LEN], max[ADDR_RAW_BUF_LEN]; 950280304Sjkim unsigned afi, *safi = NULL, safi_; 951280304Sjkim const char *addr_chars; 952280304Sjkim int prefixlen, i1, i2, delim, length; 953167612Ssimon 954280304Sjkim if (!name_cmp(val->name, "IPv4")) { 955280304Sjkim afi = IANA_AFI_IPV4; 956280304Sjkim } else if (!name_cmp(val->name, "IPv6")) { 957280304Sjkim afi = IANA_AFI_IPV6; 958280304Sjkim } else if (!name_cmp(val->name, "IPv4-SAFI")) { 959280304Sjkim afi = IANA_AFI_IPV4; 960280304Sjkim safi = &safi_; 961280304Sjkim } else if (!name_cmp(val->name, "IPv6-SAFI")) { 962280304Sjkim afi = IANA_AFI_IPV6; 963280304Sjkim safi = &safi_; 964280304Sjkim } else { 965280304Sjkim X509V3err(X509V3_F_V2I_IPADDRBLOCKS, 966280304Sjkim X509V3_R_EXTENSION_NAME_ERROR); 967280304Sjkim X509V3_conf_err(val); 968280304Sjkim goto err; 969280304Sjkim } 970167612Ssimon 971280304Sjkim switch (afi) { 972280304Sjkim case IANA_AFI_IPV4: 973280304Sjkim addr_chars = v4addr_chars; 974280304Sjkim break; 975280304Sjkim case IANA_AFI_IPV6: 976280304Sjkim addr_chars = v6addr_chars; 977280304Sjkim break; 978280304Sjkim } 979167612Ssimon 980280304Sjkim length = length_from_afi(afi); 981167612Ssimon 982280304Sjkim /* 983280304Sjkim * Handle SAFI, if any, and BUF_strdup() so we can null-terminate 984280304Sjkim * the other input values. 985280304Sjkim */ 986280304Sjkim if (safi != NULL) { 987280304Sjkim *safi = strtoul(val->value, &t, 0); 988280304Sjkim t += strspn(t, " \t"); 989280304Sjkim if (*safi > 0xFF || *t++ != ':') { 990280304Sjkim X509V3err(X509V3_F_V2I_IPADDRBLOCKS, X509V3_R_INVALID_SAFI); 991280304Sjkim X509V3_conf_err(val); 992280304Sjkim goto err; 993280304Sjkim } 994280304Sjkim t += strspn(t, " \t"); 995280304Sjkim s = BUF_strdup(t); 996280304Sjkim } else { 997280304Sjkim s = BUF_strdup(val->value); 998280304Sjkim } 999280304Sjkim if (s == NULL) { 1000280304Sjkim X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE); 1001280304Sjkim goto err; 1002280304Sjkim } 1003167612Ssimon 1004280304Sjkim /* 1005280304Sjkim * Check for inheritance. Not worth additional complexity to 1006280304Sjkim * optimize this (seldom-used) case. 1007280304Sjkim */ 1008280304Sjkim if (!strcmp(s, "inherit")) { 1009280304Sjkim if (!v3_addr_add_inherit(addr, afi, safi)) { 1010280304Sjkim X509V3err(X509V3_F_V2I_IPADDRBLOCKS, 1011280304Sjkim X509V3_R_INVALID_INHERITANCE); 1012280304Sjkim X509V3_conf_err(val); 1013280304Sjkim goto err; 1014280304Sjkim } 1015280304Sjkim OPENSSL_free(s); 1016280304Sjkim s = NULL; 1017280304Sjkim continue; 1018280304Sjkim } 1019167612Ssimon 1020280304Sjkim i1 = strspn(s, addr_chars); 1021280304Sjkim i2 = i1 + strspn(s + i1, " \t"); 1022280304Sjkim delim = s[i2++]; 1023280304Sjkim s[i1] = '\0'; 1024280304Sjkim 1025280304Sjkim if (a2i_ipadd(min, s) != length) { 1026280304Sjkim X509V3err(X509V3_F_V2I_IPADDRBLOCKS, X509V3_R_INVALID_IPADDRESS); 1027280304Sjkim X509V3_conf_err(val); 1028280304Sjkim goto err; 1029280304Sjkim } 1030280304Sjkim 1031280304Sjkim switch (delim) { 1032280304Sjkim case '/': 1033280304Sjkim prefixlen = (int)strtoul(s + i2, &t, 10); 1034280304Sjkim if (t == s + i2 || *t != '\0') { 1035280304Sjkim X509V3err(X509V3_F_V2I_IPADDRBLOCKS, 1036280304Sjkim X509V3_R_EXTENSION_VALUE_ERROR); 1037280304Sjkim X509V3_conf_err(val); 1038280304Sjkim goto err; 1039280304Sjkim } 1040280304Sjkim if (!v3_addr_add_prefix(addr, afi, safi, min, prefixlen)) { 1041280304Sjkim X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE); 1042280304Sjkim goto err; 1043280304Sjkim } 1044280304Sjkim break; 1045280304Sjkim case '-': 1046280304Sjkim i1 = i2 + strspn(s + i2, " \t"); 1047280304Sjkim i2 = i1 + strspn(s + i1, addr_chars); 1048280304Sjkim if (i1 == i2 || s[i2] != '\0') { 1049280304Sjkim X509V3err(X509V3_F_V2I_IPADDRBLOCKS, 1050280304Sjkim X509V3_R_EXTENSION_VALUE_ERROR); 1051280304Sjkim X509V3_conf_err(val); 1052280304Sjkim goto err; 1053280304Sjkim } 1054280304Sjkim if (a2i_ipadd(max, s + i1) != length) { 1055280304Sjkim X509V3err(X509V3_F_V2I_IPADDRBLOCKS, 1056280304Sjkim X509V3_R_INVALID_IPADDRESS); 1057280304Sjkim X509V3_conf_err(val); 1058280304Sjkim goto err; 1059280304Sjkim } 1060280304Sjkim if (memcmp(min, max, length_from_afi(afi)) > 0) { 1061280304Sjkim X509V3err(X509V3_F_V2I_IPADDRBLOCKS, 1062280304Sjkim X509V3_R_EXTENSION_VALUE_ERROR); 1063280304Sjkim X509V3_conf_err(val); 1064280304Sjkim goto err; 1065280304Sjkim } 1066280304Sjkim if (!v3_addr_add_range(addr, afi, safi, min, max)) { 1067280304Sjkim X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE); 1068280304Sjkim goto err; 1069280304Sjkim } 1070280304Sjkim break; 1071280304Sjkim case '\0': 1072280304Sjkim if (!v3_addr_add_prefix(addr, afi, safi, min, length * 8)) { 1073280304Sjkim X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE); 1074280304Sjkim goto err; 1075280304Sjkim } 1076280304Sjkim break; 1077280304Sjkim default: 1078280304Sjkim X509V3err(X509V3_F_V2I_IPADDRBLOCKS, 1079280304Sjkim X509V3_R_EXTENSION_VALUE_ERROR); 1080280304Sjkim X509V3_conf_err(val); 1081280304Sjkim goto err; 1082280304Sjkim } 1083280304Sjkim 1084280304Sjkim OPENSSL_free(s); 1085280304Sjkim s = NULL; 1086167612Ssimon } 1087167612Ssimon 1088280304Sjkim /* 1089280304Sjkim * Canonize the result, then we're done. 1090280304Sjkim */ 1091280304Sjkim if (!v3_addr_canonize(addr)) 1092280304Sjkim goto err; 1093280304Sjkim return addr; 1094167612Ssimon 1095167612Ssimon err: 1096280304Sjkim OPENSSL_free(s); 1097280304Sjkim sk_IPAddressFamily_pop_free(addr, IPAddressFamily_free); 1098280304Sjkim return NULL; 1099167612Ssimon} 1100167612Ssimon 1101167612Ssimon/* 1102167612Ssimon * OpenSSL dispatch 1103167612Ssimon */ 1104167612Ssimonconst X509V3_EXT_METHOD v3_addr = { 1105280304Sjkim NID_sbgp_ipAddrBlock, /* nid */ 1106280304Sjkim 0, /* flags */ 1107280304Sjkim ASN1_ITEM_ref(IPAddrBlocks), /* template */ 1108280304Sjkim 0, 0, 0, 0, /* old functions, ignored */ 1109280304Sjkim 0, /* i2s */ 1110280304Sjkim 0, /* s2i */ 1111280304Sjkim 0, /* i2v */ 1112280304Sjkim v2i_IPAddrBlocks, /* v2i */ 1113280304Sjkim i2r_IPAddrBlocks, /* i2r */ 1114280304Sjkim 0, /* r2i */ 1115280304Sjkim NULL /* extension-specific data */ 1116167612Ssimon}; 1117167612Ssimon 1118167612Ssimon/* 1119167612Ssimon * Figure out whether extension sues inheritance. 1120167612Ssimon */ 1121167612Ssimonint v3_addr_inherits(IPAddrBlocks *addr) 1122167612Ssimon{ 1123280304Sjkim int i; 1124280304Sjkim if (addr == NULL) 1125280304Sjkim return 0; 1126280304Sjkim for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { 1127280304Sjkim IPAddressFamily *f = sk_IPAddressFamily_value(addr, i); 1128280304Sjkim if (f->ipAddressChoice->type == IPAddressChoice_inherit) 1129280304Sjkim return 1; 1130280304Sjkim } 1131167612Ssimon return 0; 1132167612Ssimon} 1133167612Ssimon 1134167612Ssimon/* 1135167612Ssimon * Figure out whether parent contains child. 1136167612Ssimon */ 1137167612Ssimonstatic int addr_contains(IPAddressOrRanges *parent, 1138280304Sjkim IPAddressOrRanges *child, int length) 1139167612Ssimon{ 1140280304Sjkim unsigned char p_min[ADDR_RAW_BUF_LEN], p_max[ADDR_RAW_BUF_LEN]; 1141280304Sjkim unsigned char c_min[ADDR_RAW_BUF_LEN], c_max[ADDR_RAW_BUF_LEN]; 1142280304Sjkim int p, c; 1143167612Ssimon 1144280304Sjkim if (child == NULL || parent == child) 1145280304Sjkim return 1; 1146280304Sjkim if (parent == NULL) 1147280304Sjkim return 0; 1148167612Ssimon 1149280304Sjkim p = 0; 1150280304Sjkim for (c = 0; c < sk_IPAddressOrRange_num(child); c++) { 1151280304Sjkim if (!extract_min_max(sk_IPAddressOrRange_value(child, c), 1152280304Sjkim c_min, c_max, length)) 1153280304Sjkim return -1; 1154280304Sjkim for (;; p++) { 1155280304Sjkim if (p >= sk_IPAddressOrRange_num(parent)) 1156280304Sjkim return 0; 1157280304Sjkim if (!extract_min_max(sk_IPAddressOrRange_value(parent, p), 1158280304Sjkim p_min, p_max, length)) 1159280304Sjkim return 0; 1160280304Sjkim if (memcmp(p_max, c_max, length) < 0) 1161280304Sjkim continue; 1162280304Sjkim if (memcmp(p_min, c_min, length) > 0) 1163280304Sjkim return 0; 1164280304Sjkim break; 1165280304Sjkim } 1166167612Ssimon } 1167167612Ssimon 1168280304Sjkim return 1; 1169167612Ssimon} 1170167612Ssimon 1171167612Ssimon/* 1172167612Ssimon * Test whether a is a subset of b. 1173167612Ssimon */ 1174167612Ssimonint v3_addr_subset(IPAddrBlocks *a, IPAddrBlocks *b) 1175167612Ssimon{ 1176280304Sjkim int i; 1177280304Sjkim if (a == NULL || a == b) 1178280304Sjkim return 1; 1179280304Sjkim if (b == NULL || v3_addr_inherits(a) || v3_addr_inherits(b)) 1180280304Sjkim return 0; 1181280304Sjkim (void)sk_IPAddressFamily_set_cmp_func(b, IPAddressFamily_cmp); 1182280304Sjkim for (i = 0; i < sk_IPAddressFamily_num(a); i++) { 1183280304Sjkim IPAddressFamily *fa = sk_IPAddressFamily_value(a, i); 1184280304Sjkim int j = sk_IPAddressFamily_find(b, fa); 1185280304Sjkim IPAddressFamily *fb; 1186280304Sjkim fb = sk_IPAddressFamily_value(b, j); 1187280304Sjkim if (fb == NULL) 1188280304Sjkim return 0; 1189280304Sjkim if (!addr_contains(fb->ipAddressChoice->u.addressesOrRanges, 1190280304Sjkim fa->ipAddressChoice->u.addressesOrRanges, 1191280304Sjkim length_from_afi(v3_addr_get_afi(fb)))) 1192280304Sjkim return 0; 1193280304Sjkim } 1194167612Ssimon return 1; 1195167612Ssimon} 1196167612Ssimon 1197167612Ssimon/* 1198167612Ssimon * Validation error handling via callback. 1199167612Ssimon */ 1200280304Sjkim# define validation_err(_err_) \ 1201280304Sjkim do { \ 1202280304Sjkim if (ctx != NULL) { \ 1203280304Sjkim ctx->error = _err_; \ 1204280304Sjkim ctx->error_depth = i; \ 1205280304Sjkim ctx->current_cert = x; \ 1206280304Sjkim ret = ctx->verify_cb(0, ctx); \ 1207280304Sjkim } else { \ 1208280304Sjkim ret = 0; \ 1209280304Sjkim } \ 1210280304Sjkim if (!ret) \ 1211280304Sjkim goto done; \ 1212167612Ssimon } while (0) 1213167612Ssimon 1214167612Ssimon/* 1215167612Ssimon * Core code for RFC 3779 2.3 path validation. 1216167612Ssimon */ 1217167612Ssimonstatic int v3_addr_validate_path_internal(X509_STORE_CTX *ctx, 1218280304Sjkim STACK_OF(X509) *chain, 1219280304Sjkim IPAddrBlocks *ext) 1220167612Ssimon{ 1221280304Sjkim IPAddrBlocks *child = NULL; 1222280304Sjkim int i, j, ret = 1; 1223280304Sjkim X509 *x; 1224167612Ssimon 1225280304Sjkim OPENSSL_assert(chain != NULL && sk_X509_num(chain) > 0); 1226280304Sjkim OPENSSL_assert(ctx != NULL || ext != NULL); 1227280304Sjkim OPENSSL_assert(ctx == NULL || ctx->verify_cb != NULL); 1228167612Ssimon 1229280304Sjkim /* 1230280304Sjkim * Figure out where to start. If we don't have an extension to 1231280304Sjkim * check, we're done. Otherwise, check canonical form and 1232280304Sjkim * set up for walking up the chain. 1233280304Sjkim */ 1234280304Sjkim if (ext != NULL) { 1235280304Sjkim i = -1; 1236280304Sjkim x = NULL; 1237280304Sjkim } else { 1238280304Sjkim i = 0; 1239280304Sjkim x = sk_X509_value(chain, i); 1240280304Sjkim OPENSSL_assert(x != NULL); 1241280304Sjkim if ((ext = x->rfc3779_addr) == NULL) 1242280304Sjkim goto done; 1243167612Ssimon } 1244280304Sjkim if (!v3_addr_is_canonical(ext)) 1245280304Sjkim validation_err(X509_V_ERR_INVALID_EXTENSION); 1246280304Sjkim (void)sk_IPAddressFamily_set_cmp_func(ext, IPAddressFamily_cmp); 1247280304Sjkim if ((child = sk_IPAddressFamily_dup(ext)) == NULL) { 1248280304Sjkim X509V3err(X509V3_F_V3_ADDR_VALIDATE_PATH_INTERNAL, 1249280304Sjkim ERR_R_MALLOC_FAILURE); 1250280304Sjkim ret = 0; 1251280304Sjkim goto done; 1252167612Ssimon } 1253167612Ssimon 1254280304Sjkim /* 1255280304Sjkim * Now walk up the chain. No cert may list resources that its 1256280304Sjkim * parent doesn't list. 1257280304Sjkim */ 1258280304Sjkim for (i++; i < sk_X509_num(chain); i++) { 1259280304Sjkim x = sk_X509_value(chain, i); 1260280304Sjkim OPENSSL_assert(x != NULL); 1261280304Sjkim if (!v3_addr_is_canonical(x->rfc3779_addr)) 1262280304Sjkim validation_err(X509_V_ERR_INVALID_EXTENSION); 1263280304Sjkim if (x->rfc3779_addr == NULL) { 1264280304Sjkim for (j = 0; j < sk_IPAddressFamily_num(child); j++) { 1265280304Sjkim IPAddressFamily *fc = sk_IPAddressFamily_value(child, j); 1266280304Sjkim if (fc->ipAddressChoice->type != IPAddressChoice_inherit) { 1267280304Sjkim validation_err(X509_V_ERR_UNNESTED_RESOURCE); 1268280304Sjkim break; 1269280304Sjkim } 1270280304Sjkim } 1271280304Sjkim continue; 1272280304Sjkim } 1273280304Sjkim (void)sk_IPAddressFamily_set_cmp_func(x->rfc3779_addr, 1274280304Sjkim IPAddressFamily_cmp); 1275280304Sjkim for (j = 0; j < sk_IPAddressFamily_num(child); j++) { 1276280304Sjkim IPAddressFamily *fc = sk_IPAddressFamily_value(child, j); 1277280304Sjkim int k = sk_IPAddressFamily_find(x->rfc3779_addr, fc); 1278280304Sjkim IPAddressFamily *fp = 1279280304Sjkim sk_IPAddressFamily_value(x->rfc3779_addr, k); 1280280304Sjkim if (fp == NULL) { 1281280304Sjkim if (fc->ipAddressChoice->type == 1282280304Sjkim IPAddressChoice_addressesOrRanges) { 1283280304Sjkim validation_err(X509_V_ERR_UNNESTED_RESOURCE); 1284280304Sjkim break; 1285280304Sjkim } 1286280304Sjkim continue; 1287280304Sjkim } 1288280304Sjkim if (fp->ipAddressChoice->type == 1289280304Sjkim IPAddressChoice_addressesOrRanges) { 1290280304Sjkim if (fc->ipAddressChoice->type == IPAddressChoice_inherit 1291280304Sjkim || addr_contains(fp->ipAddressChoice->u.addressesOrRanges, 1292280304Sjkim fc->ipAddressChoice->u.addressesOrRanges, 1293280304Sjkim length_from_afi(v3_addr_get_afi(fc)))) 1294280304Sjkim sk_IPAddressFamily_set(child, j, fp); 1295280304Sjkim else 1296280304Sjkim validation_err(X509_V_ERR_UNNESTED_RESOURCE); 1297280304Sjkim } 1298280304Sjkim } 1299167612Ssimon } 1300167612Ssimon 1301280304Sjkim /* 1302280304Sjkim * Trust anchor can't inherit. 1303280304Sjkim */ 1304280304Sjkim OPENSSL_assert(x != NULL); 1305280304Sjkim if (x->rfc3779_addr != NULL) { 1306280304Sjkim for (j = 0; j < sk_IPAddressFamily_num(x->rfc3779_addr); j++) { 1307280304Sjkim IPAddressFamily *fp = 1308280304Sjkim sk_IPAddressFamily_value(x->rfc3779_addr, j); 1309280304Sjkim if (fp->ipAddressChoice->type == IPAddressChoice_inherit 1310280304Sjkim && sk_IPAddressFamily_find(child, fp) >= 0) 1311280304Sjkim validation_err(X509_V_ERR_UNNESTED_RESOURCE); 1312280304Sjkim } 1313280304Sjkim } 1314280304Sjkim 1315167612Ssimon done: 1316280304Sjkim sk_IPAddressFamily_free(child); 1317280304Sjkim return ret; 1318167612Ssimon} 1319167612Ssimon 1320280304Sjkim# undef validation_err 1321167612Ssimon 1322167612Ssimon/* 1323167612Ssimon * RFC 3779 2.3 path validation -- called from X509_verify_cert(). 1324167612Ssimon */ 1325167612Ssimonint v3_addr_validate_path(X509_STORE_CTX *ctx) 1326167612Ssimon{ 1327280304Sjkim return v3_addr_validate_path_internal(ctx, ctx->chain, NULL); 1328167612Ssimon} 1329167612Ssimon 1330167612Ssimon/* 1331167612Ssimon * RFC 3779 2.3 path validation of an extension. 1332167612Ssimon * Test whether chain covers extension. 1333167612Ssimon */ 1334167612Ssimonint v3_addr_validate_resource_set(STACK_OF(X509) *chain, 1335280304Sjkim IPAddrBlocks *ext, int allow_inheritance) 1336167612Ssimon{ 1337280304Sjkim if (ext == NULL) 1338280304Sjkim return 1; 1339280304Sjkim if (chain == NULL || sk_X509_num(chain) == 0) 1340280304Sjkim return 0; 1341280304Sjkim if (!allow_inheritance && v3_addr_inherits(ext)) 1342280304Sjkim return 0; 1343280304Sjkim return v3_addr_validate_path_internal(NULL, chain, ext); 1344167612Ssimon} 1345167612Ssimon 1346280304Sjkim#endif /* OPENSSL_NO_RFC3779 */ 1347