389-ds-base/SOURCES/0004-Issue-6825-RootDN-Access-Control-Plugin-with-wildcar.patch

126 lines
4.4 KiB
Diff

From 5613937623f0037a54490b22c60f7eb1aa52cf4e Mon Sep 17 00:00:00 2001
From: James Chapman <jachapma@redhat.com>
Date: Wed, 25 Jun 2025 14:11:05 +0000
Subject: [PATCH] =?UTF-8?q?Issue=206825=20-=20RootDN=20Access=20Control=20?=
=?UTF-8?q?Plugin=20with=20wildcards=20for=20IP=20addre=E2=80=A6=20(#6826)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Bug description:
RootDN Access Control Plugin with wildcards for IP addresses fails withi
an error "Invalid IP address"
socket.inet_aton() validates IPv4 IP addresses and does not support wildcards.
Fix description:
Add a regex pattern to match wildcard IP addresses, check each octet is
between 0-255
Fixes: https://github.com/389ds/389-ds-base/issues/6825
Reviewed by: @droideck (Thank you)
---
.../lib389/cli_conf/plugins/rootdn_ac.py | 16 +++-----
src/lib389/lib389/utils.py | 40 +++++++++++++++++++
2 files changed, 45 insertions(+), 11 deletions(-)
diff --git a/src/lib389/lib389/cli_conf/plugins/rootdn_ac.py b/src/lib389/lib389/cli_conf/plugins/rootdn_ac.py
index 65486fff8..1456f5ebe 100644
--- a/src/lib389/lib389/cli_conf/plugins/rootdn_ac.py
+++ b/src/lib389/lib389/cli_conf/plugins/rootdn_ac.py
@@ -8,7 +8,7 @@
import socket
from lib389.plugins import RootDNAccessControlPlugin
-from lib389.utils import is_valid_hostname
+from lib389.utils import is_valid_hostname, is_valid_ip
from lib389.cli_conf import add_generic_plugin_parsers, generic_object_edit
from lib389.cli_base import CustomHelpFormatter
@@ -62,19 +62,13 @@ def validate_args(args):
if args.allow_ip is not None:
for ip in args.allow_ip:
- if ip != "delete":
- try:
- socket.inet_aton(ip)
- except socket.error:
- raise ValueError(f"Invalid IP address ({ip}) for '--allow-ip'")
+ if ip != "delete" and not is_valid_ip(ip):
+ raise ValueError(f"Invalid IP address ({ip}) for '--allow-ip'")
if args.deny_ip is not None and args.deny_ip != "delete":
for ip in args.deny_ip:
- if ip != "delete":
- try:
- socket.inet_aton(ip)
- except socket.error:
- raise ValueError(f"Invalid IP address ({ip}) for '--deny-ip'")
+ if ip != "delete" and not is_valid_ip(ip):
+ raise ValueError(f"Invalid IP address ({ip}) for '--deny-ip'")
if args.allow_host is not None:
for hostname in args.allow_host:
diff --git a/src/lib389/lib389/utils.py b/src/lib389/lib389/utils.py
index afc282e94..3937fc1a8 100644
--- a/src/lib389/lib389/utils.py
+++ b/src/lib389/lib389/utils.py
@@ -31,6 +31,7 @@ import logging
import shutil
import ldap
import socket
+import ipaddress
import time
import stat
from datetime import (datetime, timedelta)
@@ -1707,6 +1708,45 @@ def is_valid_hostname(hostname):
allowed = re.compile(r"(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE)
return all(allowed.match(x) for x in hostname.split("."))
+def is_valid_ip(ip):
+ """ Validate an IPv4 or IPv6 address, including asterisks for wildcards. """
+ if '*' in ip and '.' in ip:
+ ipv4_pattern = r'^(\d{1,3}|\*)\.(\d{1,3}|\*)\.(\d{1,3}|\*)\.(\d{1,3}|\*)$'
+ if re.match(ipv4_pattern, ip):
+ octets = ip.split('.')
+ for octet in octets:
+ if octet != '*':
+ try:
+ val = int(octet, 10)
+ if not (0 <= val <= 255):
+ return False
+ except ValueError:
+ return False
+ return True
+ else:
+ return False
+
+ if '*' in ip and ':' in ip:
+ ipv6_pattern = r'^([0-9a-fA-F]{1,4}|\*)(:([0-9a-fA-F]{1,4}|\*)){0,7}$'
+ if re.match(ipv6_pattern, ip):
+ octets = ip.split(':')
+ for octet in octets:
+ if octet != '*':
+ try:
+ val = int(octet, 16)
+ if not (0 <= val <= 0xFFFF):
+ return False
+ except ValueError:
+ return False
+ return True
+ else:
+ return False
+
+ try:
+ ipaddress.ip_address(ip)
+ return True
+ except ValueError:
+ return False
def parse_size(size):
"""
--
2.49.0