From 3d7524ab7da01cab4d7dd3857e56fd11e82c061e Mon Sep 17 00:00:00 2001 From: Bob Halley Date: Fri, 8 Jul 2011 09:57:41 -0700 Subject: [PATCH] make IP address parsing stricter --- ChangeLog | 10 ++++++++++ dns/ipv4.py | 34 +++++++++++++++++----------------- dns/ipv6.py | 13 ++++++++++--- 3 files changed, 37 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index 94eca92a..08d93d83 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-07-08 Bob Halley + + * 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 * Old DNSSEC types (KEY, NXT, and SIG) have been removed. diff --git a/dns/ipv4.py b/dns/ipv4.py index 8d45b44e..ec7d2d24 100644 --- a/dns/ipv4.py +++ b/dns/ipv4.py @@ -15,22 +15,22 @@ """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 diff --git a/dns/ipv6.py b/dns/ipv6.py index 8363fe42..78fe82ec 100644 --- a/dns/ipv6.py +++ b/dns/ipv6.py @@ -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 '::' into ':'; if no match try to # turn '::' into ':' -- 2.47.3