diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2019-12-27 12:37:51 +0100 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2019-12-27 17:27:04 +0100 |
commit | 6225137b4a51da4550f01aafbe8bc39655aedc23 (patch) | |
tree | 29b6f9dc269eeab0437c39a8c0e3949649620be3 | |
parent | b0efd18f7844da29931737b8a1cf461c7493e168 (diff) | |
download | php-git-6225137b4a51da4550f01aafbe8bc39655aedc23.tar.gz |
Support auth switch request during caching sha2 auth
-rw-r--r-- | ext/mysqlnd/mysqlnd_auth.c | 32 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_structs.h | 7 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_wireprotocol.c | 29 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_wireprotocol.h | 4 |
4 files changed, 60 insertions, 12 deletions
diff --git a/ext/mysqlnd/mysqlnd_auth.c b/ext/mysqlnd/mysqlnd_auth.c index b916e40b71..3ceaaa457e 100644 --- a/ext/mysqlnd/mysqlnd_auth.c +++ b/ext/mysqlnd/mysqlnd_auth.c @@ -320,8 +320,12 @@ mysqlnd_auth_handshake(MYSQLND_CONN_DATA * conn, } if (auth_plugin && auth_plugin->methods.handle_server_response) { - auth_plugin->methods.handle_server_response(auth_plugin, conn, - orig_auth_plugin_data, orig_auth_plugin_data_len, passwd, passwd_len); + if (FAIL == auth_plugin->methods.handle_server_response(auth_plugin, conn, + orig_auth_plugin_data, orig_auth_plugin_data_len, passwd, passwd_len, + switch_to_auth_protocol, switch_to_auth_protocol_len, + switch_to_auth_protocol_data, switch_to_auth_protocol_data_len)) { + goto end; + } } if (FAIL == PACKET_READ(conn, &auth_resp_packet) || auth_resp_packet.response_code >= 0xFE) { @@ -1028,26 +1032,36 @@ mysqlnd_caching_sha2_get_and_use_key(MYSQLND_CONN_DATA *conn, } /* }}} */ -/* {{{ mysqlnd_native_auth_get_auth_data */ -static void +/* {{{ mysqlnd_caching_sha2_handle_server_response */ +static enum_func_status mysqlnd_caching_sha2_handle_server_response(struct st_mysqlnd_authentication_plugin *self, MYSQLND_CONN_DATA * conn, const zend_uchar * auth_plugin_data, const size_t auth_plugin_data_len, const char * const passwd, - const size_t passwd_len) + const size_t passwd_len, + char **new_auth_protocol, size_t *new_auth_protocol_len, + zend_uchar **new_auth_protocol_data, size_t *new_auth_protocol_data_len + ) { DBG_ENTER("mysqlnd_caching_sha2_handle_server_response"); MYSQLND_PACKET_CACHED_SHA2_RESULT result_packet; conn->payload_decoder_factory->m.init_cached_sha2_result_packet(&result_packet); if (FAIL == PACKET_READ(conn, &result_packet)) { - DBG_VOID_RETURN; + DBG_RETURN(PASS); } switch (result_packet.response_code) { + case 0xFE: + DBG_INF("auth switch response"); + *new_auth_protocol = result_packet.new_auth_protocol; + *new_auth_protocol_len = result_packet.new_auth_protocol_len; + *new_auth_protocol_data = result_packet.new_auth_protocol_data; + *new_auth_protocol_data_len = result_packet.new_auth_protocol_data_len; + DBG_RETURN(FAIL); case 3: DBG_INF("fast path succeeded"); - DBG_VOID_RETURN; + DBG_RETURN(PASS); case 4: if (conn->vio->data->ssl || conn->unix_socket.s) { DBG_INF("fast path failed, doing full auth via SSL"); @@ -1060,7 +1074,7 @@ mysqlnd_caching_sha2_handle_server_response(struct st_mysqlnd_authentication_plu PACKET_WRITE(conn, &result_packet); efree(result_packet.password); } - DBG_VOID_RETURN; + DBG_RETURN(PASS); case 2: // The server tried to send a key, which we didn't expect // fall-through @@ -1068,7 +1082,7 @@ mysqlnd_caching_sha2_handle_server_response(struct st_mysqlnd_authentication_plu php_error_docref(NULL, E_WARNING, "Unexpected server response while doing caching_sha2 auth: %i", result_packet.response_code); } - DBG_VOID_RETURN; + DBG_RETURN(PASS); } /* }}} */ diff --git a/ext/mysqlnd/mysqlnd_structs.h b/ext/mysqlnd/mysqlnd_structs.h index 9880d1643d..fcd3bc2f39 100644 --- a/ext/mysqlnd/mysqlnd_structs.h +++ b/ext/mysqlnd/mysqlnd_structs.h @@ -1383,11 +1383,14 @@ typedef zend_uchar * (*func_auth_plugin__get_auth_data)(struct st_mysqlnd_authen const MYSQLND_PFC_DATA * const pfc_data, const zend_ulong mysql_flags ); -typedef void (*func_auth_plugin__handle_server_response)(struct st_mysqlnd_authentication_plugin * self, +typedef enum_func_status (*func_auth_plugin__handle_server_response)(struct st_mysqlnd_authentication_plugin * self, MYSQLND_CONN_DATA * conn, const zend_uchar * auth_plugin_data, size_t auth_plugin_data_len, const char * const passwd, - const size_t passwd_len); + const size_t passwd_len, + char **new_auth_protocol, size_t *new_auth_protocol_len, + zend_uchar **new_auth_protocol_data, size_t *new_auth_protocol_data_len + ); struct st_mysqlnd_authentication_plugin { diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c index d0f1312f55..928e4f4201 100644 --- a/ext/mysqlnd/mysqlnd_wireprotocol.c +++ b/ext/mysqlnd/mysqlnd_wireprotocol.c @@ -2178,6 +2178,7 @@ php_mysqlnd_cached_sha2_result_read(MYSQLND_CONN_DATA * conn, void * _packet) zend_uchar buf[SHA256_PK_REQUEST_RESP_BUFFER_SIZE]; zend_uchar *p = buf; const zend_uchar * const begin = buf; + uint8_t main_response_code; DBG_ENTER("php_mysqlnd_cached_sha2_result_read"); if (FAIL == mysqlnd_read_packet_header_and_body(&(packet->header), pfc, vio, stats, error_info, connection_state, buf, sizeof(buf), "PROT_CACHED_SHA2_RESULT_PACKET", PROT_CACHED_SHA2_RESULT_PACKET)) { @@ -2185,11 +2186,37 @@ php_mysqlnd_cached_sha2_result_read(MYSQLND_CONN_DATA * conn, void * _packet) } BAIL_IF_NO_MORE_DATA; + main_response_code = uint1korr(p); p++; - packet->response_code = uint1korr(p); BAIL_IF_NO_MORE_DATA; + if (0xFE == main_response_code) { + packet->response_code = main_response_code; + /* Authentication Switch Response */ + if (packet->header.size > (size_t) (p - buf)) { + packet->new_auth_protocol = mnd_pestrdup((char *)p, FALSE); + packet->new_auth_protocol_len = strlen(packet->new_auth_protocol); + p+= packet->new_auth_protocol_len + 1; /* +1 for the \0 */ + + packet->new_auth_protocol_data_len = packet->header.size - (size_t) (p - buf); + if (packet->new_auth_protocol_data_len) { + packet->new_auth_protocol_data = mnd_emalloc(packet->new_auth_protocol_data_len); + memcpy(packet->new_auth_protocol_data, p, packet->new_auth_protocol_data_len); + } + DBG_INF_FMT("The server requested switching auth plugin to : %s", packet->new_auth_protocol); + DBG_INF_FMT("Server salt : [%d][%.*s]", packet->new_auth_protocol_data_len, packet->new_auth_protocol_data_len, packet->new_auth_protocol_data); + } + DBG_RETURN(PASS); + } + + if (0x1 != main_response_code) { + DBG_ERR_FMT("Unexpected response code %d", main_response_code); + } + + packet->response_code = uint1korr(p); p++; + BAIL_IF_NO_MORE_DATA; + packet->result = uint1korr(p); BAIL_IF_NO_MORE_DATA; diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.h b/ext/mysqlnd/mysqlnd_wireprotocol.h index 4b63e76a35..83ea5557dd 100644 --- a/ext/mysqlnd/mysqlnd_wireprotocol.h +++ b/ext/mysqlnd/mysqlnd_wireprotocol.h @@ -288,6 +288,10 @@ typedef struct st_mysqlnd_packet_cached_sha2_result { uint8_t request; zend_uchar * password; size_t password_len; + char *new_auth_protocol; + size_t new_auth_protocol_len; + zend_uchar *new_auth_protocol_data; + size_t new_auth_protocol_data_len; } MYSQLND_PACKET_CACHED_SHA2_RESULT; |