xp-framework/http

SNI with PHP 5.4

thekid opened this issue · 2 comments

Scenario: HTTP proxy which talks to a HTTPS site.

When connecting to an HTTPS server through HTTP proxy, the first request to the proxy will use plain HTTP, then issuing a CONNECT call which subsequently enables cryptography.

In PHP 5.4, the (now deprecated) SNI_server_name and SNI_enabled values are read from the stream context prior to the creation of the socket; setting these values afterwards has no effect. The server then will respond with this message: [error] Hostname A provided via SNI and hostname B provided via HTTP are different.

A fix is to settle these values early in time:

  protected function connect($s, $read, $connect) {
    $s->isConnected() && $s->close();
    $s->setTimeout($read);

    $ctx= $s->getClass()->getField('context')->setAccessible(true)->get($s);
    stream_context_set_option($ctx, 'ssl', 'SNI_enabled', true);
    stream_context_set_option($ctx, 'ssl', 'SNI_server_name', 'example.com');

    $s->connect($connect);
    return $s;
  } 

Maybe enclosed inside a if (PHP_VERSION <= '5.6') { ... } block? The relevant PHP manual page states:

SNI_server_name string

If set, then this value will be used as server name for server name indication. If this value is not set, then the server name is guessed based on the hostname used when opening the stream.
Note: This option is deprecated, in favour of peer_name, as of PHP 5.6.0.

Not an issue anymore, we require PHP 5.6 now.