Fix IPv6 hostname matching for alwaysresolve access rules
Some checks failed
webmin.dev: webmin/webmin / build (push) Has been cancelled

* Note: Fix Miniserv IPv6 hostname resolution and matching used by access control when `alwaysresolve` is enabled:
  1. Correct `to_ip6address()` success handling (before getaddrinfo result was interpreted backwards)
  2. In `ip_match()`, resolve hostnames with `to_ip6address()` for IPv6 clients instead of IPv4-only `to_ipaddress()`
  3. Canonicalize IPv6 addresses before reverse and forward verification to avoid format-based mismatches.
  4. Mirror the IPv6 logic change in "webmin/webmin-lib.pl"

https://forum.virtualmin.com/t/webmin-access-control-for-domain-names-with-ipv6/136661?u=ilia
This commit is contained in:
Ilia Ross
2026-02-21 13:30:08 +02:00
parent 209a2cbbc3
commit 2397653d55
2 changed files with 27 additions and 5 deletions

View File

@@ -2989,7 +2989,10 @@ if ($needhn && !defined($hn = $ip_match_cache{$_[0]})) {
# Reverse-lookup hostname if any rules match based on it
$hn = &to_hostname($_[0]);
if (&check_ip6address($_[0])) {
$hn = "" if (&to_ip6address($hn) ne $_[0]);
local $ip6 = &to_ip6address($hn);
$hn = "" if (!$ip6 ||
&canonicalize_ip6($ip6) ne
&canonicalize_ip6($_[0]));
}
else {
$hn = "" if (&to_ipaddress($hn) ne $_[0]);
@@ -3084,7 +3087,15 @@ for($i=2; $i<@_; $i++) {
}
elsif ($_[$i] !~ /^[0-9\.]+$/) {
# Compare with hostname
$mismatch = 1 if ($_[0] ne &to_ipaddress($_[$i]));
if (&check_ip6address($_[0])) {
local $ip6 = &to_ip6address($_[$i]);
$mismatch = 1 if (!$ip6 ||
&canonicalize_ip6($ip6) ne
&canonicalize_ip6($_[0]));
}
else {
$mismatch = 1 if ($_[0] ne &to_ipaddress($_[$i]));
}
}
return 1 if (!$mismatch);
}
@@ -3195,7 +3206,7 @@ foreach $i (@_) {
(undef, undef, undef, $inaddr) =
getaddrinfo($i, undef, AF_INET6(), SOCK_STREAM);
};
if ($inaddr) {
if (!$inaddr) {
push(@rv, undef);
}
else {

View File

@@ -1628,7 +1628,10 @@ my @io = &check_ip6address($_[0]) ? split(/:/, $_[0])
# Resolve to hostname and check that it forward resolves again
my $hn = &to_hostname($_[0]);
if (&check_ip6address($_[0])) {
$hn = "" if (&to_ip6address($hn) ne $_[0]);
my $ip6 = &to_ip6address($hn);
$hn = "" if (!$ip6 ||
&canonicalize_ip6($ip6) ne
&canonicalize_ip6($_[0]));
}
else {
$hn = "" if (&to_ipaddress($hn) ne $_[0]);
@@ -1703,7 +1706,15 @@ for(my $i=1; $i<@_; $i++) {
}
elsif ($_[$i] !~ /^[0-9\.]+$/) {
# Compare with hostname
$mismatch = 1 if ($_[0] ne &to_ipaddress($_[$i]));
if (&check_ip6address($_[0])) {
my $ip6 = &to_ip6address($_[$i]);
$mismatch = 1 if (!$ip6 ||
&canonicalize_ip6($ip6) ne
&canonicalize_ip6($_[0]));
}
else {
$mismatch = 1 if ($_[0] ne &to_ipaddress($_[$i]));
}
}
return 1 if (!$mismatch);
}