From ce33a7b2f4748d980d15d530c745e34d55b4d532 Mon Sep 17 00:00:00 2001 From: vakarisz Date: Thu, 28 Jul 2022 11:29:43 +0300 Subject: [PATCH] Common: Improve network range validation (less regex) --- .../validators/ip_ranges.py | 66 +++++++++++++++---- 1 file changed, 53 insertions(+), 13 deletions(-) diff --git a/monkey/common/agent_configuration/validators/ip_ranges.py b/monkey/common/agent_configuration/validators/ip_ranges.py index 238ee215f..82207941a 100644 --- a/monkey/common/agent_configuration/validators/ip_ranges.py +++ b/monkey/common/agent_configuration/validators/ip_ranges.py @@ -1,24 +1,64 @@ import re +from ipaddress import AddressValueError, IPv4Address, IPv4Network, NetmaskValueError from marshmallow import ValidationError -ip_regex = r"((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" -cird_notation_regex = r"([0-9]|1[0-9]|2[0-9]|3[0-2])" -hostname_regex = r"([A-Za-z0-9]*[A-Za-z]+[A-Za-z0-9]*.?)*([A-Za-z0-9]*[A-Za-z]+[A-Za-z0-9]*)" +hostname_pattern = r"([A-Za-z0-9]*[A-Za-z]+[A-Za-z0-9]*.?)*([A-Za-z0-9]*[A-Za-z]+[A-Za-z0-9]*)" +hostname_regex = re.compile(hostname_pattern) def validate_subnet_range(subnet_range: str): - range_regexes = [ - "^" + ip_regex + "$|", - "^" + ip_regex + r"\s*-\s*" + ip_regex + "$|", - "^" + ip_regex + "/" + cird_notation_regex + "$|", - "^" + hostname_regex + "$", - ] - range_regexes = re.compile("".join(range_regexes)) - if not re.match(range_regexes, subnet_range): + try: + return validate_ip(subnet_range) + except ValidationError: + pass + + try: + return validate_ip_range(subnet_range) + except ValidationError: + pass + + try: + return validate_ip_network(subnet_range) + except ValidationError: + pass + + try: + return validate_hostname(subnet_range) + except ValidationError: raise ValidationError(f"Invalid subnet range {subnet_range}") +def validate_hostname(hostname: str): + match = re.match(hostname_regex, hostname) + if match and match.group() == hostname: + return + else: + raise ValidationError(f"Invalid hostname {hostname}") + + +def validate_ip_network(ip_network: str): + try: + IPv4Network(ip_network, strict=False) + return + except (NetmaskValueError, AddressValueError): + raise ValidationError(f"Invalid IPv4 network {ip_network}") + + +def validate_ip_range(ip_range: str): + try: + ip_range = ip_range.replace(" ", "") + ips = ip_range.split("-") + validate_ip(ips[0]) + validate_ip(ips[1]) + if len(ips) != 2: + raise ValidationError(f"Invalid IP range {ip_range}") + except (AddressValueError, IndexError): + raise ValidationError(f"Invalid IP range {ip_range}") + + def validate_ip(ip: str): - if not re.match(re.compile("".join(["^", ip_regex, "$"])), ip): - raise ValidationError(f"Invalid ip address {ip}") + try: + IPv4Address(ip) + except AddressValueError: + raise ValidationError(f"Invalid IP address {ip}")