summaryrefslogtreecommitdiff
path: root/ext/mysqlnd/mysqlnd_net.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/mysqlnd/mysqlnd_net.c')
-rw-r--r--ext/mysqlnd/mysqlnd_net.c185
1 files changed, 183 insertions, 2 deletions
diff --git a/ext/mysqlnd/mysqlnd_net.c b/ext/mysqlnd/mysqlnd_net.c
index d88e20418c..4705c8b4ef 100644
--- a/ext/mysqlnd/mysqlnd_net.c
+++ b/ext/mysqlnd/mysqlnd_net.c
@@ -172,8 +172,8 @@ MYSQLND_METHOD(mysqlnd_net, connect)(MYSQLND_NET * net, const char * const schem
/* should always happen because read_timeout cannot be set via API */
net->options.timeout_read = (unsigned int) MYSQLND_G(net_read_timeout);
}
- if (net->options.timeout_read)
- {
+ if (net->options.timeout_read) {
+ DBG_INF_FMT("setting %u as PHP_STREAM_OPTION_READ_TIMEOUT", net->options.timeout_read);
tv.tv_sec = net->options.timeout_read;
tv.tv_usec = 0;
php_stream_set_option(net->stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &tv);
@@ -587,6 +587,63 @@ MYSQLND_METHOD(mysqlnd_net, set_client_option)(MYSQLND_NET * const net, enum mys
DBG_INF("MYSQL_OPT_CONNECT_TIMEOUT");
net->options.timeout_connect = *(unsigned int*) value;
break;
+ case MYSQLND_OPT_SSL_KEY:
+ {
+ zend_bool pers = net->persistent;
+ if (net->options.ssl_key) {
+ mnd_pefree(net->options.ssl_key, pers);
+ }
+ net->options.ssl_key = value? mnd_pestrdup(value, pers) : NULL;
+ break;
+ }
+ case MYSQLND_OPT_SSL_CERT:
+ {
+ zend_bool pers = net->persistent;
+ if (net->options.ssl_cert) {
+ mnd_pefree(net->options.ssl_cert, pers);
+ }
+ net->options.ssl_cert = value? mnd_pestrdup(value, pers) : NULL;
+ break;
+ }
+ case MYSQLND_OPT_SSL_CA:
+ {
+ zend_bool pers = net->persistent;
+ if (net->options.ssl_ca) {
+ mnd_pefree(net->options.ssl_ca, pers);
+ }
+ net->options.ssl_ca = value? mnd_pestrdup(value, pers) : NULL;
+ break;
+ }
+ case MYSQLND_OPT_SSL_CAPATH:
+ {
+ zend_bool pers = net->persistent;
+ if (net->options.ssl_capath) {
+ mnd_pefree(net->options.ssl_capath, pers);
+ }
+ net->options.ssl_capath = value? mnd_pestrdup(value, pers) : NULL;
+ break;
+ }
+ case MYSQLND_OPT_SSL_CIPHER:
+ {
+ zend_bool pers = net->persistent;
+ if (net->options.ssl_cipher) {
+ mnd_pefree(net->options.ssl_cipher, pers);
+ }
+ net->options.ssl_cipher = value? mnd_pestrdup(value, pers) : NULL;
+ break;
+ }
+ case MYSQLND_OPT_SSL_PASSPHRASE:
+ {
+ zend_bool pers = net->persistent;
+ if (net->options.ssl_passphrase) {
+ mnd_pefree(net->options.ssl_passphrase, pers);
+ }
+ net->options.ssl_passphrase = value? mnd_pestrdup(value, pers) : NULL;
+ break;
+ }
+ case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
+ net->options.ssl_verify_peer = value? ((*(zend_bool *)value)? TRUE:FALSE): FALSE;
+ break;
#ifdef WHEN_SUPPORTED_BY_MYSQLI
case MYSQL_OPT_READ_TIMEOUT:
DBG_INF("MYSQL_OPT_READ_TIMEOUT");
@@ -657,12 +714,113 @@ MYSQLND_METHOD(mysqlnd_net, consume_uneaten_data)(MYSQLND_NET * const net, enum
}
/* }}} */
+/*
+ in libmyusql, if cert and !key then key=cert
+*/
+/* {{{ mysqlnd_net::enable_ssl */
+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();
+ DBG_ENTER("mysqlnd_net::enable_ssl");
+ if (!context) {
+ DBG_RETURN(FAIL);
+ }
+
+ if (net->options.ssl_key) {
+ zval key_zval;
+ ZVAL_STRING(&key_zval, net->options.ssl_key, 0);
+ DBG_INF("key");
+ php_stream_context_set_option(context, "ssl", "local_pk", &key_zval);
+ }
+ if (net->options.ssl_verify_peer) {
+ zval verify_peer_zval;
+ ZVAL_TRUE(&verify_peer_zval);
+ DBG_INF("verify peer");
+ php_stream_context_set_option(context, "ssl", "verify_peer", &verify_peer_zval);
+ }
+ if (net->options.ssl_cert) {
+ zval cert_zval;
+ ZVAL_STRING(&cert_zval, net->options.ssl_cert, 0);
+ DBG_INF_FMT("local_cert=%s", net->options.ssl_cert);
+ php_stream_context_set_option(context, "ssl", "local_cert", &cert_zval);
+ if (!net->options.ssl_key) {
+ php_stream_context_set_option(context, "ssl", "local_pk", &cert_zval);
+ }
+ }
+ if (net->options.ssl_ca) {
+ zval cafile_zval;
+ ZVAL_STRING(&cafile_zval, net->options.ssl_ca, 0);
+ DBG_INF_FMT("cafile=%s", net->options.ssl_ca);
+ php_stream_context_set_option(context, "ssl", "cafile", &cafile_zval);
+ }
+ if (net->options.ssl_capath) {
+ zval capath_zval;
+ ZVAL_STRING(&capath_zval, net->options.ssl_capath, 0);
+ DBG_INF_FMT("capath=%s", net->options.ssl_capath);
+ php_stream_context_set_option(context, "ssl", "cafile", &capath_zval);
+ }
+ if (net->options.ssl_passphrase) {
+ zval passphrase_zval;
+ ZVAL_STRING(&passphrase_zval, net->options.ssl_passphrase, 0);
+ php_stream_context_set_option(context, "ssl", "passphrase", &passphrase_zval);
+ }
+ if (net->options.ssl_cipher) {
+ zval cipher_zval;
+ ZVAL_STRING(&cipher_zval, net->options.ssl_cipher, 0);
+ DBG_INF_FMT("ciphers=%s", net->options.ssl_cipher);
+ php_stream_context_set_option(context, "ssl", "ciphers", &cipher_zval);
+ }
+ php_stream_context_set(net->stream, context);
+ if (php_stream_xport_crypto_setup(net->stream, STREAM_CRYPTO_METHOD_TLS_CLIENT, NULL TSRMLS_CC) < 0 ||
+ php_stream_xport_crypto_enable(net->stream, 1 TSRMLS_CC) < 0)
+ {
+ DBG_ERR("Cannot connect to MySQL by using SSL");
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot connect to MySQL by using SSL");
+ DBG_RETURN(FAIL);
+ }
+ /*
+ get rid of the context. we are persistent and if this is a real pconn used by mysql/mysqli,
+ then the context would not survive cleaning of EG(regular_list), where it is registered, as a
+ resource. What happens is that after this destruction any use of the network will mean usage
+ of the context, which means usage of already freed memory, bad. Actually we don't need this
+ context anymore after we have enabled SSL on the connection. Thus it is very simple, we remove it.
+ */
+ php_stream_context_set(net->stream, NULL);
+
+ if (net->options.timeout_read) {
+ struct timeval tv;
+ DBG_INF_FMT("setting %u as PHP_STREAM_OPTION_READ_TIMEOUT", net->options.timeout_read);
+ tv.tv_sec = net->options.timeout_read;
+ tv.tv_usec = 0;
+ php_stream_set_option(net->stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &tv);
+ }
+
+ DBG_RETURN(PASS);
+#else
+ DBG_ENTER("mysqlnd_net::enable_ssl");
+ DBG_RETURN(PASS);
+#endif
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_net::disable_ssl */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_net, disable_ssl)(MYSQLND_NET * const net TSRMLS_DC)
+{
+ DBG_ENTER("mysqlnd_net::disable_ssl");
+ DBG_RETURN(PASS);
+}
+/* }}} */
/* {{{ mysqlnd_net::set_client_option */
static void
MYSQLND_METHOD(mysqlnd_net, free_contents)(MYSQLND_NET * net TSRMLS_DC)
{
+ zend_bool pers = net->persistent;
DBG_ENTER("mysqlnd_net::free_contents");
#ifdef MYSQLND_COMPRESSION_ENABLED
@@ -670,6 +828,27 @@ MYSQLND_METHOD(mysqlnd_net, free_contents)(MYSQLND_NET * net TSRMLS_DC)
net->uncompressed_data->free_buffer(&net->uncompressed_data TSRMLS_CC);
}
#endif
+ if (net->options.ssl_key) {
+ mnd_pefree(net->options.ssl_key, pers);
+ net->options.ssl_key = NULL;
+ }
+ if (net->options.ssl_cert) {
+ mnd_pefree(net->options.ssl_cert, pers);
+ net->options.ssl_cert = NULL;
+ }
+ if (net->options.ssl_ca) {
+ mnd_pefree(net->options.ssl_ca, pers);
+ net->options.ssl_ca = NULL;
+ }
+ if (net->options.ssl_capath) {
+ mnd_pefree(net->options.ssl_capath, pers);
+ net->options.ssl_capath = NULL;
+ }
+ if (net->options.ssl_cipher) {
+ mnd_pefree(net->options.ssl_cipher, pers);
+ net->options.ssl_cipher = NULL;
+ }
+
DBG_VOID_RETURN;
}
/* }}} */
@@ -696,6 +875,8 @@ mysqlnd_net_init(zend_bool persistent TSRMLS_DC)
net->m.encode = MYSQLND_METHOD(mysqlnd_net, encode);
net->m.consume_uneaten_data = MYSQLND_METHOD(mysqlnd_net, consume_uneaten_data);
net->m.free_contents = MYSQLND_METHOD(mysqlnd_net, free_contents);
+ net->m.enable_ssl = MYSQLND_METHOD(mysqlnd_net, enable_ssl);
+ net->m.disable_ssl = MYSQLND_METHOD(mysqlnd_net, disable_ssl);
{
unsigned int buf_size = MYSQLND_G(net_cmd_buffer_size); /* this is long, cast to unsigned int*/