systemtruststores / systemtruststores.github.io

Website
0 stars 0 forks source link

Language support: PHP #5

Open chriskilding opened 2 years ago

chriskilding commented 2 years ago

Tracking support for native TLS certificate verification in PHP.

PHP's codebase includes several common networking libraries in its ext/ folder (https://github.com/php/php-src/tree/master/ext). Some of these leverage the well-known C networking libraries:

This means that if you wanted to find out if all these libraries could be built with native TLS trust store backends, you could do this by building PHP from source (with the relevant flags).

Composer

Composer (the PHP package manager) is written in PHP, so it will do whatever PHP does for TLS on a given system.

Extra notes on HTTPS

PHP Curl

This appears to use either the curl.cainfo or openssl.cafile properties set in php.ini, like Guzzle does:

curl.cainfo ="C:\php-7.4.11\extras\ssl\cacert.pem"

Alternatively the properties can be set inline within PHP code:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_CAINFO, __DIR__ . '/cacert.pem');

PHP Streams

TODO

Guzzle

The request verify option affects TLS verification:

From the docs (https://github.com/guzzle/guzzle/blob/master/docs/request-options.rst#verify):

// Use the system's CA bundle (this is the default setting)
$client->request('GET', '/', ['verify' => true]);

// Use a custom SSL certificate on disk.
$client->request('GET', '/', ['verify' => '/path/to/cert.pem']);

// Disable validation entirely (don't do this!).
$client->request('GET', '/', ['verify' => false]);

If you do not need a specific certificate bundle, then Mozilla provides a commonly used CA bundle which can be downloaded here (provided by the maintainer of cURL). Once you have a CA bundle available on disk, you can set the openssl.cafile PHP ini setting to point to the path to the file, allowing you to omit the verify request option.

Note 1: Guzzle used to have a defaultCaCerts() method which would return the path to the OpenSSL CA cert bundle on disk, because PHP <5.6 did not set this properly. This method has since been deprecated; I assume that the 'verify' option now just follows PHP defaults (as dictated by the openssl.cafile php.ini setting).

Note 2: From https://github.com/guzzle/guzzle/issues/2134 it looks like Guzzle might use Curl underneath.

Everything else

chriskilding commented 2 years ago

It seems there are two places we could insert an alternative native TLS cert verification strategy:

The first is modifying Curl itself to build with Secure Transport (Mac) or schannel (Windows) support. If the openssl.cafile property is then not set, when PHP calls into Curl, it should just benefit from what Curl does transparently.

The second is Guzzle-specific. Under the ['verify' => true] API, we can substitute native TLS cert verification as an alternate implementation. It still technically fulfils what verify => true means - verification is indeed happening - just by a different route.

chriskilding commented 2 years ago

Windows PHP developers who use WampServer (https://www.wampserver.com/en/) have anecdotally reported that custom TLS certs from the Windows Certificate Store are picked up by WampServer's PHP without taking extra steps.

This suggests that either:

There are references to Winsocks in PHP's standard codebase, so it's possible that Winsocks + Schannel come into play when compiled for Windows.