mirror of
https://github.com/php/php-src.git
synced 2024-12-02 22:34:55 +08:00
split mysqlnd_connect() in two parts, one doing the authorization
This commit is contained in:
parent
377ffeb50a
commit
59205a6655
@ -444,6 +444,123 @@ MYSQLND_METHOD(mysqlnd_conn, end_psession)(MYSQLND * conn TSRMLS_DC)
|
||||
/* }}} */
|
||||
|
||||
|
||||
#define MYSQLND_ASSEBLED_PACKET_MAX_SIZE 3UL*1024UL*1024UL*1024UL
|
||||
/* {{{ mysqlnd_connect_run_authentication */
|
||||
static enum_func_status
|
||||
mysqlnd_connect_run_authentication(
|
||||
MYSQLND * conn,
|
||||
const char * const user,
|
||||
const char * const passwd,
|
||||
const char * const db,
|
||||
size_t db_len,
|
||||
const MYSQLND_PACKET_GREET * const greet_packet,
|
||||
const MYSQLND_OPTIONS * const options,
|
||||
unsigned long mysql_flags
|
||||
TSRMLS_DC)
|
||||
{
|
||||
const MYSQLND_CHARSET * charset = NULL;
|
||||
enum_func_status ret = FAIL;
|
||||
MYSQLND_PACKET_AUTH * auth_packet = conn->protocol->m.get_auth_packet(conn->protocol, FALSE TSRMLS_CC);
|
||||
MYSQLND_PACKET_OK * ok_packet = conn->protocol->m.get_ok_packet(conn->protocol, FALSE TSRMLS_CC);
|
||||
|
||||
DBG_ENTER("mysqlnd_connect_run_authentication");
|
||||
|
||||
if (!auth_packet || !ok_packet) {
|
||||
SET_OOM_ERROR(conn->error_info);
|
||||
goto err;
|
||||
}
|
||||
|
||||
#ifdef MYSQLND_SSL_SUPPORTED
|
||||
if ((greet_packet->server_capabilities & CLIENT_SSL) && (mysql_flags & CLIENT_SSL)) {
|
||||
auth_packet->send_half_packet = TRUE;
|
||||
}
|
||||
#endif
|
||||
auth_packet->user = user;
|
||||
auth_packet->password = passwd;
|
||||
|
||||
if (options->charset_name && (charset = mysqlnd_find_charset_name(options->charset_name))) {
|
||||
auth_packet->charset_no = charset->nr;
|
||||
} else {
|
||||
#if PHP_MAJOR_VERSION >= 6
|
||||
auth_packet->charset_no = 200;/* utf8 - swedish collation, check mysqlnd_charset.c */
|
||||
#else
|
||||
auth_packet->charset_no = greet_packet->charset_no;
|
||||
#endif
|
||||
}
|
||||
auth_packet->db = db;
|
||||
auth_packet->db_len = db_len;
|
||||
auth_packet->max_packet_size= MYSQLND_ASSEBLED_PACKET_MAX_SIZE;
|
||||
auth_packet->client_flags= mysql_flags;
|
||||
|
||||
conn->scramble = auth_packet->server_scramble_buf = mnd_pemalloc(SCRAMBLE_LENGTH, conn->persistent);
|
||||
if (!conn->scramble) {
|
||||
SET_OOM_ERROR(conn->error_info);
|
||||
goto err;
|
||||
}
|
||||
memcpy(auth_packet->server_scramble_buf, greet_packet->scramble_buf, SCRAMBLE_LENGTH);
|
||||
|
||||
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 err;
|
||||
}
|
||||
|
||||
#ifdef MYSQLND_SSL_SUPPORTED
|
||||
if (auth_packet->send_half_packet) {
|
||||
zend_bool verify = mysql_flags & CLIENT_SSL_VERIFY_SERVER_CERT? TRUE:FALSE;
|
||||
DBG_INF("Switching to SSL");
|
||||
|
||||
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 err;
|
||||
}
|
||||
|
||||
auth_packet->send_half_packet = FALSE;
|
||||
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 err;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (FAIL == PACKET_READ(ok_packet, conn) || ok_packet->field_count >= 0xFE) {
|
||||
if (ok_packet->field_count == 0xFE) {
|
||||
/* old authentication with new server !*/
|
||||
DBG_ERR(mysqlnd_old_passwd);
|
||||
SET_CLIENT_ERROR(conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, mysqlnd_old_passwd);
|
||||
} else if (ok_packet->field_count == 0xFF) {
|
||||
if (ok_packet->sqlstate[0]) {
|
||||
strlcpy(conn->error_info.sqlstate, ok_packet->sqlstate, sizeof(conn->error_info.sqlstate));
|
||||
DBG_ERR_FMT("ERROR:%d [SQLSTATE:%s] %s", ok_packet->error_no, ok_packet->sqlstate, ok_packet->error);
|
||||
}
|
||||
conn->error_info.error_no = ok_packet->error_no;
|
||||
strlcpy(conn->error_info.error, ok_packet->error, sizeof(conn->error_info.error));
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
|
||||
SET_NEW_MESSAGE(conn->last_message, conn->last_message_len,
|
||||
ok_packet->message, ok_packet->message_len,
|
||||
conn->persistent);
|
||||
conn->charset = mysqlnd_find_charset_nr(auth_packet->charset_no);
|
||||
ret = PASS;
|
||||
err:
|
||||
PACKET_FREE(auth_packet);
|
||||
PACKET_FREE(ok_packet);
|
||||
DBG_RETURN(ret);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
#define MYSQLND_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_TRANSACTIONS | \
|
||||
CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION | \
|
||||
CLIENT_MULTI_RESULTS)
|
||||
|
||||
|
||||
|
||||
/* {{{ mysqlnd_conn::connect */
|
||||
static enum_func_status
|
||||
MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
|
||||
@ -457,15 +574,11 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
|
||||
{
|
||||
char *errstr = NULL;
|
||||
int errcode = 0, host_len;
|
||||
zend_bool self_alloced = FALSE;
|
||||
zend_bool unix_socket = FALSE;
|
||||
const MYSQLND_CHARSET * charset;
|
||||
zend_bool reconnect = FALSE;
|
||||
zend_bool saved_compression = FALSE;
|
||||
|
||||
MYSQLND_PACKET_GREET * greet_packet = NULL;
|
||||
MYSQLND_PACKET_AUTH * auth_packet = NULL;
|
||||
MYSQLND_PACKET_OK * ok_packet = NULL;
|
||||
|
||||
DBG_ENTER("mysqlnd_conn::connect");
|
||||
|
||||
@ -536,7 +649,6 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
|
||||
if (!port) {
|
||||
port = 3306;
|
||||
}
|
||||
|
||||
transport_len = spprintf(&transport, 0, "tcp://%s:%d", host, port);
|
||||
}
|
||||
if (!transport) {
|
||||
@ -554,9 +666,7 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
|
||||
}
|
||||
|
||||
greet_packet = conn->protocol->m.get_greet_packet(conn->protocol, FALSE TSRMLS_CC);
|
||||
auth_packet = conn->protocol->m.get_auth_packet(conn->protocol, FALSE TSRMLS_CC);
|
||||
ok_packet = conn->protocol->m.get_ok_packet(conn->protocol, FALSE TSRMLS_CC);
|
||||
if (!greet_packet || !auth_packet || !ok_packet) {
|
||||
if (!greet_packet) {
|
||||
SET_OOM_ERROR(conn->error_info);
|
||||
goto err; /* OOM */
|
||||
}
|
||||
@ -590,7 +700,17 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
|
||||
|
||||
conn->greet_charset = mysqlnd_find_charset_nr(greet_packet->charset_no);
|
||||
/* we allow load data local infile by default */
|
||||
mysql_flags |= CLIENT_LOCAL_FILES | CLIENT_PS_MULTI_RESULTS;
|
||||
mysql_flags |= CLIENT_LOCAL_FILES | CLIENT_PS_MULTI_RESULTS;
|
||||
mysql_flags |= MYSQLND_CAPABILITIES;
|
||||
|
||||
if (db) {
|
||||
mysql_flags |= CLIENT_CONNECT_WITH_DB;
|
||||
}
|
||||
|
||||
if (PG(open_basedir) && strlen(PG(open_basedir))) {
|
||||
mysql_flags ^= CLIENT_LOCAL_FILES;
|
||||
}
|
||||
|
||||
#ifndef MYSQLND_COMPRESSION_ENABLED
|
||||
if (mysql_flags & CLIENT_COMPRESS) {
|
||||
mysql_flags &= ~CLIENT_COMPRESS;
|
||||
@ -606,81 +726,16 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
|
||||
{
|
||||
mysql_flags |= CLIENT_SSL;
|
||||
}
|
||||
if ((greet_packet->server_capabilities & CLIENT_SSL) && (mysql_flags & CLIENT_SSL)) {
|
||||
auth_packet->send_half_packet = TRUE;
|
||||
}
|
||||
#endif
|
||||
auth_packet->user = user;
|
||||
auth_packet->password = passwd;
|
||||
|
||||
if (conn->options.charset_name && (charset = mysqlnd_find_charset_name(conn->options.charset_name))) {
|
||||
auth_packet->charset_no = charset->nr;
|
||||
} else {
|
||||
#if PHP_MAJOR_VERSION >= 6
|
||||
auth_packet->charset_no = 200;/* utf8 - swedish collation, check mysqlnd_charset.c */
|
||||
#else
|
||||
auth_packet->charset_no = greet_packet->charset_no;
|
||||
#endif
|
||||
}
|
||||
auth_packet->db = db;
|
||||
auth_packet->db_len = db_len;
|
||||
auth_packet->max_packet_size= 3UL*1024UL*1024UL*1024UL;
|
||||
auth_packet->client_flags= mysql_flags;
|
||||
|
||||
conn->scramble = auth_packet->server_scramble_buf = mnd_pemalloc(SCRAMBLE_LENGTH, conn->persistent);
|
||||
if (!conn->scramble) {
|
||||
SET_OOM_ERROR(conn->error_info);
|
||||
goto err; /* OOM */
|
||||
}
|
||||
memcpy(auth_packet->server_scramble_buf, greet_packet->scramble_buf, SCRAMBLE_LENGTH);
|
||||
|
||||
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);
|
||||
if (FAIL == mysqlnd_connect_run_authentication(conn, user, passwd, db, db_len, greet_packet, &conn->options, mysql_flags TSRMLS_CC)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
#ifdef MYSQLND_SSL_SUPPORTED
|
||||
if (auth_packet->send_half_packet) {
|
||||
zend_bool verify = mysql_flags & CLIENT_SSL_VERIFY_SERVER_CERT? TRUE:FALSE;
|
||||
DBG_INF("Switching to SSL");
|
||||
|
||||
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 err;
|
||||
}
|
||||
|
||||
auth_packet->send_half_packet = FALSE;
|
||||
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 err;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (FAIL == PACKET_READ(ok_packet, conn) || ok_packet->field_count >= 0xFE) {
|
||||
if (ok_packet->field_count == 0xFE) {
|
||||
/* old authentication with new server !*/
|
||||
DBG_ERR(mysqlnd_old_passwd);
|
||||
SET_CLIENT_ERROR(conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, mysqlnd_old_passwd);
|
||||
} else if (ok_packet->field_count == 0xFF) {
|
||||
if (ok_packet->sqlstate[0]) {
|
||||
if (!self_alloced) {
|
||||
strlcpy(conn->error_info.sqlstate, ok_packet->sqlstate, sizeof(conn->error_info.sqlstate));
|
||||
}
|
||||
DBG_ERR_FMT("ERROR:%d [SQLSTATE:%s] %s", ok_packet->error_no, ok_packet->sqlstate, ok_packet->error);
|
||||
}
|
||||
if (!self_alloced) {
|
||||
conn->error_info.error_no = ok_packet->error_no;
|
||||
strlcpy(conn->error_info.error, ok_packet->error, sizeof(conn->error_info.error));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
{
|
||||
CONN_SET_STATE(conn, CONN_READY);
|
||||
|
||||
if (!self_alloced && saved_compression) {
|
||||
if (saved_compression) {
|
||||
conn->net->compressed = TRUE;
|
||||
}
|
||||
/*
|
||||
@ -733,32 +788,18 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
|
||||
}
|
||||
conn->unix_socket_len = strlen(conn->unix_socket);
|
||||
}
|
||||
conn->client_flag = auth_packet->client_flags;
|
||||
conn->max_packet_size = auth_packet->max_packet_size;
|
||||
conn->client_flag = mysql_flags;
|
||||
conn->max_packet_size = MYSQLND_ASSEBLED_PACKET_MAX_SIZE;
|
||||
/* todo: check if charset is available */
|
||||
conn->charset = mysqlnd_find_charset_nr(auth_packet->charset_no);
|
||||
conn->server_capabilities = greet_packet->server_capabilities;
|
||||
conn->upsert_status.warning_count = 0;
|
||||
conn->upsert_status.server_status = greet_packet->server_status;
|
||||
conn->upsert_status.affected_rows = 0;
|
||||
SET_NEW_MESSAGE(conn->last_message, conn->last_message_len,
|
||||
ok_packet->message, ok_packet->message_len,
|
||||
conn->persistent);
|
||||
|
||||
SET_EMPTY_ERROR(conn->error_info);
|
||||
|
||||
mysqlnd_local_infile_default(conn);
|
||||
|
||||
MYSQLND_INC_CONN_STATISTIC_W_VALUE2(conn->stats, STAT_CONNECT_SUCCESS, 1, STAT_OPENED_CONNECTIONS, 1);
|
||||
if (reconnect) {
|
||||
MYSQLND_INC_GLOBAL_STATISTIC(STAT_RECONNECT);
|
||||
}
|
||||
if (conn->persistent) {
|
||||
MYSQLND_INC_CONN_STATISTIC_W_VALUE2(conn->stats, STAT_PCONNECT_SUCCESS, 1, STAT_OPENED_PERSISTENT_CONNECTIONS, 1);
|
||||
}
|
||||
|
||||
DBG_INF_FMT("connection_id=%llu", conn->thread_id);
|
||||
|
||||
#if PHP_MAJOR_VERSION >= 6
|
||||
{
|
||||
unsigned int as_unicode = 1;
|
||||
@ -786,16 +827,23 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MYSQLND_INC_CONN_STATISTIC_W_VALUE2(conn->stats, STAT_CONNECT_SUCCESS, 1, STAT_OPENED_CONNECTIONS, 1);
|
||||
if (reconnect) {
|
||||
MYSQLND_INC_GLOBAL_STATISTIC(STAT_RECONNECT);
|
||||
}
|
||||
if (conn->persistent) {
|
||||
MYSQLND_INC_CONN_STATISTIC_W_VALUE2(conn->stats, STAT_PCONNECT_SUCCESS, 1, STAT_OPENED_PERSISTENT_CONNECTIONS, 1);
|
||||
}
|
||||
|
||||
DBG_INF_FMT("connection_id=%llu", conn->thread_id);
|
||||
|
||||
PACKET_FREE(greet_packet);
|
||||
PACKET_FREE(auth_packet);
|
||||
PACKET_FREE(ok_packet);
|
||||
|
||||
DBG_RETURN(PASS);
|
||||
}
|
||||
err:
|
||||
PACKET_FREE(greet_packet);
|
||||
PACKET_FREE(auth_packet);
|
||||
PACKET_FREE(ok_packet);
|
||||
|
||||
if (errstr) {
|
||||
DBG_ERR_FMT("[%d] %.64s (trying to connect via %s)", errcode, errstr, conn->scheme);
|
||||
@ -804,11 +852,6 @@ err:
|
||||
/* no mnd_ since we don't allocate it */
|
||||
efree(errstr);
|
||||
}
|
||||
if (conn->scheme) {
|
||||
/* no mnd_ since we don't allocate it */
|
||||
mnd_pefree(conn->scheme, conn->persistent);
|
||||
conn->scheme = NULL;
|
||||
}
|
||||
|
||||
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_CONNECT_FAILURE);
|
||||
|
||||
|
@ -405,11 +405,6 @@ void php_mysqlnd_greet_free_mem(void *_packet, zend_bool alloca TSRMLS_DC)
|
||||
/* }}} */
|
||||
|
||||
|
||||
#define MYSQLND_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_TRANSACTIONS | \
|
||||
CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION | \
|
||||
CLIENT_MULTI_RESULTS)
|
||||
|
||||
|
||||
/* {{{ php_mysqlnd_crypt */
|
||||
static void
|
||||
php_mysqlnd_crypt(zend_uchar *buffer, const zend_uchar *s1, const zend_uchar *s2, size_t len)
|
||||
@ -465,16 +460,6 @@ size_t php_mysqlnd_auth_write(void *_packet, MYSQLND * conn TSRMLS_DC)
|
||||
|
||||
DBG_ENTER("php_mysqlnd_auth_write");
|
||||
|
||||
packet->client_flags |= MYSQLND_CAPABILITIES;
|
||||
|
||||
if (packet->db) {
|
||||
packet->client_flags |= CLIENT_CONNECT_WITH_DB;
|
||||
}
|
||||
|
||||
if (PG(open_basedir) && strlen(PG(open_basedir))) {
|
||||
packet->client_flags ^= CLIENT_LOCAL_FILES;
|
||||
}
|
||||
|
||||
int4store(p, packet->client_flags);
|
||||
p+= 4;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user