如何在PHP 5.6中通过php.ini设置'verify_peer_name = false'SSL上下文选项

dma*_*a_k 9 php ssl

案例:我想打开SSL连接,localhost而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);
Run Code Online (Sandbox Code Playgroud)

由于我有很多遗留代码,我希望通过仅对php.ini(或CLI)应用更改来获得解决方案,但遗憾的是,以下两种方法都不起作用:

php -d verify_peer_name=false test.php

php -d ssl.verify_peer_name=false test.php

想法?

参考文献:

β.ε*_*.βε 12

TL; DR

何时cafilecapath同时是运行时配置SSL上下文选项,verify_peer_name并且verify_peer只是SSL上下文选项.

因此,后来的两个不能通过运行时配置指令进行修改.


我可以理解这里复制的文档中的混淆,但这两段实际上是指PHP中的两个不同的概念.

通过设置openssl.cafile或openssl.capath配置设置,或者通过使用cafile或capath上下文选项基于每个请求,可以在全局基础上覆盖默认CA捆绑包.

虽然一般不推荐,但可以通过将verify_peer context选项设置为FALSE来禁用请求的对等证书验证,并通过将verify_peer_name context选项设置为FALSE来禁用对等名称验证.

链接到PHP手册源

首先要注意的是,文件本身就是一个明显的区别openssl.cafile,并openssl.capath成为在全球范围内在每个请求的基础上对verify_peerverify_peer_name一个要求而已.

因此,这基本上意味着,何时openssl.cafile,openssl.capath可以通过php.ini或通过适应stream_context_set_option,另一方面verify_peer,verify_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;
Run Code Online (Sandbox Code Playgroud)

链接到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)
Run Code Online (Sandbox Code Playgroud)

链接到PHP github源代码

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;
}
Run Code Online (Sandbox Code Playgroud)

链接到PHP github源代码

然后在完全相同的功能中稍低一点:

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

链接到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); }
Run Code Online (Sandbox Code Playgroud)

链接到PHP github源代码

您还可以看到的是,当这两个值openssl.capthopenssl.cafile被定义为现有的ini配置,后来verify_peerverify_peer_name是无处可寻.

令人遗憾的是,正如文档提示的那样,唯一的方法就是为请求配置它 stream_context_set_option ( $stream_or_context , 'ssl' , 'verify_peer_name' , false )



另请注意:根据文档的提示,PHP版本5.6.0中更改了这两个SSL上下文选项的默认值:

5.6.0添加了peer_fingerprint和verify_peer_name.verify_peer默认更改为TRUE.

链接到PHP文档

这意味着这样的问题可以在升级PHP之后出现PHP < 5.6.0,即使我不建议,因为PHP即将到来的是支持生命周期,这两个选项的默认值可以通过坚持到5.6.0低于的版本5.*.*.