make IP address parsing stricter
authorBob Halley <halley@nominum.com>
Fri, 8 Jul 2011 16:57:41 +0000 (09:57 -0700)
committerBob Halley <halley@nominum.com>
Fri, 8 Jul 2011 16:57:41 +0000 (09:57 -0700)
ChangeLog
dns/ipv4.py
dns/ipv6.py

index 94eca92aa6e6e7ff295c96e6d3c496167b9ad9c3..08d93d83c398fb2db3a0bb756932f461f639cc2c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2011-07-08  Bob Halley  <halley@dnspython.org>
+
+       * dns/ipv4.py: dnspython now provides its own, stricter, versions
+         of IPv4 inet_ntoa() and inet_aton() instead of using the OS's
+         versions.
+
+       * dns/ipv6.py: inet_aton() now bounds checks embedded IPv4 addresses
+         more strictly.  Also, now only dns.exception.SyntaxError can be
+         raised on bad input.
+
 2011-04-05  Bob Halley  <halley@dnspython.org>
 
        * Old DNSSEC types (KEY, NXT, and SIG) have been removed.
index 8d45b44e316d76cd63b8244b45bfedeb22e3724d..ec7d2d24699b8b8e4c555d9d9a133568f2960bb6 100644 (file)
 
 """IPv4 helper functions."""
 
-import socket
-import sys
+import struct
 
-if sys.hexversion < 0x02030000 or sys.platform == 'win32':
-    #
-    # Some versions of Python 2.2 have an inet_aton which rejects
-    # the valid IP address '255.255.255.255'.  It appears this
-    # problem is still present on the Win32 platform even in 2.3.
-    # We'll work around the problem.
-    #
-    def inet_aton(text):
-        if text == '255.255.255.255':
-            return '\xff' * 4
-        else:
-            return socket.inet_aton(text)
-else:
-    inet_aton = socket.inet_aton
+import dns.exception
 
-inet_ntoa = socket.inet_ntoa
+def inet_ntoa(address):
+    if len(address) != 4:
+        raise dns.exception.SyntaxError
+    return '%u.%u.%u.%u' % (ord(address[0]), ord(address[1]),
+                            ord(address[2]), ord(address[3]))
+
+def inet_aton(text):
+    parts = text.split('.')
+    if len(parts) != 4:
+        raise dns.exception.SyntaxError
+    try:
+        bytes = [int(part) for part in parts]
+        return struct.pack('BBBB', *bytes)
+    except:
+        raise dns.exception.SyntaxError
index 8363fe42cc445a73751e3484d7881a8e8d01dc9a..78fe82ece56078c6cf4cb4b0dca47a172ac21eae 100644 (file)
@@ -113,9 +113,16 @@ def inet_aton(text):
     #
     m = _v4_ending.match(text)
     if not m is None:
-        text = "%s:%04x:%04x" % (m.group(1),
-                                 int(m.group(2)) * 256 + int(m.group(3)),
-                                 int(m.group(4)) * 256 + int(m.group(5)))
+        try:
+            b1 = int(m.group(2))
+            b2 = int(m.group(3))
+            b3 = int(m.group(4))
+            b4 = int(m.group(5))
+        except:
+            raise dns.exception.SyntaxError
+        if b1 > 255 or b2 > 255 or b3 > 255 or b4 > 255:
+            raise dns.exception.SyntaxError
+        text = "%s:%04x:%04x" % (m.group(1), b1 * 256 + b2, b3 * 256 + b4)
     #
     # Try to turn '::<whatever>' into ':<whatever>'; if no match try to
     # turn '<whatever>::' into '<whatever>:'