1656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
2656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Contributed to the OpenSSL Project by the American Registry for
3656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Internet Numbers ("ARIN").
4656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
5656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/* ====================================================================
6656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
7656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
8656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Redistribution and use in source and binary forms, with or without
9656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * modification, are permitted provided that the following conditions
10656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * are met:
11656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
12656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 1. Redistributions of source code must retain the above copyright
13656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    notice, this list of conditions and the following disclaimer.
14656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
15656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
16656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    notice, this list of conditions and the following disclaimer in
17656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    the documentation and/or other materials provided with the
18656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    distribution.
19656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
20656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 3. All advertising materials mentioning features or use of this
21656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    software must display the following acknowledgment:
22656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    "This product includes software developed by the OpenSSL Project
23656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
25656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    endorse or promote products derived from this software without
27656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    prior written permission. For written permission, please contact
28656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    licensing@OpenSSL.org.
29656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
30656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 5. Products derived from this software may not be called "OpenSSL"
31656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    nor may "OpenSSL" appear in their names without prior written
32656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    permission of the OpenSSL Project.
33656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
34656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 6. Redistributions of any form whatsoever must retain the following
35656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    acknowledgment:
36656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    "This product includes software developed by the OpenSSL Project
37656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
39656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * OF THE POSSIBILITY OF SUCH DAMAGE.
51656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * ====================================================================
52656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
53656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * This product includes cryptographic software written by Eric Young
54656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * (eay@cryptsoft.com).  This product includes software written by Tim
55656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Hudson (tjh@cryptsoft.com).
56656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
57656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
58656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
59656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Implementation of RFC 3779 section 2.2.
60656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
61656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
62656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include <stdio.h>
63656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include <stdlib.h>
64e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
65656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include "cryptlib.h"
66656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include <openssl/conf.h>
67656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include <openssl/asn1.h>
68656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include <openssl/asn1t.h>
69656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include <openssl/buffer.h>
70656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include <openssl/x509v3.h>
71656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
72656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#ifndef OPENSSL_NO_RFC3779
73656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
74656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
75656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * OpenSSL ASN.1 template translation of RFC 3779 2.2.3.
76656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
77656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
78656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source ProjectASN1_SEQUENCE(IPAddressRange) = {
79656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  ASN1_SIMPLE(IPAddressRange, min, ASN1_BIT_STRING),
80656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  ASN1_SIMPLE(IPAddressRange, max, ASN1_BIT_STRING)
81656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} ASN1_SEQUENCE_END(IPAddressRange)
82656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
83656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source ProjectASN1_CHOICE(IPAddressOrRange) = {
84656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  ASN1_SIMPLE(IPAddressOrRange, u.addressPrefix, ASN1_BIT_STRING),
85656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  ASN1_SIMPLE(IPAddressOrRange, u.addressRange,  IPAddressRange)
86656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} ASN1_CHOICE_END(IPAddressOrRange)
87656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
88656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source ProjectASN1_CHOICE(IPAddressChoice) = {
89656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  ASN1_SIMPLE(IPAddressChoice,      u.inherit,           ASN1_NULL),
90656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  ASN1_SEQUENCE_OF(IPAddressChoice, u.addressesOrRanges, IPAddressOrRange)
91656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} ASN1_CHOICE_END(IPAddressChoice)
92656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
93656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source ProjectASN1_SEQUENCE(IPAddressFamily) = {
94656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  ASN1_SIMPLE(IPAddressFamily, addressFamily,   ASN1_OCTET_STRING),
95656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  ASN1_SIMPLE(IPAddressFamily, ipAddressChoice, IPAddressChoice)
96656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project} ASN1_SEQUENCE_END(IPAddressFamily)
97656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
98656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source ProjectASN1_ITEM_TEMPLATE(IPAddrBlocks) =
99656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0,
100656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			IPAddrBlocks, IPAddressFamily)
101656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source ProjectASN1_ITEM_TEMPLATE_END(IPAddrBlocks)
102656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
103656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source ProjectIMPLEMENT_ASN1_FUNCTIONS(IPAddressRange)
104656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source ProjectIMPLEMENT_ASN1_FUNCTIONS(IPAddressOrRange)
105656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source ProjectIMPLEMENT_ASN1_FUNCTIONS(IPAddressChoice)
106656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source ProjectIMPLEMENT_ASN1_FUNCTIONS(IPAddressFamily)
107656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
108656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
109656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * How much buffer space do we need for a raw address?
110656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
111656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#define ADDR_RAW_BUF_LEN	16
112656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
113656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
114656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * What's the address length associated with this AFI?
115656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
116656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int length_from_afi(const unsigned afi)
117656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
118656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  switch (afi) {
119656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  case IANA_AFI_IPV4:
120656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return 4;
121656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  case IANA_AFI_IPV6:
122656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return 16;
123656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  default:
124656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return 0;
125656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  }
126656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
127656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
128656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
129656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Extract the AFI from an IPAddressFamily.
130656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
131e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modaduguunsigned int v3_addr_get_afi(const IPAddressFamily *f)
132656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
133656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  return ((f != NULL &&
134656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	   f->addressFamily != NULL &&
135656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	   f->addressFamily->data != NULL)
136656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	  ? ((f->addressFamily->data[0] << 8) |
137656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	     (f->addressFamily->data[1]))
138656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	  : 0);
139656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
140656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
141656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
142656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Expand the bitstring form of an address into a raw byte array.
143656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * At the moment this is coded for simplicity, not speed.
144656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
1457b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstromstatic int addr_expand(unsigned char *addr,
146656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			const ASN1_BIT_STRING *bs,
147656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			const int length,
148656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			const unsigned char fill)
149656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
1507b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom  if (bs->length < 0 || bs->length > length)
1517b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom    return 0;
152656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (bs->length > 0) {
153656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    memcpy(addr, bs->data, bs->length);
154656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    if ((bs->flags & 7) != 0) {
155656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      unsigned char mask = 0xFF >> (8 - (bs->flags & 7));
156656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      if (fill == 0)
157656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	addr[bs->length - 1] &= ~mask;
158656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      else
159656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	addr[bs->length - 1] |= mask;
160656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    }
161656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  }
162656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  memset(addr + bs->length, fill, length - bs->length);
1637b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom  return 1;
164656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
165656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
166656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
167656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Extract the prefix length from a bitstring.
168656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
169656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#define addr_prefixlen(bs) ((int) ((bs)->length * 8 - ((bs)->flags & 7)))
170656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
171656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
172656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * i2r handler for one address bitstring.
173656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
174656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int i2r_address(BIO *out,
175656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		       const unsigned afi,
176656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		       const unsigned char fill,
177656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		       const ASN1_BIT_STRING *bs)
178656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
179656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  unsigned char addr[ADDR_RAW_BUF_LEN];
180656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  int i, n;
181656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
18281c4de7869b646592127e952cda763abf8305069Brian Carlstrom  if (bs->length < 0)
18381c4de7869b646592127e952cda763abf8305069Brian Carlstrom    return 0;
184656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  switch (afi) {
185656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  case IANA_AFI_IPV4:
1867b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom    if (!addr_expand(addr, bs, 4, fill))
18781c4de7869b646592127e952cda763abf8305069Brian Carlstrom      return 0;
188656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    BIO_printf(out, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
189656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    break;
190656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  case IANA_AFI_IPV6:
1917b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom    if (!addr_expand(addr, bs, 16, fill))
19281c4de7869b646592127e952cda763abf8305069Brian Carlstrom      return 0;
193656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    for (n = 16; n > 1 && addr[n-1] == 0x00 && addr[n-2] == 0x00; n -= 2)
194656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      ;
195656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    for (i = 0; i < n; i += 2)
196656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      BIO_printf(out, "%x%s", (addr[i] << 8) | addr[i+1], (i < 14 ? ":" : ""));
197656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    if (i < 16)
198656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      BIO_puts(out, ":");
199e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    if (i == 0)
200e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu      BIO_puts(out, ":");
201656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    break;
202656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  default:
203656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    for (i = 0; i < bs->length; i++)
204656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      BIO_printf(out, "%s%02x", (i > 0 ? ":" : ""), bs->data[i]);
205656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    BIO_printf(out, "[%d]", (int) (bs->flags & 7));
206656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    break;
207656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  }
208656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  return 1;
209656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
210656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
211656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
212656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * i2r handler for a sequence of addresses and ranges.
213656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
214656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int i2r_IPAddressOrRanges(BIO *out,
215656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				 const int indent,
216656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				 const IPAddressOrRanges *aors,
217656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				 const unsigned afi)
218656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
219656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  int i;
220656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  for (i = 0; i < sk_IPAddressOrRange_num(aors); i++) {
221656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    const IPAddressOrRange *aor = sk_IPAddressOrRange_value(aors, i);
222656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    BIO_printf(out, "%*s", indent, "");
223656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    switch (aor->type) {
224656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    case IPAddressOrRange_addressPrefix:
225656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      if (!i2r_address(out, afi, 0x00, aor->u.addressPrefix))
226656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return 0;
227656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      BIO_printf(out, "/%d\n", addr_prefixlen(aor->u.addressPrefix));
228656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      continue;
229656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    case IPAddressOrRange_addressRange:
230656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      if (!i2r_address(out, afi, 0x00, aor->u.addressRange->min))
231656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return 0;
232656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      BIO_puts(out, "-");
233656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      if (!i2r_address(out, afi, 0xFF, aor->u.addressRange->max))
234656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return 0;
235656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      BIO_puts(out, "\n");
236656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      continue;
237656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    }
238656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  }
239656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  return 1;
240656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
241656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
242656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
243656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * i2r handler for an IPAddrBlocks extension.
244656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
245221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int i2r_IPAddrBlocks(const X509V3_EXT_METHOD *method,
246656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			    void *ext,
247656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			    BIO *out,
248656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			    int indent)
249656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
250656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  const IPAddrBlocks *addr = ext;
251656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  int i;
252656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  for (i = 0; i < sk_IPAddressFamily_num(addr); i++) {
253656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    IPAddressFamily *f = sk_IPAddressFamily_value(addr, i);
254e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    const unsigned int afi = v3_addr_get_afi(f);
255656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    switch (afi) {
256656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    case IANA_AFI_IPV4:
257656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      BIO_printf(out, "%*sIPv4", indent, "");
258656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      break;
259656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    case IANA_AFI_IPV6:
260656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      BIO_printf(out, "%*sIPv6", indent, "");
261656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      break;
262656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    default:
263656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      BIO_printf(out, "%*sUnknown AFI %u", indent, "", afi);
264656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      break;
265656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    }
266656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    if (f->addressFamily->length > 2) {
267656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      switch (f->addressFamily->data[2]) {
268656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      case   1:
269656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BIO_puts(out, " (Unicast)");
270656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	break;
271656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      case   2:
272656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BIO_puts(out, " (Multicast)");
273656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	break;
274656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      case   3:
275656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BIO_puts(out, " (Unicast/Multicast)");
276656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	break;
277656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      case   4:
278656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BIO_puts(out, " (MPLS)");
279656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	break;
280656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      case  64:
281656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BIO_puts(out, " (Tunnel)");
282656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	break;
283656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      case  65:
284656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BIO_puts(out, " (VPLS)");
285656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	break;
286656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      case  66:
287656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BIO_puts(out, " (BGP MDT)");
288656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	break;
289656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      case 128:
290656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BIO_puts(out, " (MPLS-labeled VPN)");
291656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	break;
292656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      default:
293656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BIO_printf(out, " (Unknown SAFI %u)",
294656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		   (unsigned) f->addressFamily->data[2]);
295656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	break;
296656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      }
297656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    }
298656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    switch (f->ipAddressChoice->type) {
299656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    case IPAddressChoice_inherit:
300656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      BIO_puts(out, ": inherit\n");
301656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      break;
302656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    case IPAddressChoice_addressesOrRanges:
303656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      BIO_puts(out, ":\n");
304656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      if (!i2r_IPAddressOrRanges(out,
305656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				 indent + 2,
306656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				 f->ipAddressChoice->u.addressesOrRanges,
307656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				 afi))
308656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return 0;
309656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      break;
310656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    }
311656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  }
312656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  return 1;
313656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
314656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
315656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
316656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Sort comparison function for a sequence of IPAddressOrRange
317656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * elements.
3187b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom *
3197b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom * There's no sane answer we can give if addr_expand() fails, and an
3207b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom * assertion failure on externally supplied data is seriously uncool,
3217b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom * so we just arbitrarily declare that if given invalid inputs this
3227b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom * function returns -1.  If this messes up your preferred sort order
3237b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom * for garbage input, tough noogies.
324656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
325656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int IPAddressOrRange_cmp(const IPAddressOrRange *a,
326656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				const IPAddressOrRange *b,
327656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				const int length)
328656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
329656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  unsigned char addr_a[ADDR_RAW_BUF_LEN], addr_b[ADDR_RAW_BUF_LEN];
330221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom  int prefixlen_a = 0, prefixlen_b = 0;
331656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  int r;
332656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
333656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  switch (a->type) {
334656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  case IPAddressOrRange_addressPrefix:
3357b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom    if (!addr_expand(addr_a, a->u.addressPrefix, length, 0x00))
3367b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom      return -1;
337656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    prefixlen_a = addr_prefixlen(a->u.addressPrefix);
338656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    break;
339656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  case IPAddressOrRange_addressRange:
3407b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom    if (!addr_expand(addr_a, a->u.addressRange->min, length, 0x00))
3417b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom      return -1;
342656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    prefixlen_a = length * 8;
343656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    break;
344656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  }
345656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
346656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  switch (b->type) {
347656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  case IPAddressOrRange_addressPrefix:
3487b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom    if (!addr_expand(addr_b, b->u.addressPrefix, length, 0x00))
3497b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom      return -1;
350656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    prefixlen_b = addr_prefixlen(b->u.addressPrefix);
351656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    break;
352656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  case IPAddressOrRange_addressRange:
3537b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom    if (!addr_expand(addr_b, b->u.addressRange->min, length, 0x00))
3547b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom      return -1;
355656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    prefixlen_b = length * 8;
356656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    break;
357656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  }
358656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
359656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if ((r = memcmp(addr_a, addr_b, length)) != 0)
360656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return r;
361656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  else
362656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return prefixlen_a - prefixlen_b;
363656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
364656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
365656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
366656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * IPv4-specific closure over IPAddressOrRange_cmp, since sk_sort()
367656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * comparision routines are only allowed two arguments.
368656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
369656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int v4IPAddressOrRange_cmp(const IPAddressOrRange * const *a,
370656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				  const IPAddressOrRange * const *b)
371656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
372656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  return IPAddressOrRange_cmp(*a, *b, 4);
373656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
374656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
375656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
376656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * IPv6-specific closure over IPAddressOrRange_cmp, since sk_sort()
377656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * comparision routines are only allowed two arguments.
378656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
379656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int v6IPAddressOrRange_cmp(const IPAddressOrRange * const *a,
380656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				  const IPAddressOrRange * const *b)
381656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
382656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  return IPAddressOrRange_cmp(*a, *b, 16);
383656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
384656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
385656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
386656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Calculate whether a range collapses to a prefix.
387656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * See last paragraph of RFC 3779 2.2.3.7.
388656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
389656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int range_should_be_prefix(const unsigned char *min,
390656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				  const unsigned char *max,
391656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				  const int length)
392656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
393656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  unsigned char mask;
394656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  int i, j;
395656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
3967b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom  OPENSSL_assert(memcmp(min, max, length) <= 0);
397656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  for (i = 0; i < length && min[i] == max[i]; i++)
398656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    ;
399656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  for (j = length - 1; j >= 0 && min[j] == 0x00 && max[j] == 0xFF; j--)
400656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    ;
401656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (i < j)
402656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return -1;
403656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (i > j)
404656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return i * 8;
405656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  mask = min[i] ^ max[i];
406656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  switch (mask) {
407656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  case 0x01: j = 7; break;
408656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  case 0x03: j = 6; break;
409656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  case 0x07: j = 5; break;
410656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  case 0x0F: j = 4; break;
411656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  case 0x1F: j = 3; break;
412656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  case 0x3F: j = 2; break;
413656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  case 0x7F: j = 1; break;
414656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  default:   return -1;
415656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  }
416656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if ((min[i] & mask) != 0 || (max[i] & mask) != mask)
417656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return -1;
418656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  else
419656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return i * 8 + j;
420656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
421656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
422656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
423656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Construct a prefix.
424656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
425656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int make_addressPrefix(IPAddressOrRange **result,
426656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			      unsigned char *addr,
427656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			      const int prefixlen)
428656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
429656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  int bytelen = (prefixlen + 7) / 8, bitlen = prefixlen % 8;
430656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  IPAddressOrRange *aor = IPAddressOrRange_new();
431656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
432656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (aor == NULL)
433656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return 0;
434656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  aor->type = IPAddressOrRange_addressPrefix;
435656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (aor->u.addressPrefix == NULL &&
436656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      (aor->u.addressPrefix = ASN1_BIT_STRING_new()) == NULL)
437656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    goto err;
438656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (!ASN1_BIT_STRING_set(aor->u.addressPrefix, addr, bytelen))
439656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    goto err;
440656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  aor->u.addressPrefix->flags &= ~7;
441656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  aor->u.addressPrefix->flags |= ASN1_STRING_FLAG_BITS_LEFT;
442656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (bitlen > 0) {
443656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    aor->u.addressPrefix->data[bytelen - 1] &= ~(0xFF >> bitlen);
444656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    aor->u.addressPrefix->flags |= 8 - bitlen;
445656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  }
446656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
447656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  *result = aor;
448656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  return 1;
449656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
450656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project err:
451656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  IPAddressOrRange_free(aor);
452656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  return 0;
453656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
454656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
455656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
456656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Construct a range.  If it can be expressed as a prefix,
457656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * return a prefix instead.  Doing this here simplifies
458656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * the rest of the code considerably.
459656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
460656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int make_addressRange(IPAddressOrRange **result,
461656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			     unsigned char *min,
462656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			     unsigned char *max,
463656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			     const int length)
464656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
465656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  IPAddressOrRange *aor;
466656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  int i, prefixlen;
467656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
468656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if ((prefixlen = range_should_be_prefix(min, max, length)) >= 0)
469656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return make_addressPrefix(result, min, prefixlen);
470656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
471656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if ((aor = IPAddressOrRange_new()) == NULL)
472656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return 0;
473656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  aor->type = IPAddressOrRange_addressRange;
474e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu  OPENSSL_assert(aor->u.addressRange == NULL);
475656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if ((aor->u.addressRange = IPAddressRange_new()) == NULL)
476656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    goto err;
477656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (aor->u.addressRange->min == NULL &&
478656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      (aor->u.addressRange->min = ASN1_BIT_STRING_new()) == NULL)
479656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    goto err;
480656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (aor->u.addressRange->max == NULL &&
481656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      (aor->u.addressRange->max = ASN1_BIT_STRING_new()) == NULL)
482656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    goto err;
483656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
484656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  for (i = length; i > 0 && min[i - 1] == 0x00; --i)
485656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    ;
486656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (!ASN1_BIT_STRING_set(aor->u.addressRange->min, min, i))
487656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    goto err;
488656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  aor->u.addressRange->min->flags &= ~7;
489656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  aor->u.addressRange->min->flags |= ASN1_STRING_FLAG_BITS_LEFT;
490656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (i > 0) {
491656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    unsigned char b = min[i - 1];
492656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    int j = 1;
493656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    while ((b & (0xFFU >> j)) != 0)
494656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      ++j;
495656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    aor->u.addressRange->min->flags |= 8 - j;
496656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  }
497656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
498656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  for (i = length; i > 0 && max[i - 1] == 0xFF; --i)
499656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    ;
500656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (!ASN1_BIT_STRING_set(aor->u.addressRange->max, max, i))
501656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    goto err;
502656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  aor->u.addressRange->max->flags &= ~7;
503656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  aor->u.addressRange->max->flags |= ASN1_STRING_FLAG_BITS_LEFT;
504656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (i > 0) {
505656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    unsigned char b = max[i - 1];
506656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    int j = 1;
507656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    while ((b & (0xFFU >> j)) != (0xFFU >> j))
508656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      ++j;
509656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    aor->u.addressRange->max->flags |= 8 - j;
510656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  }
511656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
512656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  *result = aor;
513656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  return 1;
514656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
515656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project err:
516656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  IPAddressOrRange_free(aor);
517656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  return 0;
518656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
519656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
520656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
521656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Construct a new address family or find an existing one.
522656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
523656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic IPAddressFamily *make_IPAddressFamily(IPAddrBlocks *addr,
524656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project					     const unsigned afi,
525656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project					     const unsigned *safi)
526656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
527656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  IPAddressFamily *f;
528656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  unsigned char key[3];
529656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  unsigned keylen;
530656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  int i;
531656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
532656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  key[0] = (afi >> 8) & 0xFF;
533656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  key[1] = afi & 0xFF;
534656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (safi != NULL) {
535656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    key[2] = *safi & 0xFF;
536656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    keylen = 3;
537656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  } else {
538656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    keylen = 2;
539656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  }
540656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
541656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  for (i = 0; i < sk_IPAddressFamily_num(addr); i++) {
542656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    f = sk_IPAddressFamily_value(addr, i);
543e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    OPENSSL_assert(f->addressFamily->data != NULL);
544656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    if (f->addressFamily->length == keylen &&
545656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	!memcmp(f->addressFamily->data, key, keylen))
546656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      return f;
547656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  }
548656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
549656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if ((f = IPAddressFamily_new()) == NULL)
550656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    goto err;
551656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (f->ipAddressChoice == NULL &&
552656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      (f->ipAddressChoice = IPAddressChoice_new()) == NULL)
553656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    goto err;
554656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (f->addressFamily == NULL &&
555656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      (f->addressFamily = ASN1_OCTET_STRING_new()) == NULL)
556656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    goto err;
557656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (!ASN1_OCTET_STRING_set(f->addressFamily, key, keylen))
558656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    goto err;
559656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (!sk_IPAddressFamily_push(addr, f))
560656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    goto err;
561656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
562656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  return f;
563656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
564656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project err:
565656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  IPAddressFamily_free(f);
566656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  return NULL;
567656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
568656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
569656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
570656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Add an inheritance element.
571656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
572656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint v3_addr_add_inherit(IPAddrBlocks *addr,
573656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			const unsigned afi,
574656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			const unsigned *safi)
575656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
576656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  IPAddressFamily *f = make_IPAddressFamily(addr, afi, safi);
577656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (f == NULL ||
578656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      f->ipAddressChoice == NULL ||
579656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      (f->ipAddressChoice->type == IPAddressChoice_addressesOrRanges &&
580656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project       f->ipAddressChoice->u.addressesOrRanges != NULL))
581656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return 0;
582656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (f->ipAddressChoice->type == IPAddressChoice_inherit &&
583656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      f->ipAddressChoice->u.inherit != NULL)
584656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return 1;
585656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (f->ipAddressChoice->u.inherit == NULL &&
586656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      (f->ipAddressChoice->u.inherit = ASN1_NULL_new()) == NULL)
587656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return 0;
588656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  f->ipAddressChoice->type = IPAddressChoice_inherit;
589656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  return 1;
590656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
591656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
592656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
593656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Construct an IPAddressOrRange sequence, or return an existing one.
594656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
595656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic IPAddressOrRanges *make_prefix_or_range(IPAddrBlocks *addr,
596656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project					       const unsigned afi,
597656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project					       const unsigned *safi)
598656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
599656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  IPAddressFamily *f = make_IPAddressFamily(addr, afi, safi);
600656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  IPAddressOrRanges *aors = NULL;
601656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
602656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (f == NULL ||
603656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      f->ipAddressChoice == NULL ||
604656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      (f->ipAddressChoice->type == IPAddressChoice_inherit &&
605656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project       f->ipAddressChoice->u.inherit != NULL))
606656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return NULL;
607656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (f->ipAddressChoice->type == IPAddressChoice_addressesOrRanges)
608656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    aors = f->ipAddressChoice->u.addressesOrRanges;
609656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (aors != NULL)
610656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return aors;
611656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if ((aors = sk_IPAddressOrRange_new_null()) == NULL)
612656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return NULL;
613656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  switch (afi) {
614656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  case IANA_AFI_IPV4:
6157b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom    (void) sk_IPAddressOrRange_set_cmp_func(aors, v4IPAddressOrRange_cmp);
616656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    break;
617656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  case IANA_AFI_IPV6:
6187b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom    (void) sk_IPAddressOrRange_set_cmp_func(aors, v6IPAddressOrRange_cmp);
619656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    break;
620656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  }
621656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  f->ipAddressChoice->type = IPAddressChoice_addressesOrRanges;
622656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  f->ipAddressChoice->u.addressesOrRanges = aors;
623656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  return aors;
624656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
625656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
626656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
627656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Add a prefix.
628656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
629656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint v3_addr_add_prefix(IPAddrBlocks *addr,
630656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		       const unsigned afi,
631656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		       const unsigned *safi,
632656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		       unsigned char *a,
633656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		       const int prefixlen)
634656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
635656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  IPAddressOrRanges *aors = make_prefix_or_range(addr, afi, safi);
636656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  IPAddressOrRange *aor;
637656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (aors == NULL || !make_addressPrefix(&aor, a, prefixlen))
638656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return 0;
639656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (sk_IPAddressOrRange_push(aors, aor))
640656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return 1;
641656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  IPAddressOrRange_free(aor);
642656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  return 0;
643656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
644656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
645656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
646656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Add a range.
647656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
648656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint v3_addr_add_range(IPAddrBlocks *addr,
649656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		      const unsigned afi,
650656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		      const unsigned *safi,
651656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		      unsigned char *min,
652656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		      unsigned char *max)
653656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
654656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  IPAddressOrRanges *aors = make_prefix_or_range(addr, afi, safi);
655656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  IPAddressOrRange *aor;
656656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  int length = length_from_afi(afi);
657656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (aors == NULL)
658656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return 0;
659656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (!make_addressRange(&aor, min, max, length))
660656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return 0;
661656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (sk_IPAddressOrRange_push(aors, aor))
662656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return 1;
663656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  IPAddressOrRange_free(aor);
664656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  return 0;
665656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
666656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
667656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
668656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Extract min and max values from an IPAddressOrRange.
669656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
6707b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstromstatic int extract_min_max(IPAddressOrRange *aor,
671656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			    unsigned char *min,
672656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			    unsigned char *max,
673656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			    int length)
674656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
6757b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom  if (aor == NULL || min == NULL || max == NULL)
6767b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom    return 0;
677656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  switch (aor->type) {
678656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  case IPAddressOrRange_addressPrefix:
6797b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom    return (addr_expand(min, aor->u.addressPrefix, length, 0x00) &&
6807b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom	    addr_expand(max, aor->u.addressPrefix, length, 0xFF));
681656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  case IPAddressOrRange_addressRange:
6827b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom    return (addr_expand(min, aor->u.addressRange->min, length, 0x00) &&
6837b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom	    addr_expand(max, aor->u.addressRange->max, length, 0xFF));
684656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  }
6857b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom  return 0;
686656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
687656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
688656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
689656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Public wrapper for extract_min_max().
690656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
691656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint v3_addr_get_range(IPAddressOrRange *aor,
692656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		      const unsigned afi,
693656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		      unsigned char *min,
694656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		      unsigned char *max,
695656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		      const int length)
696656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
697656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  int afi_length = length_from_afi(afi);
698656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (aor == NULL || min == NULL || max == NULL ||
699656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      afi_length == 0 || length < afi_length ||
700656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      (aor->type != IPAddressOrRange_addressPrefix &&
7017b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom       aor->type != IPAddressOrRange_addressRange) ||
7027b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom      !extract_min_max(aor, min, max, afi_length))
703656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return 0;
7047b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom
705656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  return afi_length;
706656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
707656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
708656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
709656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Sort comparision function for a sequence of IPAddressFamily.
710656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
711656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * The last paragraph of RFC 3779 2.2.3.3 is slightly ambiguous about
712656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * the ordering: I can read it as meaning that IPv6 without a SAFI
713656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * comes before IPv4 with a SAFI, which seems pretty weird.  The
714656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * examples in appendix B suggest that the author intended the
715656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * null-SAFI rule to apply only within a single AFI, which is what I
716656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * would have expected and is what the following code implements.
717656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
718656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int IPAddressFamily_cmp(const IPAddressFamily * const *a_,
719656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			       const IPAddressFamily * const *b_)
720656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
721656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  const ASN1_OCTET_STRING *a = (*a_)->addressFamily;
722656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  const ASN1_OCTET_STRING *b = (*b_)->addressFamily;
723656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  int len = ((a->length <= b->length) ? a->length : b->length);
724656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  int cmp = memcmp(a->data, b->data, len);
725656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  return cmp ? cmp : a->length - b->length;
726656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
727656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
728656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
729656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Check whether an IPAddrBLocks is in canonical form.
730656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
731656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint v3_addr_is_canonical(IPAddrBlocks *addr)
732656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
733656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN];
734656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  unsigned char b_min[ADDR_RAW_BUF_LEN], b_max[ADDR_RAW_BUF_LEN];
735656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  IPAddressOrRanges *aors;
736656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  int i, j, k;
737656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
738656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  /*
739656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project   * Empty extension is cannonical.
740656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project   */
741656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (addr == NULL)
742656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return 1;
743656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
744656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  /*
745656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project   * Check whether the top-level list is in order.
746656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project   */
747656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  for (i = 0; i < sk_IPAddressFamily_num(addr) - 1; i++) {
748656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    const IPAddressFamily *a = sk_IPAddressFamily_value(addr, i);
749656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    const IPAddressFamily *b = sk_IPAddressFamily_value(addr, i + 1);
750656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    if (IPAddressFamily_cmp(&a, &b) >= 0)
751656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      return 0;
752656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  }
753656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
754656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  /*
755656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project   * Top level's ok, now check each address family.
756656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project   */
757656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  for (i = 0; i < sk_IPAddressFamily_num(addr); i++) {
758656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    IPAddressFamily *f = sk_IPAddressFamily_value(addr, i);
759656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    int length = length_from_afi(v3_addr_get_afi(f));
760656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
761656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    /*
762656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project     * Inheritance is canonical.  Anything other than inheritance or
763656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project     * a SEQUENCE OF IPAddressOrRange is an ASN.1 error or something.
764656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project     */
765656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    if (f == NULL || f->ipAddressChoice == NULL)
766656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      return 0;
767656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    switch (f->ipAddressChoice->type) {
768656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    case IPAddressChoice_inherit:
769656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      continue;
770656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    case IPAddressChoice_addressesOrRanges:
771656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      break;
772656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    default:
773656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      return 0;
774656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    }
775656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
776656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    /*
777656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project     * It's an IPAddressOrRanges sequence, check it.
778656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project     */
779656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    aors = f->ipAddressChoice->u.addressesOrRanges;
780656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    if (sk_IPAddressOrRange_num(aors) == 0)
781656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      return 0;
782656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    for (j = 0; j < sk_IPAddressOrRange_num(aors) - 1; j++) {
783656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j);
784656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      IPAddressOrRange *b = sk_IPAddressOrRange_value(aors, j + 1);
785656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
7867b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom      if (!extract_min_max(a, a_min, a_max, length) ||
7877b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom	  !extract_min_max(b, b_min, b_max, length))
7887b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom	return 0;
789656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
790656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      /*
791656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project       * Punt misordered list, overlapping start, or inverted range.
792656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project       */
793656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      if (memcmp(a_min, b_min, length) >= 0 ||
794656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	  memcmp(a_min, a_max, length) > 0 ||
795656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	  memcmp(b_min, b_max, length) > 0)
796656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return 0;
797656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
798656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      /*
799656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project       * Punt if adjacent or overlapping.  Check for adjacency by
800656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project       * subtracting one from b_min first.
801656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project       */
802656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      for (k = length - 1; k >= 0 && b_min[k]-- == 0x00; k--)
803656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	;
804656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      if (memcmp(a_max, b_min, length) >= 0)
805656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return 0;
806656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
807656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      /*
808656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project       * Check for range that should be expressed as a prefix.
809656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project       */
810656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      if (a->type == IPAddressOrRange_addressRange &&
811656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	  range_should_be_prefix(a_min, a_max, length) >= 0)
812656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return 0;
813656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    }
814656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
815656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    /*
8167b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom     * Check range to see if it's inverted or should be a
8177b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom     * prefix.
818656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project     */
819656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    j = sk_IPAddressOrRange_num(aors) - 1;
820656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    {
821656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j);
8227b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom      if (a != NULL && a->type == IPAddressOrRange_addressRange) {
8237b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom	if (!extract_min_max(a, a_min, a_max, length))
8247b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom	  return 0;
8257b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom	if (memcmp(a_min, a_max, length) > 0 ||
8267b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom	    range_should_be_prefix(a_min, a_max, length) >= 0)
827656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	  return 0;
828656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      }
829656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    }
830656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  }
831656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
832656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  /*
833656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project   * If we made it through all that, we're happy.
834656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project   */
835656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  return 1;
836656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
837656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
838656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
839656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Whack an IPAddressOrRanges into canonical form.
840656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
841656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int IPAddressOrRanges_canonize(IPAddressOrRanges *aors,
842656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				      const unsigned afi)
843656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
844656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  int i, j, length = length_from_afi(afi);
845656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
846656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  /*
847656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project   * Sort the IPAddressOrRanges sequence.
848656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project   */
849656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  sk_IPAddressOrRange_sort(aors);
850656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
851656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  /*
852656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project   * Clean up representation issues, punt on duplicates or overlaps.
853656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project   */
854656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  for (i = 0; i < sk_IPAddressOrRange_num(aors) - 1; i++) {
855656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, i);
856656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    IPAddressOrRange *b = sk_IPAddressOrRange_value(aors, i + 1);
857656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN];
858656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    unsigned char b_min[ADDR_RAW_BUF_LEN], b_max[ADDR_RAW_BUF_LEN];
859656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
8607b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom    if (!extract_min_max(a, a_min, a_max, length) ||
8617b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom	!extract_min_max(b, b_min, b_max, length))
8627b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom      return 0;
8637b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom
8647b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom    /*
8657b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom     * Punt inverted ranges.
8667b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom     */
8677b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom    if (memcmp(a_min, a_max, length) > 0 ||
8687b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom	memcmp(b_min, b_max, length) > 0)
8697b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom      return 0;
870656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
871656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    /*
872656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project     * Punt overlaps.
873656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project     */
874656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    if (memcmp(a_max, b_min, length) >= 0)
875656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      return 0;
876656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
877656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    /*
878656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project     * Merge if a and b are adjacent.  We check for
879656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project     * adjacency by subtracting one from b_min first.
880656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project     */
881656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    for (j = length - 1; j >= 0 && b_min[j]-- == 0x00; j--)
882656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      ;
883656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    if (memcmp(a_max, b_min, length) == 0) {
884656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      IPAddressOrRange *merged;
885656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      if (!make_addressRange(&merged, a_min, b_max, length))
886656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return 0;
8877b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom      (void) sk_IPAddressOrRange_set(aors, i, merged);
8887b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom      (void) sk_IPAddressOrRange_delete(aors, i + 1);
889656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      IPAddressOrRange_free(a);
890656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      IPAddressOrRange_free(b);
891656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      --i;
892656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      continue;
893656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    }
894656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  }
895656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
8967b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom  /*
8977b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom   * Check for inverted final range.
8987b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom   */
8997b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom  j = sk_IPAddressOrRange_num(aors) - 1;
9007b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom  {
9017b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom    IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j);
9027b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom    if (a != NULL && a->type == IPAddressOrRange_addressRange) {
9037b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom      unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN];
9047b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom      extract_min_max(a, a_min, a_max, length);
9057b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom      if (memcmp(a_min, a_max, length) > 0)
9067b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom	return 0;
9077b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom    }
9087b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom  }
9097b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom
910656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  return 1;
911656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
912656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
913656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
914656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Whack an IPAddrBlocks extension into canonical form.
915656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
916656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint v3_addr_canonize(IPAddrBlocks *addr)
917656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
918656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  int i;
919656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  for (i = 0; i < sk_IPAddressFamily_num(addr); i++) {
920656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    IPAddressFamily *f = sk_IPAddressFamily_value(addr, i);
921656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    if (f->ipAddressChoice->type == IPAddressChoice_addressesOrRanges &&
922656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	!IPAddressOrRanges_canonize(f->ipAddressChoice->u.addressesOrRanges,
923656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				    v3_addr_get_afi(f)))
924656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      return 0;
925656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  }
9267b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom  (void) sk_IPAddressFamily_set_cmp_func(addr, IPAddressFamily_cmp);
927656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  sk_IPAddressFamily_sort(addr);
928e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu  OPENSSL_assert(v3_addr_is_canonical(addr));
929656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  return 1;
930656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
931656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
932656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
933656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * v2i handler for the IPAddrBlocks extension.
934656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
935221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic void *v2i_IPAddrBlocks(const struct v3_ext_method *method,
936656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			      struct v3_ext_ctx *ctx,
937656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			      STACK_OF(CONF_VALUE) *values)
938656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
939656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  static const char v4addr_chars[] = "0123456789.";
940656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  static const char v6addr_chars[] = "0123456789.:abcdefABCDEF";
941656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  IPAddrBlocks *addr = NULL;
942656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  char *s = NULL, *t;
943656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  int i;
944656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
945656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if ((addr = sk_IPAddressFamily_new(IPAddressFamily_cmp)) == NULL) {
946656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE);
947656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return NULL;
948656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  }
949656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
950656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  for (i = 0; i < sk_CONF_VALUE_num(values); i++) {
951656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    CONF_VALUE *val = sk_CONF_VALUE_value(values, i);
952656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    unsigned char min[ADDR_RAW_BUF_LEN], max[ADDR_RAW_BUF_LEN];
953656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    unsigned afi, *safi = NULL, safi_;
954656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    const char *addr_chars;
955656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    int prefixlen, i1, i2, delim, length;
956656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
957656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    if (       !name_cmp(val->name, "IPv4")) {
958656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      afi = IANA_AFI_IPV4;
959656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    } else if (!name_cmp(val->name, "IPv6")) {
960656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      afi = IANA_AFI_IPV6;
961656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    } else if (!name_cmp(val->name, "IPv4-SAFI")) {
962656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      afi = IANA_AFI_IPV4;
963656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      safi = &safi_;
964656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    } else if (!name_cmp(val->name, "IPv6-SAFI")) {
965656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      afi = IANA_AFI_IPV6;
966656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      safi = &safi_;
967656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    } else {
968656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      X509V3err(X509V3_F_V2I_IPADDRBLOCKS, X509V3_R_EXTENSION_NAME_ERROR);
969656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      X509V3_conf_err(val);
970656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      goto err;
971656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    }
972656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
973656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    switch (afi) {
974656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    case IANA_AFI_IPV4:
975656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      addr_chars = v4addr_chars;
976656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      break;
977656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    case IANA_AFI_IPV6:
978656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      addr_chars = v6addr_chars;
979656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      break;
980656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    }
981656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
982656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    length = length_from_afi(afi);
983656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
984656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    /*
985656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project     * Handle SAFI, if any, and BUF_strdup() so we can null-terminate
986656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project     * the other input values.
987656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project     */
988656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    if (safi != NULL) {
989656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      *safi = strtoul(val->value, &t, 0);
990656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      t += strspn(t, " \t");
991656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      if (*safi > 0xFF || *t++ != ':') {
992656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	X509V3err(X509V3_F_V2I_IPADDRBLOCKS, X509V3_R_INVALID_SAFI);
993656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	X509V3_conf_err(val);
994656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	goto err;
995656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      }
996656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      t += strspn(t, " \t");
997656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      s = BUF_strdup(t);
998656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    } else {
999656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      s = BUF_strdup(val->value);
1000656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    }
1001656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    if (s == NULL) {
1002656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE);
1003656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      goto err;
1004656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    }
1005656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1006656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    /*
1007656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project     * Check for inheritance.  Not worth additional complexity to
1008656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project     * optimize this (seldom-used) case.
1009656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project     */
1010656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    if (!strcmp(s, "inherit")) {
1011656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      if (!v3_addr_add_inherit(addr, afi, safi)) {
1012656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	X509V3err(X509V3_F_V2I_IPADDRBLOCKS, X509V3_R_INVALID_INHERITANCE);
1013656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	X509V3_conf_err(val);
1014656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	goto err;
1015656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      }
1016656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      OPENSSL_free(s);
1017656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      s = NULL;
1018656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      continue;
1019656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    }
1020656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1021656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    i1 = strspn(s, addr_chars);
1022656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    i2 = i1 + strspn(s + i1, " \t");
1023656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    delim = s[i2++];
1024656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    s[i1] = '\0';
1025656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1026656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    if (a2i_ipadd(min, s) != length) {
1027656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      X509V3err(X509V3_F_V2I_IPADDRBLOCKS, X509V3_R_INVALID_IPADDRESS);
1028656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      X509V3_conf_err(val);
1029656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      goto err;
1030656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    }
1031656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1032656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    switch (delim) {
1033656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    case '/':
1034656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      prefixlen = (int) strtoul(s + i2, &t, 10);
1035656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      if (t == s + i2 || *t != '\0') {
1036656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	X509V3err(X509V3_F_V2I_IPADDRBLOCKS, X509V3_R_EXTENSION_VALUE_ERROR);
1037656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	X509V3_conf_err(val);
1038656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	goto err;
1039656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      }
1040656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      if (!v3_addr_add_prefix(addr, afi, safi, min, prefixlen)) {
1041656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE);
1042656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	goto err;
1043656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      }
1044656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      break;
1045656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    case '-':
1046656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      i1 = i2 + strspn(s + i2, " \t");
1047656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      i2 = i1 + strspn(s + i1, addr_chars);
1048656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      if (i1 == i2 || s[i2] != '\0') {
1049656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	X509V3err(X509V3_F_V2I_IPADDRBLOCKS, X509V3_R_EXTENSION_VALUE_ERROR);
1050656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	X509V3_conf_err(val);
1051656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	goto err;
1052656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      }
1053656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      if (a2i_ipadd(max, s + i1) != length) {
1054656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	X509V3err(X509V3_F_V2I_IPADDRBLOCKS, X509V3_R_INVALID_IPADDRESS);
1055656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	X509V3_conf_err(val);
1056656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	goto err;
1057656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      }
10587b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom      if (memcmp(min, max, length_from_afi(afi)) > 0) {
10597b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom	X509V3err(X509V3_F_V2I_IPADDRBLOCKS, X509V3_R_EXTENSION_VALUE_ERROR);
10607b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom	X509V3_conf_err(val);
10617b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom	goto err;
10627b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom      }
1063656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      if (!v3_addr_add_range(addr, afi, safi, min, max)) {
1064656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE);
1065656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	goto err;
1066656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      }
1067656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      break;
1068656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    case '\0':
1069656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      if (!v3_addr_add_prefix(addr, afi, safi, min, length * 8)) {
1070656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE);
1071656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	goto err;
1072656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      }
1073656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      break;
1074656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    default:
1075656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      X509V3err(X509V3_F_V2I_IPADDRBLOCKS, X509V3_R_EXTENSION_VALUE_ERROR);
1076656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      X509V3_conf_err(val);
1077656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      goto err;
1078656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    }
1079656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1080656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    OPENSSL_free(s);
1081656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    s = NULL;
1082656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  }
1083656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1084656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  /*
1085656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project   * Canonize the result, then we're done.
1086656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project   */
1087656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (!v3_addr_canonize(addr))
1088656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    goto err;
1089656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  return addr;
1090656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1091656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project err:
1092656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  OPENSSL_free(s);
1093656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  sk_IPAddressFamily_pop_free(addr, IPAddressFamily_free);
1094656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  return NULL;
1095656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
1096656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1097656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
1098656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * OpenSSL dispatch
1099656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
1100656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectconst X509V3_EXT_METHOD v3_addr = {
1101656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  NID_sbgp_ipAddrBlock,		/* nid */
1102656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  0,				/* flags */
1103656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  ASN1_ITEM_ref(IPAddrBlocks),	/* template */
1104656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  0, 0, 0, 0,			/* old functions, ignored */
1105656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  0,				/* i2s */
1106656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  0,				/* s2i */
1107656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  0,				/* i2v */
1108656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  v2i_IPAddrBlocks,		/* v2i */
1109656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  i2r_IPAddrBlocks,		/* i2r */
1110656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  0,				/* r2i */
1111656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  NULL				/* extension-specific data */
1112656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project};
1113656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1114656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
1115656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Figure out whether extension sues inheritance.
1116656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
1117656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint v3_addr_inherits(IPAddrBlocks *addr)
1118656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
1119656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  int i;
1120656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (addr == NULL)
1121656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return 0;
1122656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  for (i = 0; i < sk_IPAddressFamily_num(addr); i++) {
1123656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    IPAddressFamily *f = sk_IPAddressFamily_value(addr, i);
1124656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    if (f->ipAddressChoice->type == IPAddressChoice_inherit)
1125656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      return 1;
1126656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  }
1127656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  return 0;
1128656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
1129656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1130656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
1131656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Figure out whether parent contains child.
1132656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
1133656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int addr_contains(IPAddressOrRanges *parent,
1134656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			 IPAddressOrRanges *child,
1135656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			 int length)
1136656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
1137656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  unsigned char p_min[ADDR_RAW_BUF_LEN], p_max[ADDR_RAW_BUF_LEN];
1138656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  unsigned char c_min[ADDR_RAW_BUF_LEN], c_max[ADDR_RAW_BUF_LEN];
1139656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  int p, c;
1140656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1141656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (child == NULL || parent == child)
1142656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return 1;
1143656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (parent == NULL)
1144656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return 0;
1145656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1146656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  p = 0;
1147656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  for (c = 0; c < sk_IPAddressOrRange_num(child); c++) {
11487b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom    if (!extract_min_max(sk_IPAddressOrRange_value(child, c),
11497b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom			 c_min, c_max, length))
11507b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom      return -1;
1151656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    for (;; p++) {
1152656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      if (p >= sk_IPAddressOrRange_num(parent))
1153656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return 0;
11547b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom      if (!extract_min_max(sk_IPAddressOrRange_value(parent, p),
11557b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom			   p_min, p_max, length))
11567b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom	return 0;
1157656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      if (memcmp(p_max, c_max, length) < 0)
1158656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	continue;
1159656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      if (memcmp(p_min, c_min, length) > 0)
1160656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return 0;
1161656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      break;
1162656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    }
1163656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  }
1164656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1165656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  return 1;
1166656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
1167656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1168656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
1169656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Test whether a is a subset of b.
1170656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
1171656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint v3_addr_subset(IPAddrBlocks *a, IPAddrBlocks *b)
1172656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
1173656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  int i;
1174656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (a == NULL || a == b)
1175656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return 1;
1176656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (b == NULL || v3_addr_inherits(a) || v3_addr_inherits(b))
1177656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return 0;
11787b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom  (void) sk_IPAddressFamily_set_cmp_func(b, IPAddressFamily_cmp);
1179656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  for (i = 0; i < sk_IPAddressFamily_num(a); i++) {
1180656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    IPAddressFamily *fa = sk_IPAddressFamily_value(a, i);
1181656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    int j = sk_IPAddressFamily_find(b, fa);
1182e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    IPAddressFamily *fb;
1183e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    fb = sk_IPAddressFamily_value(b, j);
1184e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    if (fb == NULL)
1185e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu       return 0;
1186656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    if (!addr_contains(fb->ipAddressChoice->u.addressesOrRanges,
1187656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		       fa->ipAddressChoice->u.addressesOrRanges,
1188656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		       length_from_afi(v3_addr_get_afi(fb))))
1189656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      return 0;
1190656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  }
1191656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  return 1;
1192656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
1193656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1194656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
1195656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Validation error handling via callback.
1196656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
1197656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#define validation_err(_err_)		\
1198656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  do {					\
1199656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    if (ctx != NULL) {			\
1200656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      ctx->error = _err_;		\
1201656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      ctx->error_depth = i;		\
1202656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      ctx->current_cert = x;		\
1203656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      ret = ctx->verify_cb(0, ctx);	\
1204656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    } else {				\
1205656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      ret = 0;				\
1206656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    }					\
1207656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    if (!ret)				\
1208656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      goto done;			\
1209656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  } while (0)
1210656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1211656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
1212656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Core code for RFC 3779 2.3 path validation.
1213656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
1214656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectstatic int v3_addr_validate_path_internal(X509_STORE_CTX *ctx,
1215656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project					  STACK_OF(X509) *chain,
1216656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project					  IPAddrBlocks *ext)
1217656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
1218656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  IPAddrBlocks *child = NULL;
1219656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  int i, j, ret = 1;
1220221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom  X509 *x;
1221656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1222e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu  OPENSSL_assert(chain != NULL && sk_X509_num(chain) > 0);
1223e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu  OPENSSL_assert(ctx != NULL || ext != NULL);
1224e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu  OPENSSL_assert(ctx == NULL || ctx->verify_cb != NULL);
1225656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1226656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  /*
1227656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project   * Figure out where to start.  If we don't have an extension to
1228656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project   * check, we're done.  Otherwise, check canonical form and
1229656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project   * set up for walking up the chain.
1230656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project   */
1231656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (ext != NULL) {
1232656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    i = -1;
1233221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom    x = NULL;
1234656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  } else {
1235656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    i = 0;
1236656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    x = sk_X509_value(chain, i);
1237e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    OPENSSL_assert(x != NULL);
1238656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    if ((ext = x->rfc3779_addr) == NULL)
1239656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      goto done;
1240656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  }
1241656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (!v3_addr_is_canonical(ext))
1242656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    validation_err(X509_V_ERR_INVALID_EXTENSION);
12437b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom  (void) sk_IPAddressFamily_set_cmp_func(ext, IPAddressFamily_cmp);
1244656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if ((child = sk_IPAddressFamily_dup(ext)) == NULL) {
1245656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    X509V3err(X509V3_F_V3_ADDR_VALIDATE_PATH_INTERNAL, ERR_R_MALLOC_FAILURE);
1246656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    ret = 0;
1247656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    goto done;
1248656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  }
1249656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1250656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  /*
1251656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project   * Now walk up the chain.  No cert may list resources that its
1252656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project   * parent doesn't list.
1253656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project   */
1254656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  for (i++; i < sk_X509_num(chain); i++) {
1255656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    x = sk_X509_value(chain, i);
1256e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    OPENSSL_assert(x != NULL);
1257656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    if (!v3_addr_is_canonical(x->rfc3779_addr))
1258656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      validation_err(X509_V_ERR_INVALID_EXTENSION);
1259656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    if (x->rfc3779_addr == NULL) {
1260656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      for (j = 0; j < sk_IPAddressFamily_num(child); j++) {
1261656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	IPAddressFamily *fc = sk_IPAddressFamily_value(child, j);
1262656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (fc->ipAddressChoice->type != IPAddressChoice_inherit) {
1263656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	  validation_err(X509_V_ERR_UNNESTED_RESOURCE);
1264656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	  break;
1265656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
1266656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      }
1267656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      continue;
1268656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    }
12697b476c43f6a45574eb34697244b592e7b09f05a3Brian Carlstrom    (void) sk_IPAddressFamily_set_cmp_func(x->rfc3779_addr, IPAddressFamily_cmp);
1270656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    for (j = 0; j < sk_IPAddressFamily_num(child); j++) {
1271656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      IPAddressFamily *fc = sk_IPAddressFamily_value(child, j);
1272656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      int k = sk_IPAddressFamily_find(x->rfc3779_addr, fc);
1273656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      IPAddressFamily *fp = sk_IPAddressFamily_value(x->rfc3779_addr, k);
1274656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      if (fp == NULL) {
1275656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (fc->ipAddressChoice->type == IPAddressChoice_addressesOrRanges) {
1276656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	  validation_err(X509_V_ERR_UNNESTED_RESOURCE);
1277656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	  break;
1278656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
1279656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	continue;
1280656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      }
1281656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      if (fp->ipAddressChoice->type == IPAddressChoice_addressesOrRanges) {
1282656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (fc->ipAddressChoice->type == IPAddressChoice_inherit ||
1283656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	    addr_contains(fp->ipAddressChoice->u.addressesOrRanges,
1284656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			  fc->ipAddressChoice->u.addressesOrRanges,
1285656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			  length_from_afi(v3_addr_get_afi(fc))))
1286656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	  sk_IPAddressFamily_set(child, j, fp);
1287656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	else
1288656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	  validation_err(X509_V_ERR_UNNESTED_RESOURCE);
1289656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      }
1290656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    }
1291656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  }
1292656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1293656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  /*
1294656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project   * Trust anchor can't inherit.
1295656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project   */
1296221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom  OPENSSL_assert(x != NULL);
1297656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (x->rfc3779_addr != NULL) {
1298656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    for (j = 0; j < sk_IPAddressFamily_num(x->rfc3779_addr); j++) {
1299656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      IPAddressFamily *fp = sk_IPAddressFamily_value(x->rfc3779_addr, j);
1300656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project      if (fp->ipAddressChoice->type == IPAddressChoice_inherit &&
1301656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	  sk_IPAddressFamily_find(child, fp) >= 0)
1302656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	validation_err(X509_V_ERR_UNNESTED_RESOURCE);
1303656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    }
1304656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  }
1305656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1306656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project done:
1307656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  sk_IPAddressFamily_free(child);
1308656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  return ret;
1309656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
1310656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1311656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#undef validation_err
1312656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1313656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
1314656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * RFC 3779 2.3 path validation -- called from X509_verify_cert().
1315656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
1316656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint v3_addr_validate_path(X509_STORE_CTX *ctx)
1317656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
1318656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  return v3_addr_validate_path_internal(ctx, ctx->chain, NULL);
1319656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
1320656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1321656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/*
1322656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * RFC 3779 2.3 path validation of an extension.
1323656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Test whether chain covers extension.
1324656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
1325656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint v3_addr_validate_resource_set(STACK_OF(X509) *chain,
1326656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				  IPAddrBlocks *ext,
1327656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				  int allow_inheritance)
1328656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project{
1329656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (ext == NULL)
1330656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return 1;
1331656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (chain == NULL || sk_X509_num(chain) == 0)
1332656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return 0;
1333656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  if (!allow_inheritance && v3_addr_inherits(ext))
1334656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    return 0;
1335656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project  return v3_addr_validate_path_internal(NULL, chain, ext);
1336656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project}
1337656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1338656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#endif /* OPENSSL_NO_RFC3779 */
1339