diff options
-rw-r--r-- | ext/mysqli/mysqli.c | 3 | ||||
-rw-r--r-- | ext/mysqli/tests/bug51647.phpt | 11 | ||||
-rw-r--r-- | ext/mysqli/tests/bug55283.phpt | 2 | ||||
-rw-r--r-- | ext/mysqli/tests/connect.inc | 9 | ||||
-rw-r--r-- | ext/mysqli/tests/mysqli_constants.phpt | 3 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd.c | 7 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_enum_n_def.h | 4 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_net.c | 49 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_structs.h | 9 |
9 files changed, 74 insertions, 23 deletions
diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c index 0ba65696f4..7e856a15b4 100644 --- a/ext/mysqli/mysqli.c +++ b/ext/mysqli/mysqli.c @@ -720,6 +720,9 @@ PHP_MINIT_FUNCTION(mysqli) REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_FOUND_ROWS", CLIENT_FOUND_ROWS, CONST_CS | CONST_PERSISTENT); #ifdef CLIENT_SSL_VERIFY_SERVER_CERT REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_SSL_VERIFY_SERVER_CERT", CLIENT_SSL_VERIFY_SERVER_CERT, CONST_CS | CONST_PERSISTENT); +#if defined(MYSQLI_USE_MYSQLND) + REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT", CLIENT_SSL_DONT_VERIFY_SERVER_CERT, CONST_CS | CONST_PERSISTENT); +#endif #endif #if (MYSQL_VERSION_ID >= 50611 && defined(CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS)) || defined(MYSQLI_USE_MYSQLND) REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS", CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS, CONST_CS | CONST_PERSISTENT); diff --git a/ext/mysqli/tests/bug51647.phpt b/ext/mysqli/tests/bug51647.phpt index 349d6dbbb0..7385538fbb 100644 --- a/ext/mysqli/tests/bug51647.phpt +++ b/ext/mysqli/tests/bug51647.phpt @@ -41,11 +41,7 @@ $link->close(); if (!is_object($link = mysqli_init())) printf("[001] Cannot create link\n"); - $path_to_pems = !$IS_MYSQLND? "ext/mysqli/tests/" : ""; - if (!$link->ssl_set("{$path_to_pems}client-key.pem", "{$path_to_pems}client-cert.pem", "{$path_to_pems}cacert.pem","","")) - printf("[002] [%d] %s\n", $link->errno, $link->error); - - if (!my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket)) { + if (!my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket, MYSQLI_CLIENT_SSL | MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT)) { printf("[003] Connect failed, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); } @@ -67,9 +63,9 @@ $link->close(); printf("[006] [%d] %s\n", $link->errno, $link->error); if (!strlen($row["Value"])) printf("[007] Empty cipher. No encrytion!"); + var_dump($row); } - var_dump($row); $link->close(); if (!is_object($link = mysqli_init())) @@ -97,10 +93,9 @@ $link->close(); printf("[012] [%d] %s\n", $link->errno, $link->error); if (!strlen($row["Value"])) printf("[013] Empty cipher. No encrytion!"); + var_dump($row); } - var_dump($row); - $link->close(); print "done!"; diff --git a/ext/mysqli/tests/bug55283.phpt b/ext/mysqli/tests/bug55283.phpt index d03daaee88..a10c604fdd 100644 --- a/ext/mysqli/tests/bug55283.phpt +++ b/ext/mysqli/tests/bug55283.phpt @@ -40,7 +40,7 @@ $link->close(); $db1 = new mysqli(); - $flags = MYSQLI_CLIENT_SSL; + $flags = MYSQLI_CLIENT_SSL | MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT; $link = mysqli_init(); mysqli_ssl_set($link, null, null, null, null, "RC4-MD5"); diff --git a/ext/mysqli/tests/connect.inc b/ext/mysqli/tests/connect.inc index 4acc20cb91..aa33f17f85 100644 --- a/ext/mysqli/tests/connect.inc +++ b/ext/mysqli/tests/connect.inc @@ -87,9 +87,8 @@ function my_mysqli_connect($host, $user, $passwd, $db, $port, $socket, $enable_env_flags = true) { global $connect_flags; - $flags = ($enable_env_flags) ? $connect_flags : false; - - if ($flags !== false) { + $flags = $enable_env_flags? $connect_flags:0; + if ($flags !== 0) { $link = mysqli_init(); if (!mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket, $flags)) $link = false; @@ -109,7 +108,7 @@ global $connect_flags; if ($enable_env_flags) - $flags & $connect_flags; + $flags = $flags | $connect_flags; return mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket, $flags); } @@ -118,7 +117,7 @@ public function __construct($host, $user, $passwd, $db, $port, $socket, $enable_env_flags = true) { global $connect_flags; - $flags = ($enable_env_flags) ? $connect_flags : false; + $flags = ($enable_env_flags) ? $connect_flags : 0; if ($flags !== false) { parent::init(); diff --git a/ext/mysqli/tests/mysqli_constants.phpt b/ext/mysqli/tests/mysqli_constants.phpt index 1cb31cc2a7..cc5fa9f1c4 100644 --- a/ext/mysqli/tests/mysqli_constants.phpt +++ b/ext/mysqli/tests/mysqli_constants.phpt @@ -139,6 +139,9 @@ require_once('skipifconnectfailure.inc'); if ($version >= 50033 || $IS_MYSQLND) { $expected_constants['MYSQLI_CLIENT_SSL_VERIFY_SERVER_CERT'] = true; } + if ($IS_MYSQLND) { + $expected_constants['MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT'] = true; + } /* First introduced in MySQL 6.0, backported to MySQL 5.5 */ if ($version >= 50606 || $IS_MYSQLND) { diff --git a/ext/mysqlnd/mysqlnd.c b/ext/mysqlnd/mysqlnd.c index ad57c6c350..6d4232dbd5 100644 --- a/ext/mysqlnd/mysqlnd.c +++ b/ext/mysqlnd/mysqlnd.c @@ -469,6 +469,7 @@ mysqlnd_switch_to_ssl_if_needed( DBG_INF_FMT("CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA= %d", mysql_flags & CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA? 1:0); DBG_INF_FMT("CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS= %d", mysql_flags & CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS? 1:0); DBG_INF_FMT("CLIENT_SESSION_TRACK= %d", mysql_flags & CLIENT_SESSION_TRACK? 1:0); + DBG_INF_FMT("CLIENT_SSL_DONT_VERIFY_SERVER_CERT= %d", mysql_flags & CLIENT_SSL_DONT_VERIFY_SERVER_CERT? 1:0); DBG_INF_FMT("CLIENT_SSL_VERIFY_SERVER_CERT= %d", mysql_flags & CLIENT_SSL_VERIFY_SERVER_CERT? 1:0); DBG_INF_FMT("CLIENT_REMEMBER_OPTIONS= %d", mysql_flags & CLIENT_REMEMBER_OPTIONS? 1:0); @@ -492,7 +493,11 @@ mysqlnd_switch_to_ssl_if_needed( if (server_has_ssl == FALSE) { goto close_conn; } else { - zend_bool verify = mysql_flags & CLIENT_SSL_VERIFY_SERVER_CERT? TRUE:FALSE; + enum mysqlnd_ssl_peer verify = mysql_flags & CLIENT_SSL_VERIFY_SERVER_CERT? + MYSQLND_SSL_PEER_VERIFY: + (mysql_flags & CLIENT_SSL_DONT_VERIFY_SERVER_CERT? + MYSQLND_SSL_PEER_DONT_VERIFY: + MYSQLND_SSL_PEER_DEFAULT); DBG_INF("Switching to SSL"); if (!PACKET_WRITE(auth_packet, conn)) { goto close_conn; diff --git a/ext/mysqlnd/mysqlnd_enum_n_def.h b/ext/mysqlnd/mysqlnd_enum_n_def.h index 1aa9c39dc9..dd80311390 100644 --- a/ext/mysqlnd/mysqlnd_enum_n_def.h +++ b/ext/mysqlnd/mysqlnd_enum_n_def.h @@ -101,6 +101,10 @@ #define CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA (1UL << 21) /* Enable authentication response packet to be larger than 255 bytes. */ #define CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS (1UL << 22) /* Don't close the connection for a connection with expired password. */ #define CLIENT_SESSION_TRACK (1UL << 23) /* Extended OK */ +/* + This is a mysqlnd extension. CLIENT_ODBC is not used anyway. We will reuse it for our case and translate it to not using SSL peer verification +*/ +#define CLIENT_SSL_DONT_VERIFY_SERVER_CERT CLIENT_ODBC #define CLIENT_SSL_VERIFY_SERVER_CERT (1UL << 30) #define CLIENT_REMEMBER_OPTIONS (1UL << 31) diff --git a/ext/mysqlnd/mysqlnd_net.c b/ext/mysqlnd/mysqlnd_net.c index 710d6fa62c..c0a913bab6 100644 --- a/ext/mysqlnd/mysqlnd_net.c +++ b/ext/mysqlnd/mysqlnd_net.c @@ -806,8 +806,27 @@ MYSQLND_METHOD(mysqlnd_net, set_client_option)(MYSQLND_NET * const net, enum mys break; } case MYSQL_OPT_SSL_VERIFY_SERVER_CERT: - net->data->options.ssl_verify_peer = value? ((*(zend_bool *)value)? TRUE:FALSE): FALSE; + { + enum mysqlnd_ssl_peer val = *((enum mysqlnd_ssl_peer *)value); + switch (val) { + case MYSQLND_SSL_PEER_VERIFY: + DBG_INF("MYSQLND_SSL_PEER_VERIFY"); + break; + case MYSQLND_SSL_PEER_DONT_VERIFY: + DBG_INF("MYSQLND_SSL_PEER_DONT_VERIFY"); + break; + case MYSQLND_SSL_PEER_DEFAULT: + DBG_INF("MYSQLND_SSL_PEER_DEFAULT"); + val = MYSQLND_SSL_PEER_DEFAULT; + break; + default: + DBG_INF("default = MYSQLND_SSL_PEER_DEFAULT_ACTION"); + val = MYSQLND_SSL_PEER_DEFAULT; + break; + } + net->data->options.ssl_verify_peer = val; break; + } case MYSQL_OPT_READ_TIMEOUT: net->data->options.timeout_read = *(unsigned int*) value; break; @@ -894,6 +913,7 @@ MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET * const net) #ifdef MYSQLND_SSL_SUPPORTED php_stream_context * context = php_stream_context_alloc(); php_stream * net_stream = net->data->m.get_stream(net); + zend_bool any_flag = FALSE; DBG_ENTER("mysqlnd_net::enable_ssl"); if (!context) { @@ -904,12 +924,7 @@ MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET * const net) zval key_zval; ZVAL_STRING(&key_zval, net->data->options.ssl_key); php_stream_context_set_option(context, "ssl", "local_pk", &key_zval); - } - { - zval verify_peer_zval; - ZVAL_BOOL(&verify_peer_zval, net->data->options.ssl_verify_peer); - php_stream_context_set_option(context, "ssl", "verify_peer", &verify_peer_zval); - php_stream_context_set_option(context, "ssl", "verify_peer_name", &verify_peer_zval); + any_flag = TRUE; } if (net->data->options.ssl_cert) { zval cert_zval; @@ -918,26 +933,46 @@ MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET * const net) if (!net->data->options.ssl_key) { php_stream_context_set_option(context, "ssl", "local_pk", &cert_zval); } + any_flag = TRUE; } if (net->data->options.ssl_ca) { zval cafile_zval; ZVAL_STRING(&cafile_zval, net->data->options.ssl_ca); php_stream_context_set_option(context, "ssl", "cafile", &cafile_zval); + any_flag = TRUE; } if (net->data->options.ssl_capath) { zval capath_zval; ZVAL_STRING(&capath_zval, net->data->options.ssl_capath); php_stream_context_set_option(context, "ssl", "capath", &capath_zval); + any_flag = TRUE; } if (net->data->options.ssl_passphrase) { zval passphrase_zval; ZVAL_STRING(&passphrase_zval, net->data->options.ssl_passphrase); php_stream_context_set_option(context, "ssl", "passphrase", &passphrase_zval); + any_flag = TRUE; } if (net->data->options.ssl_cipher) { zval cipher_zval; ZVAL_STRING(&cipher_zval, net->data->options.ssl_cipher); php_stream_context_set_option(context, "ssl", "ciphers", &cipher_zval); + any_flag = TRUE; + } + { + zval verify_peer_zval; + zend_bool verify; + + if (net->data->options.ssl_verify_peer == MYSQLND_SSL_PEER_DEFAULT) { + net->data->options.ssl_verify_peer = any_flag? MYSQLND_SSL_PEER_DEFAULT_ACTION:MYSQLND_SSL_PEER_DONT_VERIFY; + } + + verify = net->data->options.ssl_verify_peer == MYSQLND_SSL_PEER_VERIFY? TRUE:FALSE; + + DBG_INF_FMT("VERIFY=%d", verify); + ZVAL_BOOL(&verify_peer_zval, verify); + php_stream_context_set_option(context, "ssl", "verify_peer", &verify_peer_zval); + php_stream_context_set_option(context, "ssl", "verify_peer_name", &verify_peer_zval); } #if PHP_API_VERSION >= 20131106 php_stream_context_set(net_stream, context); diff --git a/ext/mysqlnd/mysqlnd_structs.h b/ext/mysqlnd/mysqlnd_structs.h index 84c78e2c85..c01f5f9034 100644 --- a/ext/mysqlnd/mysqlnd_structs.h +++ b/ext/mysqlnd/mysqlnd_structs.h @@ -206,7 +206,13 @@ typedef struct st_mysqlnd_net_options char *ssl_capath; char *ssl_cipher; char *ssl_passphrase; - zend_bool ssl_verify_peer; + enum mysqlnd_ssl_peer { + MYSQLND_SSL_PEER_DEFAULT = 0, + MYSQLND_SSL_PEER_VERIFY = 1, + MYSQLND_SSL_PEER_DONT_VERIFY = 2, + +#define MYSQLND_SSL_PEER_DEFAULT_ACTION MYSQLND_SSL_PEER_VERIFY + } ssl_verify_peer; uint64_t flags; char * sha256_server_public_key; @@ -218,6 +224,7 @@ typedef struct st_mysqlnd_net_options } MYSQLND_NET_OPTIONS; + typedef struct st_mysqlnd_connection MYSQLND; typedef struct st_mysqlnd_connection_data MYSQLND_CONN_DATA; typedef struct st_mysqlnd_net MYSQLND_NET; |