Update on the mysqlnd auth plugins, changed the plugin

structure and where they load themselves.
0xFE packets (method switch) needs to be done, additional
wire-level packet to be created to be parsed and the packet
doesn't fit the PACKET_OK structure anymore.
This commit is contained in:
Andrey Hristov 2011-01-14 20:04:17 +00:00
parent a3391dce9f
commit 16c6ce94d2
6 changed files with 174 additions and 93 deletions

View File

@ -177,10 +177,10 @@ MYSQLND_METHOD(mysqlnd_conn, free_contents)(MYSQLND * conn TSRMLS_DC)
mnd_pefree(conn->host_info, pers);
conn->host_info = NULL;
}
if (conn->scramble) {
DBG_INF("Freeing scramble");
mnd_pefree(conn->scramble, pers);
conn->scramble = NULL;
if (conn->auth_plugin_data) {
DBG_INF("Freeing auth_plugin_data");
mnd_pefree(conn->auth_plugin_data, pers);
conn->auth_plugin_data = NULL;
}
if (conn->last_message) {
mnd_pefree(conn->last_message, pers);
@ -524,15 +524,15 @@ mysqlnd_connect_run_authentication(
auth_plugin = mysqlnd_plugin_find(plugin_name);
efree(plugin_name);
if (!auth_plugin) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Server requested authentication method uknown to the client [%s]", requested_protocol);
SET_CLIENT_ERROR(conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "Server requested authentication method uknown to the client");
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The server requested authentication method uknown to the client [%s]", requested_protocol);
SET_CLIENT_ERROR(conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "The server requested authentication method uknown to the client");
break;
}
DBG_INF("plugin found");
ret = auth_plugin->methods.auth_handshake(conn, user, passwd, db, db_len, passwd_len, greet_packet, options, mysql_flags,
&switch_to_auth_protocol TSRMLS_CC);
ret = mysqlnd_auth_handshake(conn, user, passwd, db, db_len, passwd_len, greet_packet, options, mysql_flags,
auth_plugin, &switch_to_auth_protocol TSRMLS_CC);
DBG_INF_FMT("switch_to_auth_protocol=%s", switch_to_auth_protocol? switch_to_auth_protocol:"n/a");
} while (ret == FAIL && switch_to_auth_protocol != NULL);
@ -1942,6 +1942,7 @@ MYSQLND_METHOD(mysqlnd_conn, change_user)(MYSQLND * const conn,
db = "";
}
{
char * switch_to_auth_protocol = NULL;
const char * requested_protocol = NULL;
@ -1961,13 +1962,15 @@ MYSQLND_METHOD(mysqlnd_conn, change_user)(MYSQLND * const conn,
efree(plugin_name);
if (!auth_plugin) {
if (!silent) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Server requested authentication method uknown to the client [%s]", requested_protocol);
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The server requested authentication method uknown to the client [%s]", requested_protocol);
}
SET_CLIENT_ERROR(conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "Server requested authentication method uknown to the client");
SET_CLIENT_ERROR(conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "The server requested authentication method uknown to the client");
break;
}
DBG_INF("plugin found");
ret = auth_plugin->methods.auth_change_user(conn, user, strlen(user), passwd, db, strlen(db), passwd_len, silent, &switch_to_auth_protocol TSRMLS_CC);
ret = mysqlnd_auth_change_user(conn, user, strlen(user), passwd, db, strlen(db), passwd_len, silent,
auth_plugin, &switch_to_auth_protocol TSRMLS_CC);
DBG_INF_FMT("switch_to_auth_protocol=%s", switch_to_auth_protocol? switch_to_auth_protocol:"n/a");
} while (ret == FAIL && switch_to_auth_protocol != NULL);
if (ret == PASS) {

View File

@ -30,8 +30,8 @@
/* {{{ mysqlnd_native_auth_handshake */
static enum_func_status
mysqlnd_native_auth_handshake(MYSQLND * conn,
enum_func_status
mysqlnd_auth_handshake(MYSQLND * conn,
const char * const user,
const char * const passwd,
const char * const db,
@ -40,6 +40,7 @@ mysqlnd_native_auth_handshake(MYSQLND * conn,
const MYSQLND_PACKET_GREET * const greet_packet,
const MYSQLND_OPTIONS * const options,
unsigned long mysql_flags,
struct st_mysqlnd_authentication_plugin * auth_plugin,
char ** switch_to_auth_protocol
TSRMLS_DC)
{
@ -50,14 +51,6 @@ mysqlnd_native_auth_handshake(MYSQLND * conn,
DBG_ENTER("mysqlnd_native_auth_handshake");
/* 5.5.x reports 21 as scramble length because it needs to show the length of the data before the plugin name */
if (greet_packet->scramble_buf_len != SCRAMBLE_LENGTH && (greet_packet->scramble_buf_len != 21)) {
/* mysql_native_password only works with SCRAMBLE_LENGTH scramble */
SET_CLIENT_ERROR(conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "The server sent wrong length for scramble");
DBG_ERR_FMT("The server sent wrong length for scramble %u. Expected %u", greet_packet->scramble_buf_len, SCRAMBLE_LENGTH);
goto end;
}
ok_packet = conn->protocol->m.get_ok_packet(conn->protocol, FALSE TSRMLS_CC);
auth_packet = conn->protocol->m.get_auth_packet(conn->protocol, FALSE TSRMLS_CC);
@ -80,17 +73,21 @@ mysqlnd_native_auth_handshake(MYSQLND * conn,
auth_packet->send_auth_data = TRUE;
auth_packet->user = user;
auth_packet->password = passwd;
auth_packet->db = db;
auth_packet->db_len = db_len;
auth_packet->server_scramble_buf_len = greet_packet->scramble_buf_len;
conn->scramble = auth_packet->server_scramble_buf = mnd_pemalloc(auth_packet->server_scramble_buf_len, conn->persistent);
if (!conn->scramble) {
conn->auth_plugin_data_len = greet_packet->auth_plugin_data_len;
conn->auth_plugin_data = mnd_pemalloc(conn->auth_plugin_data_len, conn->persistent);
if (!conn->auth_plugin_data) {
SET_OOM_ERROR(conn->error_info);
goto end;
}
memcpy(auth_packet->server_scramble_buf, greet_packet->scramble_buf, greet_packet->scramble_buf_len);
memcpy(conn->auth_plugin_data, greet_packet->auth_plugin_data, greet_packet->auth_plugin_data_len);
auth_packet->auth_data =
auth_plugin->methods.get_auth_data(NULL, &auth_packet->auth_data_len, conn, user, passwd, passwd_len,
conn->auth_plugin_data, conn->auth_plugin_data_len, options, mysql_flags TSRMLS_CC);
if (!PACKET_WRITE(auth_packet, conn)) {
CONN_SET_STATE(conn, CONN_QUIT_SENT);
@ -118,6 +115,7 @@ mysqlnd_native_auth_handshake(MYSQLND * conn,
conn->charset = mysqlnd_find_charset_nr(auth_packet->charset_no);
ret = PASS;
end:
mnd_efree(auth_packet->auth_data);
PACKET_FREE(auth_packet);
PACKET_FREE(ok_packet);
DBG_RETURN(ret);
@ -126,8 +124,8 @@ end:
/* {{{ mysqlnd_native_auth_change_user */
static enum_func_status
mysqlnd_native_auth_change_user(MYSQLND * const conn,
enum_func_status
mysqlnd_auth_change_user(MYSQLND * const conn,
const char * const user,
const size_t user_len,
const char * const passwd,
@ -135,6 +133,7 @@ mysqlnd_native_auth_change_user(MYSQLND * const conn,
const size_t db_len,
const size_t passwd_len,
const zend_bool silent,
struct st_mysqlnd_authentication_plugin * auth_plugin,
char ** switch_to_auth_protocol
TSRMLS_DC)
{
@ -156,13 +155,17 @@ mysqlnd_native_auth_change_user(MYSQLND * const conn,
SET_OOM_ERROR(conn->error_info);
goto end;
}
auth_packet->is_change_user_packet = TRUE;
auth_packet->user = user;
auth_packet->password = passwd;
auth_packet->db = db;
auth_packet->db_len = db_len;
auth_packet->server_scramble_buf = conn->scramble;
auth_packet->silent = silent;
auth_packet->auth_data =
auth_plugin->methods.get_auth_data(NULL, &auth_packet->auth_data_len, conn, user, passwd, passwd_len,
conn->auth_plugin_data, conn->auth_plugin_data_len, NULL /* options */, 0 /* mysql_flags */ TSRMLS_CC);
if (mysqlnd_get_server_version(conn) >= 50123) {
auth_packet->charset_no = conn->charset->nr;
p+=2;
@ -225,12 +228,47 @@ mysqlnd_native_auth_change_user(MYSQLND * const conn,
SET_CLIENT_ERROR(conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, mysqlnd_old_passwd);
}
end:
mnd_efree(auth_packet->auth_data);
PACKET_FREE(auth_packet);
PACKET_FREE(chg_user_resp);
DBG_RETURN(ret);
}
/* }}} */
/* {{{ mysqlnd_native_auth_get_auth_data */
static zend_uchar *
mysqlnd_native_auth_get_auth_data(struct st_mysqlnd_authentication_plugin * self,
size_t * auth_data_len,
MYSQLND * conn, const char * const user, const char * const passwd,
const size_t passwd_len, zend_uchar * auth_plugin_data, size_t auth_plugin_data_len,
const MYSQLND_OPTIONS * const options, unsigned long mysql_flags
TSRMLS_DC)
{
zend_uchar * ret = NULL;
DBG_ENTER("mysqlnd_native_auth_get_auth_data");
*auth_data_len = 0;
/* 5.5.x reports 21 as scramble length because it needs to show the length of the data before the plugin name */
if (auth_plugin_data_len != SCRAMBLE_LENGTH && (auth_plugin_data_len != 21)) {
/* mysql_native_password only works with SCRAMBLE_LENGTH scramble */
SET_CLIENT_ERROR(conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "The server sent wrong length for scramble");
DBG_ERR_FMT("The server sent wrong length for scramble %u. Expected %u", auth_plugin_data_len, SCRAMBLE_LENGTH);
DBG_RETURN(NULL);
}
/* copy scrambled pass*/
if (passwd && passwd_len) {
ret = mnd_emalloc(SCRAMBLE_LENGTH);
*auth_data_len = SCRAMBLE_LENGTH;
/* In 4.1 we use CLIENT_SECURE_CONNECTION and thus the len of the buf should be passed */
php_mysqlnd_scramble((zend_uchar*)ret, auth_plugin_data, (zend_uchar*)passwd, passwd_len);
}
DBG_RETURN(ret);
}
/* }}} */
static struct st_mysqlnd_authentication_plugin mysqlnd_native_auth_plugin =
{
{
@ -249,11 +287,11 @@ static struct st_mysqlnd_authentication_plugin mysqlnd_native_auth_plugin =
}
},
{/* methods */
mysqlnd_native_auth_handshake,
mysqlnd_native_auth_change_user
mysqlnd_native_auth_get_auth_data
}
};
/* {{{ mysqlnd_native_authentication_plugin_register */
void
mysqlnd_native_authentication_plugin_register(TSRMLS_D)

View File

@ -196,6 +196,36 @@ void mysqlnd_native_authentication_plugin_register(TSRMLS_D);
void mysqlnd_example_plugin_register(TSRMLS_D);
struct st_mysqlnd_packet_greet;
struct st_mysqlnd_authentication_plugin;
enum_func_status
mysqlnd_auth_handshake(MYSQLND * conn,
const char * const user,
const char * const passwd,
const char * const db,
const size_t db_len,
const size_t passwd_len,
const struct st_mysqlnd_packet_greet * const greet_packet,
const MYSQLND_OPTIONS * const options,
unsigned long mysql_flags,
struct st_mysqlnd_authentication_plugin * auth_plugin,
char ** switch_to_auth_protocol
TSRMLS_DC);
enum_func_status
mysqlnd_auth_change_user(MYSQLND * const conn,
const char * const user,
const size_t user_len,
const char * const passwd,
const char * const db,
const size_t db_len,
const size_t passwd_len,
const zend_bool silent,
struct st_mysqlnd_authentication_plugin * auth_plugin,
char ** switch_to_auth_protocol
TSRMLS_DC);
#endif /* MYSQLND_PRIV_H */

View File

@ -736,7 +736,8 @@ struct st_mysqlnd_connection
uint64_t thread_id;
char *server_version;
char *host_info;
unsigned char *scramble;
zend_uchar *auth_plugin_data;
size_t auth_plugin_data_len;
const MYSQLND_CHARSET *charset;
const MYSQLND_CHARSET *greet_charset;
char *connect_or_select_db;
@ -964,21 +965,22 @@ struct st_mysqlnd_typeii_plugin_example
unsigned int counter;
};
struct st_mysqlnd_packet_greet;
struct st_mysqlnd_authentication_plugin;
typedef zend_uchar * (*func_auth_plugin__get_auth_data)(struct st_mysqlnd_authentication_plugin * self,
size_t * auth_data_len,
MYSQLND * conn, const char * const user, const char * const passwd,
const size_t passwd_len, zend_uchar * auth_plugin_data, size_t auth_plugin_data_len,
const MYSQLND_OPTIONS * const options, unsigned long mysql_flags
TSRMLS_DC);
struct st_mysqlnd_authentication_plugin
{
struct st_mysqlnd_plugin_header plugin_header;
struct {
enum_func_status (*auth_handshake)(MYSQLND * conn, const char * const user, const char * const passwd, const char * const db,
const size_t db_len, const size_t passwd_len, const struct st_mysqlnd_packet_greet * const greet_packet,
const MYSQLND_OPTIONS * const options, unsigned long mysql_flags,
char ** switch_to_auth_protocol TSRMLS_DC);
enum_func_status (*auth_change_user)(MYSQLND * const conn, const char * const user, const size_t user_len, const char * const passwd,
const char * const db, const size_t db_len, const size_t passwd_len, const zend_bool silent,
char ** switch_to_auth_protocol TSRMLS_DC);
func_auth_plugin__get_auth_data get_auth_data;
} methods;
};
#endif /* MYSQLND_STRUCTS_H */

View File

@ -314,8 +314,8 @@ php_mysqlnd_greet_read(void *_packet, MYSQLND *conn TSRMLS_DC)
PACKET_READ_HEADER_AND_BODY(packet, conn, buf, sizeof(buf), "greeting", PROT_GREET_PACKET);
BAIL_IF_NO_MORE_DATA;
packet->scramble_buf = &packet->intern_scramble_buf;
packet->scramble_buf_len = sizeof(packet->intern_scramble_buf);
packet->auth_plugin_data = packet->intern_auth_plugin_data;
packet->auth_plugin_data_len = sizeof(packet->intern_auth_plugin_data);
if (packet->header.size < sizeof(buf)) {
/*
@ -353,7 +353,7 @@ php_mysqlnd_greet_read(void *_packet, MYSQLND *conn TSRMLS_DC)
p+=4;
BAIL_IF_NO_MORE_DATA;
memcpy(packet->scramble_buf, p, SCRAMBLE_LENGTH_323);
memcpy(packet->auth_plugin_data, p, SCRAMBLE_LENGTH_323);
p+= SCRAMBLE_LENGTH_323;
BAIL_IF_NO_MORE_DATA;
@ -379,8 +379,8 @@ php_mysqlnd_greet_read(void *_packet, MYSQLND *conn TSRMLS_DC)
BAIL_IF_NO_MORE_DATA;
if ((size_t) (p - buf) < packet->header.size) {
/* scramble_buf is split into two parts */
memcpy(packet->scramble_buf + SCRAMBLE_LENGTH_323, p, SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
/* auth_plugin_data is split into two parts */
memcpy(packet->auth_plugin_data + SCRAMBLE_LENGTH_323, p, SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
p+= SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323;
p++; /* 0x0 at the end of the scramble and thus last byte in the packet in 5.1 and previous */
} else {
@ -395,19 +395,19 @@ php_mysqlnd_greet_read(void *_packet, MYSQLND *conn TSRMLS_DC)
/* Additional 16 bits for server capabilities */
packet->server_capabilities |= uint2korr(pad_start) << 16;
/* And a length of the server scramble in one byte */
packet->scramble_buf_len = uint1korr(pad_start + 2);
if (packet->scramble_buf_len > SCRAMBLE_LENGTH) {
packet->auth_plugin_data_len = uint1korr(pad_start + 2);
if (packet->auth_plugin_data_len > SCRAMBLE_LENGTH) {
/* more data*/
char * new_scramble_buf = emalloc(packet->scramble_buf_len);
if (!new_scramble_buf) {
zend_uchar * new_auth_plugin_data = emalloc(packet->auth_plugin_data_len);
if (!new_auth_plugin_data) {
goto premature_end;
}
/* copy what we already have */
memcpy(new_scramble_buf, packet->scramble_buf, SCRAMBLE_LENGTH);
memcpy(new_auth_plugin_data, packet->auth_plugin_data, SCRAMBLE_LENGTH);
/* add additional scramble data 5.5+ sent us */
memcpy(new_scramble_buf + SCRAMBLE_LENGTH, p, packet->scramble_buf_len - SCRAMBLE_LENGTH);
p+= (packet->scramble_buf_len - SCRAMBLE_LENGTH);
packet->scramble_buf = new_scramble_buf;
memcpy(new_auth_plugin_data + SCRAMBLE_LENGTH, p, packet->auth_plugin_data_len - SCRAMBLE_LENGTH);
p+= (packet->auth_plugin_data_len - SCRAMBLE_LENGTH);
packet->auth_plugin_data = new_auth_plugin_data;
}
}
@ -423,7 +423,7 @@ php_mysqlnd_greet_read(void *_packet, MYSQLND *conn TSRMLS_DC)
DBG_INF_FMT("server_capabilities=%u charset_no=%u server_status=%i auth_protocol=%s scramble_length=%u",
packet->server_capabilities, packet->charset_no, packet->server_status,
packet->auth_protocol? packet->auth_protocol:"n/a", packet->scramble_buf_len);
packet->auth_protocol? packet->auth_protocol:"n/a", packet->auth_plugin_data_len);
DBG_RETURN(PASS);
premature_end:
@ -444,9 +444,9 @@ void php_mysqlnd_greet_free_mem(void *_packet, zend_bool stack_allocation TSRMLS
efree(p->server_version);
p->server_version = NULL;
}
if (p->scramble_buf && p->scramble_buf != &p->intern_scramble_buf) {
efree(p->scramble_buf);
p->scramble_buf = NULL;
if (p->auth_plugin_data && p->auth_plugin_data != p->intern_auth_plugin_data) {
efree(p->auth_plugin_data);
p->auth_plugin_data = NULL;
}
if (p->auth_protocol) {
efree(p->auth_protocol);
@ -472,7 +472,7 @@ php_mysqlnd_crypt(zend_uchar *buffer, const zend_uchar *s1, const zend_uchar *s2
/* {{{ php_mysqlnd_scramble */
void php_mysqlnd_scramble(zend_uchar * const buffer, const zend_uchar * const scramble, const zend_uchar * const password)
void php_mysqlnd_scramble(zend_uchar * const buffer, const zend_uchar * const scramble, const zend_uchar * const password, size_t password_len)
{
PHP_SHA1_CTX context;
zend_uchar sha1[SHA1_MAX_LENGTH];
@ -480,7 +480,7 @@ void php_mysqlnd_scramble(zend_uchar * const buffer, const zend_uchar * const sc
/* Phase 1: hash password */
PHP_SHA1Init(&context);
PHP_SHA1Update(&context, password, strlen((char *)password));
PHP_SHA1Update(&context, password, password_len);
PHP_SHA1Final(sha1, &context);
/* Phase 2: hash sha1 */
@ -500,7 +500,7 @@ void php_mysqlnd_scramble(zend_uchar * const buffer, const zend_uchar * const sc
/* }}} */
#define AUTH_WRITE_BUFFER_LEN (MYSQLND_HEADER_SIZE + MYSQLND_MAX_ALLOWED_USER_LEN + SCRAMBLE_LENGTH + MYSQLND_MAX_ALLOWED_DB_LEN + 1 + 128)
#define AUTH_WRITE_BUFFER_LEN (MYSQLND_HEADER_SIZE + MYSQLND_MAX_ALLOWED_USER_LEN + SCRAMBLE_LENGTH + MYSQLND_MAX_ALLOWED_DB_LEN + 1 + 1024)
/* {{{ php_mysqlnd_auth_write */
static
@ -533,17 +533,20 @@ size_t php_mysqlnd_auth_write(void *_packet, MYSQLND * conn TSRMLS_DC)
p+= len;
*p++ = '\0';
/* copy scrambled pass*/
if (packet->password && packet->password[0]) {
/* In 4.1 we use CLIENT_SECURE_CONNECTION and thus the len of the buf should be passed */
int1store(p, SCRAMBLE_LENGTH);
p++;
php_mysqlnd_scramble((zend_uchar*)p, packet->server_scramble_buf, (zend_uchar*)packet->password);
p+= SCRAMBLE_LENGTH;
} else {
/* Zero length */
int1store(p, 0);
p++;
/* defensive coding */
if (!packet->auth_data) {
packet->auth_data = 0;
}
int1store(p, packet->auth_data_len);
++p;
/*!!!!! is the buffer big enough ??? */
if ((sizeof(buffer) - (p - buffer)) < packet->auth_data_len) {
DBG_ERR("the stack buffer was not enough!!");
DBG_RETURN(0);
}
if (packet->auth_data_len) {
memcpy(p, packet->auth_data, packet->auth_data_len);
p+= packet->auth_data_len;
}
if (packet->db) {
@ -555,9 +558,18 @@ size_t php_mysqlnd_auth_write(void *_packet, MYSQLND * conn TSRMLS_DC)
}
/* no \0 for no DB */
if (packet->is_change_user_packet && packet->charset_no) {
int2store(p, packet->charset_no);
p+= 2;
if (packet->is_change_user_packet) {
if (packet->charset_no) {
int2store(p, packet->charset_no);
p+= 2;
}
} else {
if (packet->auth_plugin_name) {
size_t len = MIN(strlen(packet->auth_plugin_name), sizeof(buffer) - (p - buffer) - 1);
memcpy(p, packet->auth_plugin_name, len);
p+= len;
*p++= '\0';
}
}
}
if (packet->is_change_user_packet) {

View File

@ -70,9 +70,9 @@ typedef struct st_mysqlnd_packet_greet {
uint8_t protocol_version;
char *server_version;
uint32_t thread_id;
zend_uchar intern_scramble_buf[SCRAMBLE_LENGTH];
zend_uchar * scramble_buf;
size_t scramble_buf_len;
zend_uchar intern_auth_plugin_data[SCRAMBLE_LENGTH];
zend_uchar * auth_plugin_data;
size_t auth_plugin_data_len;
/* 1 byte pad */
uint32_t server_capabilities;
uint8_t charset_no;
@ -92,22 +92,18 @@ typedef struct st_mysqlnd_packet_auth {
MYSQLND_PACKET_HEADER header;
uint32_t client_flags;
uint32_t max_packet_size;
uint8_t charset_no;
/* 23 byte pad */
uint8_t charset_no;
const char *user;
/* 8 byte scramble */
zend_uchar *auth_data;
size_t auth_data_len;
const char *db;
/* 12 byte scramble */
char *auth_plugin_name;
/* Here the packet ends. This is user supplied data */
const char *password;
/* +1 for \0 because of scramble() */
unsigned char *server_scramble_buf;
size_t server_scramble_buf_len;
size_t db_len;
zend_bool send_auth_data;
zend_bool is_change_user_packet;
zend_bool silent;
size_t db_len;
zend_bool send_auth_data;
zend_bool is_change_user_packet;
zend_bool silent;
} MYSQLND_PACKET_AUTH;
/* OK packet */
@ -255,7 +251,7 @@ typedef struct st_mysqlnd_packet_chg_user_resp {
} MYSQLND_PACKET_CHG_USER_RESPONSE;
PHPAPI void php_mysqlnd_scramble(zend_uchar * const buffer, const zend_uchar * const scramble, const zend_uchar * const pass);
PHPAPI void php_mysqlnd_scramble(zend_uchar * const buffer, const zend_uchar * const scramble, const zend_uchar * const pass, size_t pass_len);
unsigned long php_mysqlnd_net_field_length(zend_uchar **packet);
zend_uchar * php_mysqlnd_net_store_length(zend_uchar *packet, uint64_t length);