diff options
author | Stanislav Malyshev <stas@php.net> | 2015-07-05 00:00:53 -0700 |
---|---|---|
committer | Stanislav Malyshev <stas@php.net> | 2015-07-07 09:38:31 -0700 |
commit | 97aa752fee61fccdec361279adbfb17a3c60f3f4 (patch) | |
tree | 773d8f16304441530453130f7ca32495b589f58a /ext/mysqlnd | |
parent | 6dedeb40db13971af45276f80b5375030aa7e76f (diff) | |
download | php-git-97aa752fee61fccdec361279adbfb17a3c60f3f4.tar.gz |
Fix bug #69669 (mysqlnd is vulnerable to BACKRONYM)
Diffstat (limited to 'ext/mysqlnd')
-rw-r--r-- | ext/mysqlnd/mysqlnd.c | 65 |
1 files changed, 40 insertions, 25 deletions
diff --git a/ext/mysqlnd/mysqlnd.c b/ext/mysqlnd/mysqlnd.c index d265dfd392..61daf96887 100644 --- a/ext/mysqlnd/mysqlnd.c +++ b/ext/mysqlnd/mysqlnd.c @@ -378,7 +378,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, set_server_option)(MYSQLND_CONN_DATA * const c int2store(buffer, (unsigned int) option); ret = conn->m->simple_command(conn, COM_SET_OPTION, buffer, sizeof(buffer), PROT_EOF_PACKET, FALSE, TRUE TSRMLS_CC); - + conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC); } DBG_RETURN(ret); @@ -446,26 +446,41 @@ mysqlnd_switch_to_ssl_if_needed( } #ifdef MYSQLND_SSL_SUPPORTED - if ((greet_packet->server_capabilities & CLIENT_SSL) && (mysql_flags & CLIENT_SSL)) { - zend_bool verify = mysql_flags & CLIENT_SSL_VERIFY_SERVER_CERT? TRUE:FALSE; - DBG_INF("Switching to SSL"); - if (!PACKET_WRITE(auth_packet, conn)) { - CONN_SET_STATE(conn, CONN_QUIT_SENT); - SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone); - goto end; - } + if (mysql_flags & CLIENT_SSL) { + zend_bool server_has_ssl = (greet_packet->server_capabilities & CLIENT_SSL)? TRUE:FALSE; + if (server_has_ssl == FALSE) { + goto close_conn; + } else { + zend_bool verify = mysql_flags & CLIENT_SSL_VERIFY_SERVER_CERT? TRUE:FALSE; + DBG_INF("Switching to SSL"); + if (!PACKET_WRITE(auth_packet, conn)) { + goto close_conn; + } - conn->net->m.set_client_option(conn->net, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (const char *) &verify TSRMLS_CC); + conn->net->m.set_client_option(conn->net, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (const char *) &verify TSRMLS_CC); - if (FAIL == conn->net->m.enable_ssl(conn->net TSRMLS_CC)) { - goto end; + if (FAIL == conn->net->m.enable_ssl(conn->net TSRMLS_CC)) { + goto end; + } } } +#else + auth_packet->client_flags &= ~CLIENT_SSL; + if (!PACKET_WRITE(auth_packet, conn)) { + goto close_conn; + } #endif ret = PASS; end: PACKET_FREE(auth_packet); DBG_RETURN(ret); + +close_conn: + CONN_SET_STATE(conn, CONN_QUIT_SENT); + conn->m->send_close(conn TSRMLS_CC); + SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone); + PACKET_FREE(auth_packet); + DBG_RETURN(ret); } /* }}} */ @@ -587,7 +602,7 @@ mysqlnd_connect_run_authentication( if (plugin_data) { mnd_efree(plugin_data); } - + if (ret == PASS) { DBG_INF_FMT("saving requested_protocol=%s", requested_protocol); conn->m->set_client_option(conn, MYSQLND_OPT_AUTH_PROTOCOL, requested_protocol TSRMLS_CC); @@ -1438,7 +1453,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, sqlstate)(const MYSQLND_CONN_DATA * const conn /* {{{ mysqlnd_old_escape_string */ -PHPAPI ulong +PHPAPI ulong mysqlnd_old_escape_string(char * newstr, const char * escapestr, size_t escapestr_len TSRMLS_DC) { DBG_ENTER("mysqlnd_old_escape_string"); @@ -1599,7 +1614,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, statistic)(MYSQLND_CONN_DATA * conn, char **me if (PASS == (ret = PACKET_READ(stats_header, conn))) { /* will be freed by Zend, thus don't use the mnd_ allocator */ - *message = estrndup(stats_header->message, stats_header->message_len); + *message = estrndup(stats_header->message, stats_header->message_len); *message_len = stats_header->message_len; DBG_INF(*message); } @@ -1724,7 +1739,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, shutdown)(MYSQLND_CONN_DATA * const conn, uint conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC); } - DBG_RETURN(ret); + DBG_RETURN(ret); } /* }}} */ @@ -2243,7 +2258,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, change_user)(MYSQLND_CONN_DATA * const conn, */ end: if (TRUE == local_tx_started) { - conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC); + conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC); } DBG_INF(ret == PASS? "PASS":"FAIL"); DBG_RETURN(ret); @@ -2335,7 +2350,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, set_client_option)(MYSQLND_CONN_DATA * const c ret = FAIL; break; } - + new_charset_name = mnd_pestrdup(value, conn->persistent); if (!new_charset_name) { goto oom; @@ -2401,11 +2416,11 @@ MYSQLND_METHOD(mysqlnd_conn_data, set_client_option)(MYSQLND_CONN_DATA * const c default: ret = FAIL; } - conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC); + conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC); DBG_RETURN(ret); oom: SET_OOM_ERROR(*conn->error_info); - conn->m->local_tx_end(conn, this_func, FAIL TSRMLS_CC); + conn->m->local_tx_end(conn, this_func, FAIL TSRMLS_CC); end: DBG_RETURN(FAIL); } @@ -2446,7 +2461,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, use_result)(MYSQLND_CONN_DATA * const conn TSR conn->current_result = NULL; } while (0); - conn->m->local_tx_end(conn, this_func, result == NULL? FAIL:PASS TSRMLS_CC); + conn->m->local_tx_end(conn, this_func, result == NULL? FAIL:PASS TSRMLS_CC); } DBG_RETURN(result); @@ -2486,7 +2501,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, store_result)(MYSQLND_CONN_DATA * const conn T conn->current_result = NULL; } while (0); - conn->m->local_tx_end(conn, this_func, result == NULL? FAIL:PASS TSRMLS_CC); + conn->m->local_tx_end(conn, this_func, result == NULL? FAIL:PASS TSRMLS_CC); } DBG_RETURN(result); } @@ -2515,7 +2530,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, set_autocommit)(MYSQLND_CONN_DATA * conn, unsi if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) { ret = conn->m->query(conn, (mode) ? "SET AUTOCOMMIT=1":"SET AUTOCOMMIT=0", sizeof("SET AUTOCOMMIT=1") - 1 TSRMLS_CC); - conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC); + conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC); } DBG_RETURN(ret); @@ -2533,7 +2548,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, tx_commit)(MYSQLND_CONN_DATA * conn TSRMLS_DC) if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) { ret = conn->m->query(conn, "COMMIT", sizeof("COMMIT") - 1 TSRMLS_CC); - conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC); + conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC); } DBG_RETURN(ret); @@ -2551,7 +2566,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, tx_rollback)(MYSQLND_CONN_DATA * conn TSRMLS_D if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) { ret = conn->m->query(conn, "ROLLBACK", sizeof("ROLLBACK") - 1 TSRMLS_CC); - conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC); + conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC); } DBG_RETURN(ret); |