aboutsummaryrefslogtreecommitdiff
path: root/openssl/trunk/crypto/x509v3/v3_addr.c
diff options
context:
space:
mode:
Diffstat (limited to 'openssl/trunk/crypto/x509v3/v3_addr.c')
-rw-r--r--openssl/trunk/crypto/x509v3/v3_addr.c230
1 files changed, 111 insertions, 119 deletions
diff --git a/openssl/trunk/crypto/x509v3/v3_addr.c b/openssl/trunk/crypto/x509v3/v3_addr.c
index d0459db6..b06ee2b4 100644
--- a/openssl/trunk/crypto/x509v3/v3_addr.c
+++ b/openssl/trunk/crypto/x509v3/v3_addr.c
@@ -31,6 +31,10 @@
#include <openssl/asn1t.h>
#include <openssl/x509v3.h>
+/*
+ * 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)
@@ -102,43 +106,12 @@ static void addr_expand(unsigned char *addr,
#define addr_prefixlen(bs) ((bs)->length * 8 - ((bs)->flags & 7))
/*
- * Compare two addresses.
- * At the moment this is coded for simplicity, not for speed.
- *
- * Well, ok, this was simple until we had to check for adjacency. The
- * idea is that, once we know that b is larger than a, we can subtract
- * one from b and check for equality to see if they're adjacent. If
- * this hack offends you, feel free to recode this whole thing in
- * terms of the BN library....
+ * i2r handler for one address bitstring.
*/
-static int addr_cmp(const ASN1_BIT_STRING *a,
- const ASN1_BIT_STRING *b,
- const unsigned char fill_a,
- const unsigned char fill_b,
- const int length,
- const int check_adjacent)
-{
- int r;
- unsigned char a_[ADDR_RAW_BUF_LEN];
- unsigned char b_[ADDR_RAW_BUF_LEN];
- assert(length <= ADDR_RAW_BUF_LEN);
- addr_expand(a_, a, length, fill_a);
- addr_expand(b_, b, length, fill_b);
- r = memcmp(a, b, length);
- if (check_adjacent && r < 0) {
- int i = length - 1;
- while (i >= 0 && !b[i]--)
- i--;
- if (!memcmp(a, b, length))
- r = 0;
- }
- return r;
-}
-
static int i2r_address(BIO *out,
- unsigned afi,
- unsigned char fill,
- ASN1_BIT_STRING *bs)
+ const unsigned afi,
+ const unsigned char fill,
+ const ASN1_BIT_STRING *bs)
{
unsigned char addr[ADDR_RAW_BUF_LEN];
char buf[ADDR_TXT_BUF_LEN];
@@ -166,14 +139,17 @@ static int i2r_address(BIO *out,
return 1;
}
-static int i2r_IPAddressOrRange(BIO *out,
- int indent,
- IPAddressOrRanges *aors,
- unsigned afi)
+/*
+ * 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++) {
- IPAddressOrRange *aor = sk_IPAddressOrRange_num(aors, i);
+ const IPAddressOrRange *aor = sk_IPAddressOrRange_num(aors, i);
BIO_printf(out, "%*s", indent, "");
switch (aor->type) {
case IPAddressOrRange_addressPrefix:
@@ -194,14 +170,20 @@ static int i2r_IPAddressOrRange(BIO *out,
return 1;
}
+/*
+ * i2r handler for an IPAddrBlocks extension.
+ */
static int i2r_IPAddrBlocks(X509V3_EXT_METHOD *method,
- void *ext, BIO *out, int indent)
+ const void *ext,
+ BIO *out,
+ const int indent)
{
+ const IPAddrBlocks *addr = ext;
int i;
- for (i = 0; i < sk_IPAddrBlocks_num(ext); i++) {
- IPAddressFamily *f = sk_IPAddrBlocks_value(ext, i);
- unsigned afi = ((f->addressFamily->data[0] << 8) |
- (f->addressFamily->data[1]));
+ for (i = 0; i < sk_IPAddrBlocks_num(addr); i++) {
+ const IPAddressFamily *f = sk_IPAddrBlocks_value(addr, i);
+ const unsigned afi = ((f->addressFamily->data[0] << 8) |
+ (f->addressFamily->data[1]));
switch (afi) {
case IANA_AFI_IPV4:
BIO_printf(out, "%*sIPv4", indent, "");
@@ -263,7 +245,8 @@ static int i2r_IPAddrBlocks(X509V3_EXT_METHOD *method,
}
/*
- * Compare two IPAddressOrRanges elements.
+ * Sort comparison function for a sequence of IPAddressOrRange
+ * elements.
*/
static int IPAddressOrRange_cmp(const IPAddressOrRange *a,
const IPAddressOrRange *b,
@@ -302,8 +285,8 @@ static int IPAddressOrRange_cmp(const IPAddressOrRange *a,
}
/*
- * Closures, since sk_sort() comparision routines are only allowed two
- * arguments, and have a weird double pointer type signature.
+ * 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)
@@ -311,6 +294,10 @@ static int v4IPAddressOrRange_cmp(const IPAddressOrRange * const *a,
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)
{
@@ -318,49 +305,39 @@ static int v6IPAddressOrRange_cmp(const IPAddressOrRange * const *a,
}
/*
- * Calculate whether a range should be collapsed to a prefix.
- * prefixlen is set on return to indicate the prefix length we found
+ * 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,
- int *prefixlen)
+ const int length)
{
unsigned char mask;
- int p, i, j;
-
- i = 0;
- while (i < length && min[i] == max[i])
- i++;
-
- j = length - 1;
- while (j >= 0 && min[j] == 0x00 && max[j] == 0xFF)
- j--;
+ 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 0;
-
- if (i > j) {
- *prefixlen = i * 8;
- return 1;
- }
-
+ return -1;
+ if (i > j)
+ return i * 8;
mask = min[i] ^ max[i];
switch (mask) {
- case 0x01: p = 7; break;
- case 0x03: p = 6; break;
- case 0x07: p = 5; break;
- case 0x0F: p = 4; break;
- case 0x1F: p = 3; break;
- case 0x3F: p = 2; break;
- case 0x7F: p = 1; break;
- default: return 0;
+ 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 0;
- *prefixlen = i * 8 + p;
- return 1;
+ return -1;
+ else
+ return i * 8 + j;
}
/*
@@ -410,7 +387,7 @@ static int make_addressRange(IPAddressOrRange **result,
ASN1_BIT_STRING *min = NULL, *max = NULL;
int i, prefixlen;
- if (range_should_be_prefix(min_, max_, length, &prefixlen))
+ if ((prefixlen = range_should_be_prefix(min_, max_, length)) >= 0)
return make_addressPrefix(result, min_, prefixlen);
if ((aor = IPAddressOrRange_new()) == NULL ||
@@ -470,18 +447,21 @@ static int make_addressRange(IPAddressOrRange **result,
return 0;
}
-static IPAddressFamily *add_IPAddressFamily(IPAddrBlocks *addr,
- unsigned afi,
- int has_safi,
- unsigned safi)
+/*
+ * Construct a new address family or find an existing one.
+ */
+static IPAddressFamily *make_IPAddressFamily(IPAddrBlocks *addr,
+ const unsigned afi,
+ const unsigned *safi)
{
IPAddressFamily *f;
unsigned char key[3];
- unsigned keylen = has_safi ? 3 : 2;
+ unsigned keylen = safi == NULL ? 2 : 3;
int i;
key[0] = (afi >> 8) & 0xFF;
key[1] = afi & 0xFF;
- key[2] = safi & 0xFF;
+ if (safi != NULL)
+ key[2] = *safi & 0xFF;
for (i = 0; i < sk_IPAddressFamily_num(addr); i++) {
*f = sk_IPAddressFamily_value(addr, i);
if (!memcmp(f->addressFamily, key, keylen))
@@ -509,12 +489,14 @@ static IPAddressFamily *add_IPAddressFamily(IPAddrBlocks *addr,
return NULL;
}
+/*
+ * Add an inheritance element.
+ */
static int addr_add_inherit(IPAddrBlocks *addr,
- unsigned afi,
- int has_safi,
- unsigned safi)
+ const unsigned afi,
+ const unsigned *safi)
{
- IPAddressFamily *f = add_IPAddressFamily(addr, afi, has_safi, safi);
+ IPAddressFamily *f = make_IPAddressFamily(addr, afi, safi);
if (f == NULL || f->ipAddressChoice == NULL ||
(f->ipAddressChoice->type == IPAddressChoice_addressesOrRanges &&
f->ipAddressChoice->u.addressesOrRanges != NULL))
@@ -532,11 +514,10 @@ static int addr_add_inherit(IPAddrBlocks *addr,
* Construct an IPAddressOrRanges sequence, or return an existing one.
*/
static IPAddressOrRanges *make_prefix_or_range(IPAddrBlocks *addr,
- unsigned afi,
- int has_safi,
- unsigned safi)
+ const unsigned afi,
+ const unsigned *safi)
{
- IPAddressFamily *f = add_IPAddressFamily(addr, afi, has_safi, safi);
+ IPAddressFamily *f = make_IPAddressFamily(addr, afi, safi);
IPAddressOrRanges *aors = NULL;
if (f == NULL || f->ipAddressChoice == NULL ||
@@ -562,17 +543,18 @@ static IPAddressOrRanges *make_prefix_or_range(IPAddrBlocks *addr,
return aors;
}
+/*
+ * Add a prefix.
+ */
static int addr_add_prefix(IPAddrBlocks *addr,
- unsigned afi,
- int has_safi,
- unsigned safi,
- unsigned char *addr,
- int prefixlen)
+ const unsigned afi,
+ const unsigned *safi,
+ const unsigned char *addr,
+ const int prefixlen)
{
- IPAddressOrRanges *aors = make_prefix_or_range(addr, afi, has_safi, safi);
+ IPAddressOrRanges *aors = make_prefix_or_range(addr, afi, safi);
IPAddressOrRange *aor;
- if (aors == NULL ||
- !make_addressPrefix(&aor, addr, prefixlen))
+ if (aors == NULL || !make_addressPrefix(&aor, addr, prefixlen))
return 0;
if (sk_IPAddressOrRange_push(aors, aor))
return 1;
@@ -582,14 +564,16 @@ static int addr_add_prefix(IPAddrBlocks *addr,
return 0;
}
+/*
+ * Add a range.
+ */
static int addr_add_range(IPAddrBlocks *addr,
- unsigned afi,
- int has_safi,
- unsigned safi,
- unsigned char *min,
- unsigned char *max)
+ const unsigned afi,
+ const unsigned *safi,
+ const unsigned char *min,
+ const unsigned char *max)
{
- IPAddressOrRanges *aors = make_prefix_or_range(addr, afi, has_safi, safi);
+ IPAddressOrRanges *aors = make_prefix_or_range(addr, afi, safi);
IPAddressOrRange *aor;
unsigned length;
if (aors == NULL)
@@ -618,7 +602,7 @@ static int addr_add_range(IPAddrBlocks *addr,
* Whack an IPAddressOrRanges into canonical form.
*/
static int IPAddressOrRanges_canonize(IPAddressOrRanges *aors,
- unsigned afi)
+ const unsigned afi)
{
int i, j, length;
@@ -706,6 +690,9 @@ static int IPAddressOrRanges_canonize(IPAddressOrRanges *aors,
return 1;
}
+/*
+ * Sort comparision function for a sequence of IPAddressFamily.
+ */
static int IPAddressFamily_cmp(const IPAddressFamily * const *a,
const IPAddressFamily * const *b)
{
@@ -713,6 +700,9 @@ static int IPAddressFamily_cmp(const IPAddressFamily * const *a,
(*b)->addressFamily);
}
+/*
+ * v2i handler for the IPAddrBlocks extension.
+ */
static void *v2i_IPAddrBlocks(struct v3_ext_method *method,
struct v3_ext_ctx *ctx,
STACK_OF(CONF_VALUE) *values)
@@ -727,11 +717,10 @@ static void *v2i_IPAddrBlocks(struct v3_ext_method *method,
for (i = 0; i < sk_CONF_VALUE_num(values); i++) {
CONF_VALUE *val = sk_CONF_VALUE_value(values, i);
- unsigned afi, safi;
- int prefixlen, has_safi = 0;
unsigned char min[ADDR_RAW_BUF_LEN], max[ADDR_RAW_BUF_LEN];
+ unsigned afi, *safi = NULL, safi_;
char *s = val->value;
- int af;
+ int prefixlen, af;
if ( !strcmp(val->name, "ipv4")) {
afi = IANA_AFI_IPV4;
@@ -739,17 +728,17 @@ static void *v2i_IPAddrBlocks(struct v3_ext_method *method,
afi = IANA_AFI_IPV6;
} else if (!strcmp(val->name, "ipv4-safi")) {
afi = IANA_AFI_IPV4;
- has_safi = 1;
+ safi = &safi_;
} else if (!strcmp(val->name, "ipv6-safi")) {
afi = IANA_AFI_IPV6;
- has_safi = 1;
+ safi = &safi_;
} else {
X509V3err(X509V3_F_V2I_IPAddrBlocks, X509V3_R_EXTENSION_NAME_ERROR);
X509V3_conf_err(val);
goto err;
}
- if (has_safi) {
+ if (safi != NULL) {
safi = strtoul(val->value, &s, 0);
s += strspn(s, " \t");
if (safi > 0xFF || *s++ != ':') {
@@ -761,7 +750,7 @@ static void *v2i_IPAddrBlocks(struct v3_ext_method *method,
}
if (!strcmp(s, "inherit")) {
- if (addr_add_inherit(addr, afi, has_safi, safi))
+ if (addr_add_inherit(addr, afi, safi))
continue;
X509V3err(X509V3_F_V2I_IPAddrBlocks, X509V3_R_INVALID_INHERITANCE);
X509V3_conf_err(val);
@@ -795,7 +784,7 @@ static void *v2i_IPAddrBlocks(struct v3_ext_method *method,
case '/':
prefixlen = (int) strtoul(s, &s, 10);
if (*(s + strspn(s, " \t")) != '\0' ||
- !addr_add_prefix(addr, afi, has_safi, safi, min, prefixlen)) {
+ !addr_add_prefix(addr, afi, safi, min, prefixlen)) {
X509V3err(X509V3_F_V2I_IPAddrBlocks, X509V3_R_EXTENSION_VALUE_ERROR);
X509V3_conf_err(val);
goto err;
@@ -805,7 +794,7 @@ static void *v2i_IPAddrBlocks(struct v3_ext_method *method,
s += strspn(s, " \t");
if (inet_pton(af, s, max) != 1 ||
*(s + strspn(s, " \t")) != '\0' ||
- !addr_add_range(addr, afi, has_safi, safi, min, max)) {
+ !addr_add_range(addr, afi, safi, min, max)) {
X509V3err(X509V3_F_V2I_IPAddrBlocks, X509V3_R_EXTENSION_VALUE_ERROR);
X509V3_conf_err(val);
goto err;
@@ -834,6 +823,9 @@ static void *v2i_IPAddrBlocks(struct v3_ext_method *method,
return NULL;
}
+/*
+ * OpenSSL dispatch
+ */
X509V3_EXT_METHOD v3_addr = {
NID_IPAddrBlocks, /* nid */
0, /* flags */