diff options
Diffstat (limited to 'openssl/trunk/crypto/x509v3/v3_addr.c')
-rw-r--r-- | openssl/trunk/crypto/x509v3/v3_addr.c | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/openssl/trunk/crypto/x509v3/v3_addr.c b/openssl/trunk/crypto/x509v3/v3_addr.c index 0a3b7539..880b5d8c 100644 --- a/openssl/trunk/crypto/x509v3/v3_addr.c +++ b/openssl/trunk/crypto/x509v3/v3_addr.c @@ -60,6 +60,128 @@ IMPLEMENT_ASN1_FUNCTIONS(IPAddressChoice) IMPLEMENT_ASN1_FUNCTIONS(IPAddressFamily) IMPLEMENT_ASN1_FUNCTIONS(IPAddrBlocks) +static const struct { + unsigned length; + int af; + const char *description; +} afi_table[] = { + { 0 }, + { 4, AF_INET, "IPv4" }, + { 16, AF_INET6, "IPv6" } +}; + +#define afi_index(x) \ + (x > 0 && x < sizeof(afi_table)/sizeof(*afi_table) ? x : 0) + +static const char *safi_table[] = { + 0, + "Unicast", + "Multicast", + "Unicast/Multicast", + "MPLS" +}; + +#define safi_index(x) \ + (x > 0 && x < sizeof(safi_table)/sizeof(*safi_table) ? x : 0) + +static int bitstring_to_address(unsigned char *addr, int len, unsigned char fill, ASN1_BIT_STRING *bs) +{ + if (bs->length > len) + return 0; + memset(addr, fill, len); + if (bs->length == 0) + return 1; + memcpy(addr, bs->data, bs->length); + if ((bs->flags & 7) != 0) + addr[bs->length - 1] |= fill >> (8 - (bs->flags & 7)); + return 1; +} + +static void i2r_unknown_afi_bitstring(BIO *out, ASN1_BIT_STRING *bs) +{ + int i; + for (i = 0; i < bs->length; i++) { + if (i > 0) + BIO_puts(out, ":"); + BIO_printf(out, "%02x", bs->data[i]); + } + BIO_printf(out, "[%d]", bs->flags & 7); +} + +static int i2r_IPAddressOrRange(BIO *out, int indent, IPAddressOrRange *aor, int afi) +{ + int af = afi_table[afi_index(afi)].af, length = afi_table[afi_index(afi)].length; + unsigned char addr[16]; + char buf[48]; + + assert(sizeof(addr) >= length); + BIO_printf(out, "%*s", indent, ""); + switch (aor->type) { + case IPAddressOrRange_addressPrefix: + if (afi_index(afi)) { + if (!bitstring_to_address(addr, length, 0x00, aor->addressPrefix) || + inet_ntop(af, addr, buf, sizeof(buf)) == NULL) + return 0; + BIO_printf(out, "%s/%d\n", buf, + aor->addressPrefix->length * 8 - (aor->addressPrefix->flags & 7)); + } else { + i2r_unknown_afi_bitstring(out, aor->addressPrefix); + BIO_puts(out, "\n"); + } + return 1; + case IPAddressOrRange_addressRange: + if (afi_index(afi)) { + if (!bitstring_to_address(addr, length, 0x00, aor->addressRange->min) || + inet_ntop(af, addr, buf, sizeof(buf)) == NULL) + return 0; + BIO_puts(out, buf); + if (!bitstring_to_address(addr, length, 0xFF, aor->addressRange->max) || + inet_ntop(af, addr, buf, sizeof(buf)) == NULL) + return 0; + BIO_printf(out, "-%s\n", buf); + } else { + i2r_unknown_afi_bitstring(out, aor->addressRange->min); + BIO_puts(out, "-"); + i2r_unknown_afi_bitstring(out, aor->addressRange->max); + BIO_puts(out, "\n"); + } + return 1; + } +} + +static int i2r_IPAddrBlocks(X509V3_EXT_METHOD *method, void *ext, BIO *out, int indent) +{ + int i, j; + for (i = 0; i < sk_IPAddrBlocks_num(ext); i++) { + IPAddressFamily *f = sk_IPAddrBlocks_value(ext, i); + int afi = (f->addressFamily->data[0] << 8) | f->addressFamily->data[1]; + if (afi_index(afi)) + BIO_printf(out, "%*s%s", indent, "", afi_table[afi_index(afi)].description); + else + BIO_printf(out, "%*sUnknown AFI %i", indent, "", afi); + if (f->addressFamily->length > 2) { + int safi = f->addressFamily->data[2]; + if (safi_index(safi)) + BIO_printf(out, " (%s)", safi_table[safi_index(safi)]); + else + BIO_printf(out, " (Unknown SAFI %d)", safi); + } + switch (f->ipAddressChoice->type) { + case IPAddressChoice_inherit: + BIO_puts(out, ": inherit\n"); + break; + case IPAddressChoice_addressesOrRanges: + BIO_puts(out, ":\n"); + for (j = 0; j < sk_IPAddressOrRange_num(f->ipAddressChoice->u.asIdsOrRanges); j++) + if (!i2r_IPAddressOrRange(out, indent + 2, sk_IPAddressOrRange_num(f->ipAddressChoice->u.asIdsOrRanges, j), afi)) + return 0; + break; + } + } + return 1; +} + + X509V3_EXT_METHOD v3_addr = { NID_IPAddrBlocks, /* nid */ 0, /* flags */ |