From 6c92f670cb824700c34e04b1493215cd5aaae80d Mon Sep 17 00:00:00 2001 From: Michael Chisholm Date: Thu, 13 Aug 2020 16:22:24 -0400 Subject: [PATCH] Fix ipv4/6 special canonicalizers to reformat IP addresses even when a non-CIDR address is used. Before, it left plain IP addresses untouched. --- .../patterns/transform/specials.py | 88 +++++++++++-------- 1 file changed, 50 insertions(+), 38 deletions(-) diff --git a/stix2/equivalence/patterns/transform/specials.py b/stix2/equivalence/patterns/transform/specials.py index c565e27..0eba091 100644 --- a/stix2/equivalence/patterns/transform/specials.py +++ b/stix2/equivalence/patterns/transform/specials.py @@ -124,15 +124,20 @@ def ipv4_addr(comp_expr): if _path_is(comp_expr.lhs, ("value",)): value = comp_expr.rhs.value slash_idx = value.find("/") + is_cidr = slash_idx >= 0 - if 0 <= slash_idx < len(value)-1: + if is_cidr: ip_str = value[:slash_idx] - try: - ip_bytes = socket.inet_aton(ip_str) - except OSError: - # illegal IPv4 address string - return + else: + ip_str = value + try: + ip_bytes = socket.inet_aton(ip_str) + except OSError: + # illegal IPv4 address string + return + + if is_cidr: try: prefix_size = int(value[slash_idx+1:]) except ValueError: @@ -143,22 +148,23 @@ def ipv4_addr(comp_expr): # illegal prefix size return - if prefix_size == 32: - # Drop the "32" since it's redundant. Run the address bytes - # through inet_ntoa() in case it would adjust the format (e.g. - # drop leading zeros: 1.2.3.004 => 1.2.3.4). - value = socket.inet_ntoa(ip_bytes) + if not is_cidr or prefix_size == 32: + # If a CIDR with prefix size 32, drop the prefix size since it's + # redundant. Run the address bytes through inet_ntoa() in case it + # would adjust the format (e.g. drop leading zeros: + # 1.2.3.004 => 1.2.3.4). + value = socket.inet_ntoa(ip_bytes) - else: - # inet_aton() gives an immutable 'bytes' value; we need a value - # we can change. - ip_bytes = bytearray(ip_bytes) - _mask_bytes(ip_bytes, prefix_size) + else: + # inet_aton() gives an immutable 'bytes' value; we need a value + # we can change. + ip_bytes = bytearray(ip_bytes) + _mask_bytes(ip_bytes, prefix_size) - ip_str = socket.inet_ntoa(ip_bytes) - value = ip_str + "/" + str(prefix_size) + ip_str = socket.inet_ntoa(ip_bytes) + value = ip_str + "/" + str(prefix_size) - comp_expr.rhs.value = value + comp_expr.rhs.value = value def ipv6_addr(comp_expr): @@ -178,15 +184,20 @@ def ipv6_addr(comp_expr): if _path_is(comp_expr.lhs, ("value",)): value = comp_expr.rhs.value slash_idx = value.find("/") + is_cidr = slash_idx >= 0 - if 0 <= slash_idx < len(value)-1: + if is_cidr: ip_str = value[:slash_idx] - try: - ip_bytes = socket.inet_pton(socket.AF_INET6, ip_str) - except OSError: - # illegal IPv6 address string - return + else: + ip_str = value + try: + ip_bytes = socket.inet_pton(socket.AF_INET6, ip_str) + except OSError: + # illegal IPv6 address string + return + + if is_cidr: try: prefix_size = int(value[slash_idx+1:]) except ValueError: @@ -197,19 +208,20 @@ def ipv6_addr(comp_expr): # illegal prefix size return - if prefix_size == 128: - # Drop the "128" since it's redundant. Run the IP address - # through inet_ntop() so it can reformat with the double-colons - # (and make any other adjustments) if necessary. - value = socket.inet_ntop(socket.AF_INET6, ip_bytes) + if not is_cidr or prefix_size == 128: + # If a CIDR with prefix size 128, drop the prefix size since it's + # redundant. Run the IP address through inet_ntop() so it can + # reformat with the double-colons (and make any other adjustments) + # if necessary. + value = socket.inet_ntop(socket.AF_INET6, ip_bytes) - else: - # inet_pton() gives an immutable 'bytes' value; we need a value - # we can change. - ip_bytes = bytearray(ip_bytes) - _mask_bytes(ip_bytes, prefix_size) + else: + # inet_pton() gives an immutable 'bytes' value; we need a value + # we can change. + ip_bytes = bytearray(ip_bytes) + _mask_bytes(ip_bytes, prefix_size) - ip_str = socket.inet_ntop(socket.AF_INET6, ip_bytes) - value = ip_str + "/" + str(prefix_size) + ip_str = socket.inet_ntop(socket.AF_INET6, ip_bytes) + value = ip_str + "/" + str(prefix_size) - comp_expr.rhs.value = value + comp_expr.rhs.value = value