Случай. Я хотел бы открыть SSL-соединение с localhost
а SSL-сертификат – это проблемы для полного доменного имени.
Проблема: без специальной обработки в строке (*)
программа ниже не работает со следующим сообщением:
PHP Warning: stream_socket_enable_crypto(): Peer certificate CN='myhost.com' did not match expected CN='localhost' in test.php
Тест-программа PHP:
$fp = stream_socket_client("tcp://localhost:993", $errno, $errstr, 30); // (*) if commented, the program fails //stream_context_set_option($fp, 'ssl', 'verify_peer_name', false); if (!$fp) { die("Unable to connect: $errstr ($errno)"); } if (!stream_socket_enable_crypto($fp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) { die("Failed to start SSL"); } fwrite($fp, "USER god\r\n"); fwrite($fp, "PASS secret\r\n"); while ($motd = fgets($fp)) { echo $motd; } fclose($fp);
Поскольку у меня много устаревшего кода, я хотел бы иметь решение, применяя только изменения в php.ini
(или CLI), но, к сожалению, ни один из ниже не работает:
php -d verify_peer_name=false test.php
php -d ssl.verify_peer_name=false test.php
Идеи?
Рекомендации:
Когда cafile
и capath
являются одновременно конфигурацией среды выполнения и параметрами контекста SSL , verify_peer_name
и verify_peer
являются только параметрами контекста SSL .
Таким образом, эти более поздние два не могут быть изменены с помощью директив конфигурации времени исполнения.
Я могу понять путаницу из документации, воспроизведенной здесь, но эти два абзаца на самом деле относятся к двум различным понятиям в PHP.
Пакет CA по умолчанию может быть переопределен на глобальной основе , установив либо параметр конфигурации openssl.cafile, либо openssl.capath, либо на основе запроса , используя параметры контекста cafile или capath.
Хотя это и не рекомендуется в целом, можно отключить проверку сертификатов одноранговой сети для запроса , установив параметр контекста verify_peer в FALSE и отключить проверку имени пэра, установив параметр контекста verify_peer_name в FALSE.
Ссылка на исходный источник PHP
Прежде всего обратите внимание, что сама документация имеет четкое различие между openssl.cafile
и openssl.capath
на глобальной основе или на основе запроса в сравнении с verify_peer
и verify_peer_name
для запроса .
Это означает, что, когда openssl.cafile
и openssl.capath
могут быть адаптированы как через php.ini
и через stream_context_set_option
, с другой стороны verify_peer
и verify_peer_name
доступны только через stream_context_set_option
.
Это также подтверждается самим исходным кодом PHP, вот некоторые строки, показывающие, что PHP
php_stream_context_get_option
основе языка C
получает значение только из php_stream_context_get_option
.
must_verify_peer_name = GET_VER_OPT("verify_peer_name") ? zend_is_true(val) : sslsock->is_client;
Ссылка на исходный код PHP github
Для ясности, вот объявление макроса GET_VER_OPT
#define GET_VER_OPT(name) (PHP_STREAM_CONTEXT(stream) && (val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "ssl", name)) != NULL)
Ссылка на исходный код PHP github
Когда cafile
и capath
на самом деле сначала сопоставляются с значением php_stream_context_get_option
, но тогда, если они имеют NULL
в контексте, они затем выбираются в конфигурации ini.
GET_VER_OPT_STRING("cafile", cafile); GET_VER_OPT_STRING("capath", capath); if (cafile == NULL) { cafile = zend_ini_string("openssl.cafile", sizeof("openssl.cafile")-1, 0); cafile = strlen(cafile) ? cafile : NULL; }
Ссылка на исходный код PHP github
Тогда немного ниже в той же самой функции:
if (capath == NULL) { capath = zend_ini_string("openssl.capath", sizeof("openssl.capath")-1, 0); capath = strlen(capath) ? capath : NULL; }
Ссылка на исходный код PHP github
Для ясности, вот объявление макроса GET_VER_OPT_STRING
#define GET_VER_OPT_STRING(name, str) if (GET_VER_OPT(name)) { convert_to_string_ex(val); str = Z_STRVAL_P(val); }
Ссылка на исходный код PHP github
Вы также можете видеть, что, когда эти два значения openssl.capth
и openssl.cafile
определяются как существующая ini
конфигурация, более поздние verify_peer
и verify_peer_name
нигде не найдены.
К сожалению, единственный способ пойти, как подсказывает его документация, – настроить его для запроса через stream_context_set_option ( $stream_or_context , 'ssl' , 'verify_peer_name' , false )
Также обратите внимание : значение по умолчанию для этих двух параметров контекста SSL изменилось в PHP версии 5.6.0, как это было предложено в документации:
5.6.0 Добавлено peer_fingerprint и verify_peer_name. Значение параметра verify_peer по умолчанию изменено на TRUE.
Ссылка на документацию PHP
Это означает, что такая проблема может возникнуть после обновления PHP с PHP < 5.6.0
поэтому, даже если я этого не рекомендую, поскольку PHP 5.5
подходит к концу, это жизненный цикл поддержки , значение по умолчанию этих двух параметров может сохраняться в false, придерживаясь версии PHP
ниже 5.6.0
.