Skip to content

Commit 95911d9

Browse files
committed
Extend checks for IPv6 addresses
- Make sure enclosing brackets match. - Use the built-in classes/checks for the IPv6/IPv4 address format. - Extend tests to bad cases Signed-off-by: Ivan Kanakarakis <[email protected]>
1 parent 9bc9e57 commit 95911d9

File tree

2 files changed

+33
-40
lines changed

2 files changed

+33
-40
lines changed

src/saml2/validate.py

Lines changed: 16 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
import struct
55
import base64
66
import time
7+
from ipaddress import AddressValueError
8+
from ipaddress import IPv4Address
9+
from ipaddress import IPv6Address
710

811
from saml2 import time_util
912

@@ -112,57 +115,30 @@ def validate_before(not_before, slack):
112115

113116

114117
def valid_address(address):
118+
"""Validate IPv4/IPv6 addresses."""
115119
if not (valid_ipv4(address) or valid_ipv6(address)):
116120
raise NotValid("address")
117121
return True
118122

119123

120124
def valid_ipv4(address):
121-
parts = address.split(".")
122-
if len(parts) != 4:
125+
"""Validate IPv4 addresses."""
126+
try:
127+
IPv4Address(address)
128+
except AddressValueError:
123129
return False
124-
for item in parts:
125-
try:
126-
if not 0 <= int(item) <= 255:
127-
raise NotValid("ipv4")
128-
except ValueError:
129-
return False
130130
return True
131131

132-
#
133-
IPV6_PATTERN = re.compile(r"""
134-
^
135-
\s* # Leading whitespace
136-
\[? # See https://tools.ietf.org/html/rfc4038#section-5.1
137-
(?!.*::.*::) # Only a single wildcard allowed
138-
(?:(?!:)|:(?=:)) # Colon iff it would be part of a wildcard
139-
(?: # Repeat 6 times:
140-
[0-9a-f]{0,4} # A group of at most four hexadecimal digits
141-
(?:(?<=::)|(?<!::):) # Colon unless preceeded by wildcard
142-
){6} #
143-
(?: # Either
144-
[0-9a-f]{0,4} # Another group
145-
(?:(?<=::)|(?<!::):) # Colon unless preceeded by wildcard
146-
[0-9a-f]{0,4} # Last group
147-
(?: (?<=::) # Colon iff preceeded by exacly one colon
148-
| (?<!:) #
149-
| (?<=:) (?<!::) : #
150-
) # OR
151-
| # A v4 address with NO leading zeros
152-
(?:25[0-4]|2[0-4]\d|1\d\d|[1-9]?\d)
153-
(?: \.
154-
(?:25[0-4]|2[0-4]\d|1\d\d|[1-9]?\d)
155-
){3}
156-
)
157-
\]? # See https://tools.ietf.org/html/rfc4038#section-5.1
158-
\s* # Trailing whitespace
159-
$
160-
""", re.VERBOSE | re.IGNORECASE | re.DOTALL)
161-
162132

163133
def valid_ipv6(address):
164-
"""Validates IPv6 addresses. """
165-
return IPV6_PATTERN.match(address) is not None
134+
"""Validate IPv6 addresses."""
135+
is_enclosed_in_brackets = address.startswith("[") and address.endswith("]")
136+
address_raw = address[1:-1] if is_enclosed_in_brackets else address
137+
try:
138+
IPv6Address(address_raw)
139+
except AddressValueError:
140+
return False
141+
return True
166142

167143

168144
def valid_boolean(val):

tests/test_13_validate.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,27 @@ def test_valid_anytype():
121121
assert valid_anytype("P1Y2M3DT10H30M")
122122
assert valid_anytype("urn:oasis:names:tc:SAML:2.0:attrname-format:uri")
123123

124+
124125
def test_valid_address():
125126
assert valid_address("130.239.16.3")
126127
assert valid_address("2001:8003:5555:9999:555a:5555:c77:d5c5")
128+
assert valid_address("2001:8003:5555::555a:5555:c77:d5c5")
127129

128130
# See https://tools.ietf.org/html/rfc4038#section-5.1 regarding
129131
# the inclusion of brackets in the ipv6 address below.
130132
assert valid_address("[2001:8003:5555:9999:555a:5555:c77:d5c5]")
133+
134+
with raises(NotValid):
135+
assert valid_address("127.0.0.256")
136+
with raises(NotValid):
137+
assert valid_address("127.0.0.")
138+
with raises(NotValid):
139+
assert valid_address("127.0.0")
140+
with raises(NotValid):
141+
assert valid_address("2001::5555:9999::5555:c77:d5c5]")
142+
with raises(NotValid):
143+
assert valid_address("2001:8003:5555:9999:555a:5555:c77:d5c5]")
144+
with raises(NotValid):
145+
assert valid_address("[2001:8003:5555:9999:555a:5555:c77:d5c5")
146+
with raises(NotValid):
147+
assert valid_address("[[2001:8003:5555:9999:555a:5555:c77:d5c5]")

0 commit comments

Comments
 (0)