Skip to content

[2.1] Use stream_socket_client instead of fsocketopen if possible - #9862

Open
jdarwood007 wants to merge 1 commit into
SimpleMachines:release-2.1from
jdarwood007:2.1/fixes9803
Open

jdarwood007 wants to merge 1 commit into
SimpleMachines:release-2.1from
jdarwood007:2.1/fixes9803

Conversation

@jdarwood007

Copy link
Copy Markdown
Member

Fixes #9803

@jdarwood007 jdarwood007 added this to the 2.1.9 milestone Nov 10, 2026
@jdarwood007 jdarwood007 linked an issue Nov 10, 2026 that may be closed by this pull request
@albertlast

Copy link
Copy Markdown
Collaborator

Connecting to the address from get_ips_for_url() fixes #9803 when that connection succeeds. With cURL disabled, so the socket path is the one used, fetches of https://www.google.com/robots.txt, http://www.google.com/robots.txt and a raw.githubusercontent.com file returned the same as release-2.1. The fsockopen() fallback is the concern:

$fp = @fsockopen(($match[2] ? 'ssl://' : '') . $ip[0] ?? $match[3], ...);

. binds tighter than ??, and $ip is the address as a string, so $ip[0] is its first character. For an address starting with 9 this evaluates to "ssl://9":

$match = [2 => 's', 3 => 'example.com'];
$ip = '93.184.215.14';
var_dump(($match[2] ? 'ssl://' : '') . $ip[0] ?? $match[3]);   // string(7) "ssl://9"

So the fallback never connects. Even written as intended, an ssl:// connection to a bare IP fails certificate verification, so it would need the host name. The host name, though, goes back through the system resolver, which is the mismatch #9803 is about. Trying each address from get_ips_for_url() in turn would avoid needing the fallback at all. Only $ips[0] is tried now.

The stream_context_create() line also ends in trailing tabs.

@albertlast

Copy link
Copy Markdown
Collaborator

I re-ran this against the current head (21aba83). With cURL disabled, so the socket path is the one used, normal fetches work: https://www.google.com/robots.txt, http://www.google.com/robots.txt and a raw.githubusercontent.com file all came back complete.

The fallback still can't help for HTTPS. As PHP evaluates it now:

($match[2] ? 'ssl://' : '') . $ips[0] ?? $match[3]
// 93.184.215.14  ->  "ssl://93.184.215.14"
// 2001:db8::1    ->  "ssl://2001:db8::1"
  • An SSL connection to a bare IP fails certificate verification, because there is no host name to check the certificate against. Against a real server, fsockopen('ssl://' . gethostbyname('www.google.com'), 443) failed, while fsockopen('ssl://www.google.com', 443) connected.
  • An IPv6 address is not bracketed, so it cannot be told apart from the port.
  • It retries $ips[0], the same address stream_socket_client() has just failed to reach.
  • ?? $match[3] never applies, because . binds tighter than ??.

Trying each address from get_ips_for_url() in turn with stream_socket_client(), with the same peer_name context, would cover an unreachable first address without the fallback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[2.1|3.0] url_resolves_to fails due to caching and low TTL

2 participants