summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamian Johnson <atagar@torproject.org>2014-12-06 12:50:14 -0800
committerDamian Johnson <atagar@torproject.org>2014-12-06 12:50:14 -0800
commit91f6c3bb2a5a4f4bb9a822f1280a4c250aeacdcd (patch)
tree97ff87288d84a380676395c0cac894684c4f7d77
parent90bb28f44929bcb33b321eb51a27bb247c4ae6ab (diff)
Don't use the socket module to validate that IP addresses are valid
This largely reverts commit 25771fe. Evidently the socket builtin doens't always know what an IPv6 address looks like... https://trac.torproject.org/projects/tor/ticket/13904
-rw-r--r--stem/util/connection.py43
1 files changed, 33 insertions, 10 deletions
diff --git a/stem/util/connection.py b/stem/util/connection.py
index df918d2d..f5ca3f4d 100644
--- a/stem/util/connection.py
+++ b/stem/util/connection.py
@@ -46,7 +46,6 @@ import hmac
import os
import platform
import re
-import socket
import stem.util.proc
import stem.util.system
@@ -334,12 +333,23 @@ def is_valid_ipv4_address(address):
:returns: **True** if input is a valid IPv4 address, **False** otherwise
"""
- try:
- packed = socket.inet_pton(socket.AF_INET, address)
- return socket.inet_ntop(socket.AF_INET, packed) == address
- except (TypeError, socket.error):
+ if not isinstance(address, (bytes, unicode)):
return False
+ # checks if theres four period separated values
+
+ if address.count('.') != 3:
+ return False
+
+ # checks that each value in the octet are decimal values between 0-255
+ for entry in address.split('.'):
+ if not entry.isdigit() or int(entry) < 0 or int(entry) > 255:
+ return False
+ elif entry[0] == '0' and len(entry) > 1:
+ return False # leading zeros, for instance in '1.2.3.001'
+
+ return True
+
def is_valid_ipv6_address(address, allow_brackets = False):
"""
@@ -355,11 +365,24 @@ def is_valid_ipv6_address(address, allow_brackets = False):
if address.startswith('[') and address.endswith(']'):
address = address[1:-1]
- try:
- socket.inet_pton(socket.AF_INET6, address)
- return True
- except (TypeError, socket.error):
- return False
+ # addresses are made up of eight colon separated groups of four hex digits
+ # with leading zeros being optional
+ # https://en.wikipedia.org/wiki/IPv6#Address_format
+
+ colon_count = address.count(':')
+
+ if colon_count > 7:
+ return False # too many groups
+ elif colon_count != 7 and '::' not in address:
+ return False # not enough groups and none are collapsed
+ elif address.count('::') > 1 or ':::' in address:
+ return False # multiple groupings of zeros can't be collapsed
+
+ for entry in address.split(':'):
+ if not re.match('^[0-9a-fA-f]{0,4}$', entry):
+ return False
+
+ return True
def is_valid_port(entry, allow_zero = False):