diff --git a/api.php b/api.php index f5b861c..c1a8f49 100644 --- a/api.php +++ b/api.php @@ -140,29 +140,36 @@ function getClientIp(): string { /** * Tarkista onko IP sallittujen listalla. * Tyhjä lista = ei rajoitusta (kaikki sallittu). - * Tukee yksittäisiä IP-osoitteita ja CIDR-alueita (esim. 192.168.1.0/24). + * Tukee IPv4 ja IPv6, yksittäisiä osoitteita ja CIDR-alueita. */ function isIpAllowed(string $ip, string $allowedIps): bool { $allowedIps = trim($allowedIps); - if ($allowedIps === '' || strtolower($allowedIps) === 'kaikki') return true; // ei rajoitusta + if ($allowedIps === '' || strtolower($allowedIps) === 'kaikki') return true; $entries = preg_split('/[\s,]+/', $allowedIps, -1, PREG_SPLIT_NO_EMPTY); - $ipLong = ip2long($ip); - if ($ipLong === false) return false; + $ipBin = @inet_pton($ip); + if ($ipBin === false) return false; foreach ($entries as $entry) { $entry = trim($entry); if ($entry === '') continue; if (strpos($entry, '/') !== false) { - // CIDR-alue (esim. 192.168.1.0/24) + // CIDR-alue (IPv4 tai IPv6) [$subnet, $bits] = explode('/', $entry, 2); $bits = (int)$bits; - if ($bits < 0 || $bits > 32) continue; - $subnetLong = ip2long($subnet); - if ($subnetLong === false) continue; - $mask = $bits === 0 ? 0 : (~0 << (32 - $bits)); - if (($ipLong & $mask) === ($subnetLong & $mask)) return true; + $subnetBin = @inet_pton($subnet); + if ($subnetBin === false) continue; + // IPv4 = 4 tavua, IPv6 = 16 tavua — pitää olla sama perhe + if (strlen($ipBin) !== strlen($subnetBin)) continue; + $maxBits = strlen($ipBin) * 8; + if ($bits < 0 || $bits > $maxBits) continue; + // Rakenna bittimask + $mask = str_repeat("\xff", intdiv($bits, 8)); + if ($bits % 8) $mask .= chr(0xff << (8 - ($bits % 8))); + $mask = str_pad($mask, strlen($ipBin), "\x00"); + if (($ipBin & $mask) === ($subnetBin & $mask)) return true; } else { - // Yksittäinen IP - if (ip2long($entry) === $ipLong) return true; + // Yksittäinen IP (IPv4 tai IPv6) + $entryBin = @inet_pton($entry); + if ($entryBin !== false && $ipBin === $entryBin) return true; } } return false;