Skip to content

Commit fd883bd

Browse files
authored
Merge pull request #29852 from nextcloud/backport/29835/stable22
[stable22] Fix getting subnet of ipv4 mapped ipv6 addresses
2 parents f5db8a1 + 74eeca3 commit fd883bd

File tree

2 files changed

+53
-0
lines changed

2 files changed

+53
-0
lines changed

lib/private/Security/Normalizer/IpAddress.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,38 @@ private function getIPv6Subnet(string $ip, int $maskBits = 48): string {
9292
return \inet_ntop($binary).'/'.$maskBits;
9393
}
9494

95+
/**
96+
* Returns the IPv4 address embedded in an IPv6 if applicable.
97+
* The detected format is "::ffff:x.x.x.x" using the binary form.
98+
*
99+
* @return string|null embedded IPv4 string or null if none was found
100+
*/
101+
private function getEmbeddedIpv4(string $ipv6): ?string {
102+
$binary = inet_pton($ipv6);
103+
if (!$binary) {
104+
return null;
105+
}
106+
for ($i = 0; $i <= 9; $i++) {
107+
if (unpack('C', $binary[$i])[1] !== 0) {
108+
return null;
109+
}
110+
}
111+
112+
for ($i = 10; $i <= 11; $i++) {
113+
if (unpack('C', $binary[$i])[1] !== 255) {
114+
return null;
115+
}
116+
}
117+
118+
$binary4 = '';
119+
for ($i = 12; $i < 16; $i++) {
120+
$binary4 .= $binary[$i];
121+
}
122+
123+
return inet_ntop($binary4);
124+
}
125+
126+
95127
/**
96128
* Gets either the /32 (IPv4) or the /64 (IPv6) subnet of an IP address
97129
*
@@ -104,6 +136,15 @@ public function getSubnet(): string {
104136
32
105137
);
106138
}
139+
140+
$ipv4 = $this->getEmbeddedIpv4($this->ip);
141+
if ($ipv4 !== null) {
142+
return $this->getIPv4Subnet(
143+
$ipv4,
144+
32
145+
);
146+
}
147+
107148
return $this->getIPv6Subnet(
108149
$this->ip,
109150
64

tests/lib/Security/Normalizer/IpAddressTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,18 @@ public function subnetDataProvider() {
3838
'192.168.0.123',
3939
'192.168.0.123/32',
4040
],
41+
[
42+
'::ffff:192.168.0.123',
43+
'192.168.0.123/32',
44+
],
45+
[
46+
'0:0:0:0:0:ffff:192.168.0.123',
47+
'192.168.0.123/32',
48+
],
49+
[
50+
'0:0:0:0:0:ffff:c0a8:7b',
51+
'192.168.0.123/32',
52+
],
4153
[
4254
'2001:0db8:85a3:0000:0000:8a2e:0370:7334',
4355
'2001:db8:85a3::/64',

0 commit comments

Comments
 (0)