Index: openssl/crypto/x509v3/v3_addr.c |
=================================================================== |
--- openssl/crypto/x509v3/v3_addr.c (revision 105093) |
+++ openssl/crypto/x509v3/v3_addr.c (working copy) |
@@ -142,12 +142,13 @@ |
* 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, |
+static int 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 || bs->length > length) |
+ return 0; |
if (bs->length > 0) { |
memcpy(addr, bs->data, bs->length); |
if ((bs->flags & 7) != 0) { |
@@ -159,6 +160,7 @@ |
} |
} |
memset(addr + bs->length, fill, length - bs->length); |
+ return 1; |
} |
/* |
@@ -177,13 +179,17 @@ |
unsigned char addr[ADDR_RAW_BUF_LEN]; |
int i, n; |
+ if (bs->length < 0) |
+ return 0; |
switch (afi) { |
case IANA_AFI_IPV4: |
- addr_expand(addr, bs, 4, fill); |
+ if (!addr_expand(addr, bs, 4, fill)) |
+ return 0; |
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); |
+ if (!addr_expand(addr, bs, 16, fill)) |
+ return 0; |
for (n = 16; n > 1 && addr[n-1] == 0x00 && addr[n-2] == 0x00; n -= 2) |
; |
for (i = 0; i < n; i += 2) |
@@ -236,7 +242,7 @@ |
/* |
* i2r handler for an IPAddrBlocks extension. |
*/ |
-static int i2r_IPAddrBlocks(X509V3_EXT_METHOD *method, |
+static int i2r_IPAddrBlocks(const X509V3_EXT_METHOD *method, |
void *ext, |
BIO *out, |
int indent) |
@@ -309,34 +315,43 @@ |
/* |
* Sort comparison function for a sequence of IPAddressOrRange |
* elements. |
+ * |
+ * There's no sane answer we can give if addr_expand() fails, and an |
+ * assertion failure on externally supplied data is seriously uncool, |
+ * so we just arbitrarily declare that if given invalid inputs this |
+ * function returns -1. If this messes up your preferred sort order |
+ * for garbage input, tough noogies. |
*/ |
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 prefixlen_a = 0, prefixlen_b = 0; |
int r; |
switch (a->type) { |
case IPAddressOrRange_addressPrefix: |
- addr_expand(addr_a, a->u.addressPrefix, length, 0x00); |
+ if (!addr_expand(addr_a, a->u.addressPrefix, length, 0x00)) |
+ return -1; |
prefixlen_a = addr_prefixlen(a->u.addressPrefix); |
break; |
case IPAddressOrRange_addressRange: |
- addr_expand(addr_a, a->u.addressRange->min, length, 0x00); |
+ if (!addr_expand(addr_a, a->u.addressRange->min, length, 0x00)) |
+ return -1; |
prefixlen_a = length * 8; |
break; |
} |
switch (b->type) { |
case IPAddressOrRange_addressPrefix: |
- addr_expand(addr_b, b->u.addressPrefix, length, 0x00); |
+ if (!addr_expand(addr_b, b->u.addressPrefix, length, 0x00)) |
+ return -1; |
prefixlen_b = addr_prefixlen(b->u.addressPrefix); |
break; |
case IPAddressOrRange_addressRange: |
- addr_expand(addr_b, b->u.addressRange->min, length, 0x00); |
+ if (!addr_expand(addr_b, b->u.addressRange->min, length, 0x00)) |
+ return -1; |
prefixlen_b = length * 8; |
break; |
} |
@@ -378,6 +393,7 @@ |
unsigned char mask; |
int i, j; |
+ OPENSSL_assert(memcmp(min, max, length) <= 0); |
for (i = 0; i < length && min[i] == max[i]; i++) |
; |
for (j = length - 1; j >= 0 && min[j] == 0x00 && max[j] == 0xFF; j--) |
@@ -596,10 +612,10 @@ |
return NULL; |
switch (afi) { |
case IANA_AFI_IPV4: |
- (void)sk_IPAddressOrRange_set_cmp_func(aors, v4IPAddressOrRange_cmp); |
+ (void) sk_IPAddressOrRange_set_cmp_func(aors, v4IPAddressOrRange_cmp); |
break; |
case IANA_AFI_IPV6: |
- (void)sk_IPAddressOrRange_set_cmp_func(aors, v6IPAddressOrRange_cmp); |
+ (void) sk_IPAddressOrRange_set_cmp_func(aors, v6IPAddressOrRange_cmp); |
break; |
} |
f->ipAddressChoice->type = IPAddressChoice_addressesOrRanges; |
@@ -651,22 +667,22 @@ |
/* |
* Extract min and max values from an IPAddressOrRange. |
*/ |
-static void extract_min_max(IPAddressOrRange *aor, |
+static int extract_min_max(IPAddressOrRange *aor, |
unsigned char *min, |
unsigned char *max, |
int length) |
{ |
- OPENSSL_assert(aor != NULL && min != NULL && max != NULL); |
+ if (aor == NULL || min == NULL || max == NULL) |
+ return 0; |
switch (aor->type) { |
case IPAddressOrRange_addressPrefix: |
- addr_expand(min, aor->u.addressPrefix, length, 0x00); |
- addr_expand(max, aor->u.addressPrefix, length, 0xFF); |
- return; |
+ return (addr_expand(min, aor->u.addressPrefix, length, 0x00) && |
+ addr_expand(max, aor->u.addressPrefix, length, 0xFF)); |
case IPAddressOrRange_addressRange: |
- addr_expand(min, aor->u.addressRange->min, length, 0x00); |
- addr_expand(max, aor->u.addressRange->max, length, 0xFF); |
- return; |
+ return (addr_expand(min, aor->u.addressRange->min, length, 0x00) && |
+ addr_expand(max, aor->u.addressRange->max, length, 0xFF)); |
} |
+ return 0; |
} |
/* |
@@ -682,9 +698,10 @@ |
if (aor == NULL || min == NULL || max == NULL || |
afi_length == 0 || length < afi_length || |
(aor->type != IPAddressOrRange_addressPrefix && |
- aor->type != IPAddressOrRange_addressRange)) |
+ aor->type != IPAddressOrRange_addressRange) || |
+ !extract_min_max(aor, min, max, afi_length)) |
return 0; |
- extract_min_max(aor, min, max, afi_length); |
+ |
return afi_length; |
} |
@@ -766,8 +783,9 @@ |
IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); |
IPAddressOrRange *b = sk_IPAddressOrRange_value(aors, j + 1); |
- extract_min_max(a, a_min, a_max, length); |
- extract_min_max(b, b_min, b_max, length); |
+ if (!extract_min_max(a, a_min, a_max, length) || |
+ !extract_min_max(b, b_min, b_max, length)) |
+ return 0; |
/* |
* Punt misordered list, overlapping start, or inverted range. |
@@ -795,15 +813,18 @@ |
} |
/* |
- * Check final range to see if it should be a prefix. |
+ * Check range to see if it's inverted or should be a |
+ * prefix. |
*/ |
j = sk_IPAddressOrRange_num(aors) - 1; |
{ |
IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); |
- if (a->type == IPAddressOrRange_addressRange) { |
- extract_min_max(a, a_min, a_max, length); |
- if (range_should_be_prefix(a_min, a_max, length) >= 0) |
+ if (a != NULL && a->type == IPAddressOrRange_addressRange) { |
+ if (!extract_min_max(a, a_min, a_max, length)) |
return 0; |
+ if (memcmp(a_min, a_max, length) > 0 || |
+ range_should_be_prefix(a_min, a_max, length) >= 0) |
+ return 0; |
} |
} |
} |
@@ -836,10 +857,18 @@ |
unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; |
unsigned char b_min[ADDR_RAW_BUF_LEN], b_max[ADDR_RAW_BUF_LEN]; |
- extract_min_max(a, a_min, a_max, length); |
- extract_min_max(b, b_min, b_max, length); |
+ if (!extract_min_max(a, a_min, a_max, length) || |
+ !extract_min_max(b, b_min, b_max, length)) |
+ return 0; |
/* |
+ * Punt inverted ranges. |
+ */ |
+ if (memcmp(a_min, a_max, length) > 0 || |
+ memcmp(b_min, b_max, length) > 0) |
+ return 0; |
+ |
+ /* |
* Punt overlaps. |
*/ |
if (memcmp(a_max, b_min, length) >= 0) |
@@ -855,8 +884,8 @@ |
IPAddressOrRange *merged; |
if (!make_addressRange(&merged, a_min, b_max, length)) |
return 0; |
- sk_IPAddressOrRange_set(aors, i, merged); |
- (void)sk_IPAddressOrRange_delete(aors, i + 1); |
+ (void) sk_IPAddressOrRange_set(aors, i, merged); |
+ (void) sk_IPAddressOrRange_delete(aors, i + 1); |
IPAddressOrRange_free(a); |
IPAddressOrRange_free(b); |
--i; |
@@ -864,6 +893,20 @@ |
} |
} |
+ /* |
+ * Check for inverted final range. |
+ */ |
+ j = sk_IPAddressOrRange_num(aors) - 1; |
+ { |
+ IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); |
+ if (a != NULL && a->type == IPAddressOrRange_addressRange) { |
+ unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; |
+ extract_min_max(a, a_min, a_max, length); |
+ if (memcmp(a_min, a_max, length) > 0) |
+ return 0; |
+ } |
+ } |
+ |
return 1; |
} |
@@ -880,7 +923,7 @@ |
v3_addr_get_afi(f))) |
return 0; |
} |
- (void)sk_IPAddressFamily_set_cmp_func(addr, IPAddressFamily_cmp); |
+ (void) sk_IPAddressFamily_set_cmp_func(addr, IPAddressFamily_cmp); |
sk_IPAddressFamily_sort(addr); |
OPENSSL_assert(v3_addr_is_canonical(addr)); |
return 1; |
@@ -889,7 +932,7 @@ |
/* |
* v2i handler for the IPAddrBlocks extension. |
*/ |
-static void *v2i_IPAddrBlocks(struct v3_ext_method *method, |
+static void *v2i_IPAddrBlocks(const struct v3_ext_method *method, |
struct v3_ext_ctx *ctx, |
STACK_OF(CONF_VALUE) *values) |
{ |
@@ -1012,6 +1055,11 @@ |
X509V3_conf_err(val); |
goto err; |
} |
+ if (memcmp(min, max, length_from_afi(afi)) > 0) { |
+ X509V3err(X509V3_F_V2I_IPADDRBLOCKS, X509V3_R_EXTENSION_VALUE_ERROR); |
+ X509V3_conf_err(val); |
+ goto err; |
+ } |
if (!v3_addr_add_range(addr, afi, safi, min, max)) { |
X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE); |
goto err; |
@@ -1097,13 +1145,15 @@ |
p = 0; |
for (c = 0; c < sk_IPAddressOrRange_num(child); c++) { |
- extract_min_max(sk_IPAddressOrRange_value(child, c), |
- c_min, c_max, length); |
+ if (!extract_min_max(sk_IPAddressOrRange_value(child, c), |
+ c_min, c_max, length)) |
+ return -1; |
for (;; p++) { |
if (p >= sk_IPAddressOrRange_num(parent)) |
return 0; |
- extract_min_max(sk_IPAddressOrRange_value(parent, p), |
- p_min, p_max, length); |
+ if (!extract_min_max(sk_IPAddressOrRange_value(parent, p), |
+ p_min, p_max, length)) |
+ return 0; |
if (memcmp(p_max, c_max, length) < 0) |
continue; |
if (memcmp(p_min, c_min, length) > 0) |
@@ -1125,7 +1175,7 @@ |
return 1; |
if (b == NULL || v3_addr_inherits(a) || v3_addr_inherits(b)) |
return 0; |
- (void)sk_IPAddressFamily_set_cmp_func(b, IPAddressFamily_cmp); |
+ (void) sk_IPAddressFamily_set_cmp_func(b, IPAddressFamily_cmp); |
for (i = 0; i < sk_IPAddressFamily_num(a); i++) { |
IPAddressFamily *fa = sk_IPAddressFamily_value(a, i); |
int j = sk_IPAddressFamily_find(b, fa); |
@@ -1167,7 +1217,7 @@ |
{ |
IPAddrBlocks *child = NULL; |
int i, j, ret = 1; |
- X509 *x = NULL; |
+ X509 *x; |
OPENSSL_assert(chain != NULL && sk_X509_num(chain) > 0); |
OPENSSL_assert(ctx != NULL || ext != NULL); |
@@ -1180,6 +1230,7 @@ |
*/ |
if (ext != NULL) { |
i = -1; |
+ x = NULL; |
} else { |
i = 0; |
x = sk_X509_value(chain, i); |
@@ -1189,7 +1240,7 @@ |
} |
if (!v3_addr_is_canonical(ext)) |
validation_err(X509_V_ERR_INVALID_EXTENSION); |
- (void)sk_IPAddressFamily_set_cmp_func(ext, IPAddressFamily_cmp); |
+ (void) sk_IPAddressFamily_set_cmp_func(ext, IPAddressFamily_cmp); |
if ((child = sk_IPAddressFamily_dup(ext)) == NULL) { |
X509V3err(X509V3_F_V3_ADDR_VALIDATE_PATH_INTERNAL, ERR_R_MALLOC_FAILURE); |
ret = 0; |
@@ -1215,7 +1266,7 @@ |
} |
continue; |
} |
- (void)sk_IPAddressFamily_set_cmp_func(x->rfc3779_addr, IPAddressFamily_cmp); |
+ (void) sk_IPAddressFamily_set_cmp_func(x->rfc3779_addr, IPAddressFamily_cmp); |
for (j = 0; j < sk_IPAddressFamily_num(child); j++) { |
IPAddressFamily *fc = sk_IPAddressFamily_value(child, j); |
int k = sk_IPAddressFamily_find(x->rfc3779_addr, fc); |
@@ -1242,6 +1293,7 @@ |
/* |
* Trust anchor can't inherit. |
*/ |
+ OPENSSL_assert(x != NULL); |
if (x->rfc3779_addr != NULL) { |
for (j = 0; j < sk_IPAddressFamily_num(x->rfc3779_addr); j++) { |
IPAddressFamily *fp = sk_IPAddressFamily_value(x->rfc3779_addr, j); |