PR: 2482
authorDr. Stephen Henson <steve@openssl.org>
Sun, 9 Oct 2011 00:56:52 +0000 (00:56 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Sun, 9 Oct 2011 00:56:52 +0000 (00:56 +0000)
Submitted by: Rob Austein <sra@hactrn.net>
Reviewed by: steve

Don't allow inverted ranges in RFC3779 code, discovered by Frank Ellermann.

crypto/x509v3/v3_addr.c

index 0d70e86..76a5722 100644 (file)
@@ -383,6 +383,7 @@ static int range_should_be_prefix(const unsigned char *min,
   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--)
@@ -800,14 +801,16 @@ int v3_addr_is_canonical(IPAddrBlocks *addr)
     }
 
     /*
-     * 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) {
+      if (a != NULL && 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 (memcmp(a_min, a_max, length) > 0 ||
+           range_should_be_prefix(a_min, a_max, length) >= 0)
          return 0;
       }
     }
@@ -844,6 +847,13 @@ static int IPAddressOrRanges_canonize(IPAddressOrRanges *aors,
     extract_min_max(a, a_min, a_max, length);
     extract_min_max(b, b_min, b_max, length);
 
+    /*
+     * Punt inverted ranges.
+     */
+    if (memcmp(a_min, a_max, length) > 0 ||
+       memcmp(b_min, b_max, length) > 0)
+      return 0;
+
     /*
      * Punt overlaps.
      */
@@ -869,6 +879,20 @@ static int IPAddressOrRanges_canonize(IPAddressOrRanges *aors,
     }
   }
 
+  /*
+   * 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;
 }
 
@@ -1017,6 +1041,11 @@ static void *v2i_IPAddrBlocks(const struct v3_ext_method *method,
        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;