📄 v3_addr.c
字号:
/* * Contributed to the OpenSSL Project by the American Registry for * Internet Numbers ("ARIN"). *//* ==================================================================== * Copyright (c) 2006 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" * * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please contact * licensing@OpenSSL.org. * * 5. Products derived from this software may not be called "OpenSSL" * nor may "OpenSSL" appear in their names without prior written * permission of the OpenSSL Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" * * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This product includes cryptographic software written by Eric Young * (eay@cryptsoft.com). This product includes software written by Tim * Hudson (tjh@cryptsoft.com). *//* * Implementation of RFC 3779 section 2.2. */#include <stdio.h>#include <stdlib.h>#include "cryptlib.h"#include <openssl/conf.h>#include <openssl/asn1.h>#include <openssl/asn1t.h>#include <openssl/buffer.h>#include <openssl/x509v3.h>#ifndef OPENSSL_NO_RFC3779/* * OpenSSL ASN.1 template translation of RFC 3779 2.2.3. */ASN1_SEQUENCE(IPAddressRange) = { ASN1_SIMPLE(IPAddressRange, min, ASN1_BIT_STRING), ASN1_SIMPLE(IPAddressRange, max, ASN1_BIT_STRING)} ASN1_SEQUENCE_END(IPAddressRange)ASN1_CHOICE(IPAddressOrRange) = { ASN1_SIMPLE(IPAddressOrRange, u.addressPrefix, ASN1_BIT_STRING), ASN1_SIMPLE(IPAddressOrRange, u.addressRange, IPAddressRange)} ASN1_CHOICE_END(IPAddressOrRange)ASN1_CHOICE(IPAddressChoice) = { ASN1_SIMPLE(IPAddressChoice, u.inherit, ASN1_NULL), ASN1_SEQUENCE_OF(IPAddressChoice, u.addressesOrRanges, IPAddressOrRange)} ASN1_CHOICE_END(IPAddressChoice)ASN1_SEQUENCE(IPAddressFamily) = { ASN1_SIMPLE(IPAddressFamily, addressFamily, ASN1_OCTET_STRING), ASN1_SIMPLE(IPAddressFamily, ipAddressChoice, IPAddressChoice)} ASN1_SEQUENCE_END(IPAddressFamily)ASN1_ITEM_TEMPLATE(IPAddrBlocks) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, IPAddrBlocks, IPAddressFamily)ASN1_ITEM_TEMPLATE_END(IPAddrBlocks)IMPLEMENT_ASN1_FUNCTIONS(IPAddressRange)IMPLEMENT_ASN1_FUNCTIONS(IPAddressOrRange)IMPLEMENT_ASN1_FUNCTIONS(IPAddressChoice)IMPLEMENT_ASN1_FUNCTIONS(IPAddressFamily)/* * How much buffer space do we need for a raw address? */#define ADDR_RAW_BUF_LEN 16/* * What's the address length associated with this AFI? */static int length_from_afi(const unsigned afi){ switch (afi) { case IANA_AFI_IPV4: return 4; case IANA_AFI_IPV6: return 16; default: return 0; }}/* * Extract the AFI from an IPAddressFamily. */unsigned int v3_addr_get_afi(const IPAddressFamily *f){ return ((f != NULL && f->addressFamily != NULL && f->addressFamily->data != NULL) ? ((f->addressFamily->data[0] << 8) | (f->addressFamily->data[1])) : 0);}/* * Expand the bitstring form of an address into a raw byte array. * At the moment this is coded for simplicity, not speed. */static void addr_expand(unsigned char *addr, const ASN1_BIT_STRING *bs, const int length, const unsigned char fill){ OPENSSL_assert(bs->length >= 0 && bs->length <= length); if (bs->length > 0) { memcpy(addr, bs->data, bs->length); if ((bs->flags & 7) != 0) { unsigned char mask = 0xFF >> (8 - (bs->flags & 7)); if (fill == 0) addr[bs->length - 1] &= ~mask; else addr[bs->length - 1] |= mask; } } memset(addr + bs->length, fill, length - bs->length);}/* * Extract the prefix length from a bitstring. */#define addr_prefixlen(bs) ((int) ((bs)->length * 8 - ((bs)->flags & 7)))/* * i2r handler for one address bitstring. */static int i2r_address(BIO *out, const unsigned afi, const unsigned char fill, const ASN1_BIT_STRING *bs){ unsigned char addr[ADDR_RAW_BUF_LEN]; int i, n; switch (afi) { case IANA_AFI_IPV4: addr_expand(addr, bs, 4, fill); BIO_printf(out, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); break; case IANA_AFI_IPV6: addr_expand(addr, bs, 16, fill); for (n = 16; n > 1 && addr[n-1] == 0x00 && addr[n-2] == 0x00; n -= 2) ; for (i = 0; i < n; i += 2) BIO_printf(out, "%x%s", (addr[i] << 8) | addr[i+1], (i < 14 ? ":" : "")); if (i < 16) BIO_puts(out, ":"); if (i == 0) BIO_puts(out, ":"); break; default: for (i = 0; i < bs->length; i++) BIO_printf(out, "%s%02x", (i > 0 ? ":" : ""), bs->data[i]); BIO_printf(out, "[%d]", (int) (bs->flags & 7)); break; } return 1;}/* * i2r handler for a sequence of addresses and ranges. */static int i2r_IPAddressOrRanges(BIO *out, const int indent, const IPAddressOrRanges *aors, const unsigned afi){ int i; for (i = 0; i < sk_IPAddressOrRange_num(aors); i++) { const IPAddressOrRange *aor = sk_IPAddressOrRange_value(aors, i); BIO_printf(out, "%*s", indent, ""); switch (aor->type) { case IPAddressOrRange_addressPrefix: if (!i2r_address(out, afi, 0x00, aor->u.addressPrefix)) return 0; BIO_printf(out, "/%d\n", addr_prefixlen(aor->u.addressPrefix)); continue; case IPAddressOrRange_addressRange: if (!i2r_address(out, afi, 0x00, aor->u.addressRange->min)) return 0; BIO_puts(out, "-"); if (!i2r_address(out, afi, 0xFF, aor->u.addressRange->max)) return 0; BIO_puts(out, "\n"); continue; } } return 1;}/* * i2r handler for an IPAddrBlocks extension. */static int i2r_IPAddrBlocks(X509V3_EXT_METHOD *method, void *ext, BIO *out, int indent){ const IPAddrBlocks *addr = ext; int i; for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { IPAddressFamily *f = sk_IPAddressFamily_value(addr, i); const unsigned int afi = v3_addr_get_afi(f); switch (afi) { case IANA_AFI_IPV4: BIO_printf(out, "%*sIPv4", indent, ""); break; case IANA_AFI_IPV6: BIO_printf(out, "%*sIPv6", indent, ""); break; default: BIO_printf(out, "%*sUnknown AFI %u", indent, "", afi); break; } if (f->addressFamily->length > 2) { switch (f->addressFamily->data[2]) { case 1: BIO_puts(out, " (Unicast)"); break; case 2: BIO_puts(out, " (Multicast)"); break; case 3: BIO_puts(out, " (Unicast/Multicast)"); break; case 4: BIO_puts(out, " (MPLS)"); break; case 64: BIO_puts(out, " (Tunnel)"); break; case 65: BIO_puts(out, " (VPLS)"); break; case 66: BIO_puts(out, " (BGP MDT)"); break; case 128: BIO_puts(out, " (MPLS-labeled VPN)"); break; default: BIO_printf(out, " (Unknown SAFI %u)", (unsigned) f->addressFamily->data[2]); break; } } switch (f->ipAddressChoice->type) { case IPAddressChoice_inherit: BIO_puts(out, ": inherit\n"); break; case IPAddressChoice_addressesOrRanges: BIO_puts(out, ":\n"); if (!i2r_IPAddressOrRanges(out, indent + 2, f->ipAddressChoice->u.addressesOrRanges, afi)) return 0; break; } } return 1;}/* * Sort comparison function for a sequence of IPAddressOrRange * elements. */static int IPAddressOrRange_cmp(const IPAddressOrRange *a, const IPAddressOrRange *b, const int length){ unsigned char addr_a[ADDR_RAW_BUF_LEN], addr_b[ADDR_RAW_BUF_LEN]; int prefixlen_a = 0; int prefixlen_b = 0; int r; switch (a->type) { case IPAddressOrRange_addressPrefix: addr_expand(addr_a, a->u.addressPrefix, length, 0x00); prefixlen_a = addr_prefixlen(a->u.addressPrefix); break; case IPAddressOrRange_addressRange: addr_expand(addr_a, a->u.addressRange->min, length, 0x00); prefixlen_a = length * 8; break; } switch (b->type) { case IPAddressOrRange_addressPrefix: addr_expand(addr_b, b->u.addressPrefix, length, 0x00); prefixlen_b = addr_prefixlen(b->u.addressPrefix); break; case IPAddressOrRange_addressRange: addr_expand(addr_b, b->u.addressRange->min, length, 0x00); prefixlen_b = length * 8; break; } if ((r = memcmp(addr_a, addr_b, length)) != 0) return r; else return prefixlen_a - prefixlen_b;}/* * IPv4-specific closure over IPAddressOrRange_cmp, since sk_sort() * comparision routines are only allowed two arguments. */static int v4IPAddressOrRange_cmp(const IPAddressOrRange * const *a, const IPAddressOrRange * const *b){ return IPAddressOrRange_cmp(*a, *b, 4);}/* * IPv6-specific closure over IPAddressOrRange_cmp, since sk_sort() * comparision routines are only allowed two arguments. */static int v6IPAddressOrRange_cmp(const IPAddressOrRange * const *a, const IPAddressOrRange * const *b){ return IPAddressOrRange_cmp(*a, *b, 16);}/* * Calculate whether a range collapses to a prefix. * See last paragraph of RFC 3779 2.2.3.7. */static int range_should_be_prefix(const unsigned char *min, const unsigned char *max, const int length){ unsigned char mask; int i, j; for (i = 0; i < length && min[i] == max[i]; i++) ; for (j = length - 1; j >= 0 && min[j] == 0x00 && max[j] == 0xFF; j--) ; if (i < j) return -1; if (i > j) return i * 8; mask = min[i] ^ max[i]; switch (mask) { case 0x01: j = 7; break; case 0x03: j = 6; break; case 0x07: j = 5; break; case 0x0F: j = 4; break; case 0x1F: j = 3; break; case 0x3F: j = 2; break; case 0x7F: j = 1; break; default: return -1; } if ((min[i] & mask) != 0 || (max[i] & mask) != mask) return -1; else return i * 8 + j;}/* * Construct a prefix. */static int make_addressPrefix(IPAddressOrRange **result, unsigned char *addr, const int prefixlen){ int bytelen = (prefixlen + 7) / 8, bitlen = prefixlen % 8; IPAddressOrRange *aor = IPAddressOrRange_new(); if (aor == NULL) return 0; aor->type = IPAddressOrRange_addressPrefix; if (aor->u.addressPrefix == NULL && (aor->u.addressPrefix = ASN1_BIT_STRING_new()) == NULL) goto err; if (!ASN1_BIT_STRING_set(aor->u.addressPrefix, addr, bytelen)) goto err; aor->u.addressPrefix->flags &= ~7; aor->u.addressPrefix->flags |= ASN1_STRING_FLAG_BITS_LEFT; if (bitlen > 0) { aor->u.addressPrefix->data[bytelen - 1] &= ~(0xFF >> bitlen); aor->u.addressPrefix->flags |= 8 - bitlen; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -