Edit report at https://bugs.php.net/bug.php?id=68344&edit=1
ID: 68344
Comment by: arekm at maven dot pl
Reported by: james at jamesreno dot com
Summary: MySQLi does not provide way to disable peer
certificate validation
Status: No Feedback
Type: Bug
Package: MySQLi related
Operating System: NA
PHP Version: 5.6.2
Assigned To: mysql
Block user comment: N
Private report: N
New Comment:
More, mysqli internally uses mysqlnd, which creates new context in mysqlnd_net::enable_ssl thus
ignoring default context.
Whit patch below I'm getting default context being used.
diff --git a/ext/mysqlnd/mysqlnd_net.c b/ext/mysqlnd/mysqlnd_net.c
index 8683248..2f63961 100644
--- a/ext/mysqlnd/mysqlnd_net.c
+++ b/ext/mysqlnd/mysqlnd_net.c
@@ -29,6 +29,7 @@
#include "mysqlnd_ext_plugin.h"
#include "php_network.h"
#include "zend_ini.h"
+#include "ext/standard/file.h"
#ifdef MYSQLND_COMPRESSION_ENABLED
#include <zlib.h>
#endif
@@ -859,7 +860,7 @@ static enum_func_status
MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET * const net TSRMLS_DC)
{
#ifdef MYSQLND_SSL_SUPPORTED
- php_stream_context * context = php_stream_context_alloc(TSRMLS_C);
+ php_stream_context * context = FG(default_context) ? FG(default_context) :
php_stream_context_alloc(TSRMLS_C);
php_stream * net_stream = net->data->m.get_stream(net TSRMLS_CC);
DBG_ENTER("mysqlnd_net::enable_ssl");
Unfortunately above method means that mysqlnd will change some settings
in default context. What we need to do is to leave creation of new context
but then copy all options from default context to our new context, pseudocode:
php_stream_context * context = php_stream_context_alloc(TSRMLS_C);
copy_all_options_from_default_context_to_new_context(context, default_context)
Don't see any internal function that could do that, so someone with code knowledge would have
to write it.
Previous Comments:
------------------------------------------------------------------------
[2015-08-10 09:12:48] arekm at maven dot pl
"nicely sets GET_VER_OPT("verify_peer") and
GET_VER_OPT("verify_peer_name")) to 0, which is fine."
or rather these are 0 by default.... so default context options are actually not being passed here
:-/
------------------------------------------------------------------------
[2015-08-10 07:51:01] arekm at maven dot pl
Ok, the problem comes from generic openssl code:
ext/openssl/xp_ssl.c, apply_peer_verification_policy() function
must_verify_peer = GET_VER_OPT("verify_peer")
? zend_is_true(*val)
: sslsock->is_client;
has_cnmatch_ctx_opt = GET_VER_OPT("CN_match");
must_verify_peer_name = (has_cnmatch_ctx_opt || GET_VER_OPT("verify_peer_name"))
? zend_is_true(*val)
: sslsock->is_client;
Now code:
$opts = array('ssl'=>array('verify_peer'=> false,
'verify_peer_name' => false));
stream_context_set_default($opts);
nicely sets GET_VER_OPT("verify_peer") and GET_VER_OPT("verify_peer_name")) to
0, which is fine.
Unfortunately above code fallback to sslsock->is_client which is 1. That means that if we are
client (is_client==1) then openssl extension ignores our verify_peer and verify_peer_name settings.
Why is that? No idea.
If I'm looking correctly then this commit changed behaviour:
commit ce8dc0ede2e8084beef1e7b03c8960e938c8399f
Author: Daniel Lowrey <rdlowrey@php.net>
Date: Fri Feb 14 15:17:30 2014 -0700
Bug #47030 (separate host and peer verification)
Previously it behaved differently for is_client == 1.
------------------------------------------------------------------------
[2015-08-09 20:03:26] arekm at maven dot pl
"Warning: mysqli_real_connect(): Peer certificate CN=.... did not match expected CN" comes
from openssl/xp_ssl.c
That code uses php stream functions like:
stream = php_stream_alloc_rel(&php_openssl_socket_ops, sslsock, persistent_id, "r+");
...
then php_openssl_socket_ops structure has php_openssl_sockop_set_option function which then call few
functions and is some cases raises above error.
apply_peer_verification_policy actually checks verify_peer:
must_verify_peer = GET_VER_OPT("verify_peer")
? zend_is_true(*val)
: sslsock->is_client;
so it should be possible to switch this check off. Unfortunately for me php 5.6.12 is ignoring
setting for this:
$opts = array('ssl'=>array('verify_peer'=> false,
'verify_peer_name' => false));
stream_context_set_default($opts);
$cb = mysqli_init();
mysqli_ssl_set($cb, null, null, null, null, null);
mysqli_real_connect($cb,$db_host, $db_user, $db_pass, $db_name, false, false, MYSQLI_CLIENT_SSL)
and yet I'm getting
"Warning: mysqli_real_connect(): Peer certificate CN=.... did not match expected CN"
So the question is - why openssl code ignores verify_peer setting from default context?
------------------------------------------------------------------------
[2015-08-07 12:08:28] t dot launer at intershop dot de
I've been watching this bug entry for some time now and actually thought this issue was too
important not to be fixed fast. A number of our systems are affected by this bug, seeing that we
maintain a set of distributed applications and a central MySQL server that hosts all the
company's MySQL database instances with which every application server (OTRS, Wikis, ...) must
communicate via X509. I simply cannot upgrade their PHP to 5.6 because that required abandoning our
security policy.
I agree with "spam2 at rhsoft dot net" in that it is a security measure to create server
and client certificates from a CA that is hidden to everyone.
Please consider fixing this bug in 5.6 soon - or at least make the 5.5 functionality available as
option again in version 7.
------------------------------------------------------------------------
[2015-08-07 07:31:24] spam2 at rhsoft dot net
and another month is gone where peole which using encryption for anything which make sit to a
ethernet cable the last years CAN NOT UPGRADE TO PHP 5.6 - holy crap mysql encryption in general
broke repeatly without even push a fixing update in a tiemly manner, now it's broken again -
that's all a joke
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
https://bugs.php.net/bug.php?id=68344
--
Edit this bug report at https://bugs.php.net/bug.php?id=68344&edit=1