【问题标题】:How to set 'verify_peer_name=false' SSL context option via php.ini in PHP 5.6如何在 PHP 5.6 中通过 php.ini 设置“verify_peer_name=false”SSL 上下文选项
【发布时间】:2014-11-07 21:15:22
【问题描述】:

案例:我想打开到localhost 的 SSL 连接,而 SSL 证书是 FQDN 的问题。

问题:如果没有在(*) 行中进行特殊处理,下面的程序将失败并显示以下消息:

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

想法?

参考资料:

【问题讨论】:

  • 这只是一个警告,它不应该失败
  • 它向控制台打印警告,但实际上 stream_socket_enable_crypto() 返回 0(失败)。
  • 您找到解决方案了吗?
  • 哪个 PHP 版本?
  • @Thibaut:如果你问我,那么我实际上已经按照以下答案得出了解决方案,即我必须编写一些 PHP 代码(看this post,搜索function sqenable_ssl($stream) )。

标签: php ssl


【解决方案1】:

TL;博士

cafilecapath同时是runtime configurationSSL context options时,verify_peer_nameverify_peer只有SSL context options

所以后面的两个不能通过运行时配置指令进行修改。


我可以从下面复制的文档中理解混乱,但这两段实际上是指 PHP 中的两个不同概念。

默认的 CA 包可以通过设置在全球范围内被覆盖 openssl.cafile 或 openssl.capath 配置设置,或 使用 cafile 或 capath 上下文选项基于每个请求

虽然一般不推荐,但可以禁用对等点 证书验证请求通过设置 verify_peer 上下文选项为 FALSE,并通过以下方式禁用对等名称验证 将 verify_peer_name 上下文选项设置为 FALSE。

Link to PHP manual source

首先请注意,文档本身明确区分了openssl.cafileopenssl.capath在全球范围内在每个请求基础上与verify_peer verify_peer_name 仅用于请求

所以这基本上意味着,当openssl.cafileopenssl.capath 可以通过php.inistream_context_set_option 进行调整时,另一方面verify_peerverify_peer_name 只能通过stream_context_set_option 访问。

PHP 源代码本身也证实了这一点,这里有几行表明 PHP 底层 C 语言仅从 php_stream_context_get_option 获取值。

must_verify_peer_name = GET_VER_OPT("verify_peer_name")
        ? zend_is_true(val)
        : sslsock->is_client;

Link to PHP github source code

为了清楚起见,这里是宏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)

Link to PHP github source code

cafilecapath 实际上首先与 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;
}

Link to PHP github source code

然后在完全相同的函数中稍微低一点:

if (capath == NULL) {
    capath = zend_ini_string("openssl.capath", sizeof("openssl.capath")-1, 0);
    capath = strlen(capath) ? capath : NULL;
}

Link to PHP github source code

为清楚起见,这里是宏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); }

Link to PHP github source code

你还可以看到,当openssl.capthopenssl.cafile这两个值被定义为现有的ini配置时,后面的verify_peerverify_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。

Link to PHP documentation

这意味着从PHP < 5.6.0 升级PHP 后可能会出现这种问题,因此,这两个选项的默认值可以通过坚持低于5.6.0PHP 版本保持为false;但由于 PHP 的分支 5.*.* 现在是 totally out of support,这不再是一个可行的选择。

【讨论】:

  • 顺便说一句很好的答案;颁奖前我是waiting for the bounty period to end,但我想没有人会想出比这更好的答案。
  • 在您的评论中乍一看没有看到元帖子的链接。我认为开放赏金是完全公平的,真的,不用担心。
猜你喜欢
  • 2014-04-28
  • 2014-11-01
  • 2014-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多