Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Fix DnsPinMiddleware resolve pinning bug
Libcurl expects the value of the CURLOPT_RESOLVE configurations to be an
array of strings, those strings containing a comma delimited list of
resolved IPs for each host:port combination.

The original code here does create that array with the host:port:ip
combination, but multiple ips for a single host:port result in
additional array entries, rather than adding them to the end of the
string with a comma. Per the libcurl docs, the `CURLOPT_RESOLVE` array
entries should match the syntax `host:port:address[,address]`.

This creates a function-scoped associative array which uses `host:port`
as the key (which are supposed to be unique and this ensures that), and
the value is an array containing IP strings (ipv4 or ipv6). Once the
associative array is populated, it is then set to the CURLOPT_RESOLVE
array, imploding the ip arrays using a comma delimiter so the array
syntax matches the expected by libcurl.

Note that this reorders the "foreach ip" and "foreach port" loops.
Rather than looping over ips then ports, we now loop over ports then
ips, since ports are part of the unique host:port map, and multiple ips
can exist therein.

Signed-off-by: Aaron Ball <[email protected]>
  • Loading branch information
nullspoon authored and backportbot[bot] committed Jul 5, 2021
commit f8db7ce8f5d3255bc6f04617164de1351b8010ab
17 changes: 12 additions & 5 deletions lib/private/Http/Client/DnsPinMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,15 +112,22 @@ public function addDnsPinning() {

$targetIps = $this->dnsResolve($hostName, 0);

foreach ($targetIps as $ip) {
$this->localAddressChecker->ThrowIfLocalIp($ip);
$curlResolves = [];

foreach ($ports as $port) {
$curlEntry = $hostName . ':' . $port . ':' . $ip;
$options['curl'][CURLOPT_RESOLVE][] = $curlEntry;
foreach ($ports as $port) {
$curlResolves["$hostName:$port"] = [];

foreach ($targetIps as $ip) {
$this->localAddressChecker->ThrowIfLocalIp($ip);
$curlResolves["$hostName:$port"][] = $ip;
}
}

// Coalesce the per-host:port ips back into a comma separated list
foreach ($curlResolves as $hostport => $ips) {
$options['curl'][CURLOPT_RESOLVE][] = "$hostport:" . implode(',', $ips);
}

return $handler($request, $options);
};
};
Expand Down