I'm trying to auto resolve if host is supporting certificate for SSL. Here is my piece of code:
$context = stream_context_create([
'socket' => [
'tcp_nodelay' => true,
],
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
'SNI_enabled' => false,
'allow_self_signed' => true,
'capture_peer_cert' => true,
'capture_peer_cert_chain' => true
]
]);
$this->stream = @stream_socket_client('tcp://' . $this->ip . ':' . $this->port, $errno, $errstr, $this->timeout, STREAM_CLIENT_CONNECT, $context);
if ($this->stream === false) {
throw new ConnectException($errstr, $errno);
}
if (!stream_set_blocking($this->stream, true)) {
throw new ConnectException('Cannot set socket into blocking mode');
}
$enableCrypto = stream_socket_enable_crypto($this->stream, true, STREAM_CRYPTO_METHOD_ANY_CLIENT);
if ($enableCrypto === true) {
$params = stream_context_get_params($this->stream);
if (isset($params['options']['ssl']['peer_certificate']) && is_resource($params['options']['ssl']['peer_certificate'])) {
$cert = openssl_x509_parse($params['options']['ssl']['peer_certificate']);
stream_context_set_params($this->stream, [
'ssl' => [
'verify_peer' => true,
'verify_peer_name' => true,
'SNI_enabled' => true,
'peer_name' => $cert['subject']['CN'],
'allow_self_signed' => count($params['options']['ssl']['peer_certificate_chain']) == 1 && $cert['subject'] == $cert['issuer']
]
]);
}
} else {
stream_socket_enable_crypto($this->stream, false, STREAM_CRYPTO_METHOD_ANY_CLIENT);
}
As you can see the logic is about creating connection over tcp (without ssl) but with requesting certificates. Certificates are not requested until you call stream_socket_enable_crypto. Next I will update stream socket parameters by certificate. This works great with server which have SSL. But when I try to run it against host without SSL (ex. localhost instance) the stream_socket_enable_crypto triggers warning (which is not a big deal because I can suppress it with @) and $enableCrypto contains (int)0:
Warning: stream_socket_enable_crypto(): SSL: The operation completed successfully.
but the connection is aborted after I try to use it:
Notice: fwrite(): send of 16 bytes failed with errno=10053 An established connection was aborted by the software in your host machine.