Skip to content

Commit 6225137

Browse files
committed
Support auth switch request during caching sha2 auth
1 parent b0efd18 commit 6225137

File tree

4 files changed

+60
-12
lines changed

4 files changed

+60
-12
lines changed

ext/mysqlnd/mysqlnd_auth.c

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -320,8 +320,12 @@ mysqlnd_auth_handshake(MYSQLND_CONN_DATA * conn,
320320
}
321321

322322
if (auth_plugin && auth_plugin->methods.handle_server_response) {
323-
auth_plugin->methods.handle_server_response(auth_plugin, conn,
324-
orig_auth_plugin_data, orig_auth_plugin_data_len, passwd, passwd_len);
323+
if (FAIL == auth_plugin->methods.handle_server_response(auth_plugin, conn,
324+
orig_auth_plugin_data, orig_auth_plugin_data_len, passwd, passwd_len,
325+
switch_to_auth_protocol, switch_to_auth_protocol_len,
326+
switch_to_auth_protocol_data, switch_to_auth_protocol_data_len)) {
327+
goto end;
328+
}
325329
}
326330

327331
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,
10281032
}
10291033
/* }}} */
10301034

1031-
/* {{{ mysqlnd_native_auth_get_auth_data */
1032-
static void
1035+
/* {{{ mysqlnd_caching_sha2_handle_server_response */
1036+
static enum_func_status
10331037
mysqlnd_caching_sha2_handle_server_response(struct st_mysqlnd_authentication_plugin *self,
10341038
MYSQLND_CONN_DATA * conn,
10351039
const zend_uchar * auth_plugin_data, const size_t auth_plugin_data_len,
10361040
const char * const passwd,
1037-
const size_t passwd_len)
1041+
const size_t passwd_len,
1042+
char **new_auth_protocol, size_t *new_auth_protocol_len,
1043+
zend_uchar **new_auth_protocol_data, size_t *new_auth_protocol_data_len
1044+
)
10381045
{
10391046
DBG_ENTER("mysqlnd_caching_sha2_handle_server_response");
10401047
MYSQLND_PACKET_CACHED_SHA2_RESULT result_packet;
10411048
conn->payload_decoder_factory->m.init_cached_sha2_result_packet(&result_packet);
10421049

10431050
if (FAIL == PACKET_READ(conn, &result_packet)) {
1044-
DBG_VOID_RETURN;
1051+
DBG_RETURN(PASS);
10451052
}
10461053

10471054
switch (result_packet.response_code) {
1055+
case 0xFE:
1056+
DBG_INF("auth switch response");
1057+
*new_auth_protocol = result_packet.new_auth_protocol;
1058+
*new_auth_protocol_len = result_packet.new_auth_protocol_len;
1059+
*new_auth_protocol_data = result_packet.new_auth_protocol_data;
1060+
*new_auth_protocol_data_len = result_packet.new_auth_protocol_data_len;
1061+
DBG_RETURN(FAIL);
10481062
case 3:
10491063
DBG_INF("fast path succeeded");
1050-
DBG_VOID_RETURN;
1064+
DBG_RETURN(PASS);
10511065
case 4:
10521066
if (conn->vio->data->ssl || conn->unix_socket.s) {
10531067
DBG_INF("fast path failed, doing full auth via SSL");
@@ -1060,15 +1074,15 @@ mysqlnd_caching_sha2_handle_server_response(struct st_mysqlnd_authentication_plu
10601074
PACKET_WRITE(conn, &result_packet);
10611075
efree(result_packet.password);
10621076
}
1063-
DBG_VOID_RETURN;
1077+
DBG_RETURN(PASS);
10641078
case 2:
10651079
// The server tried to send a key, which we didn't expect
10661080
// fall-through
10671081
default:
10681082
php_error_docref(NULL, E_WARNING, "Unexpected server response while doing caching_sha2 auth: %i", result_packet.response_code);
10691083
}
10701084

1071-
DBG_VOID_RETURN;
1085+
DBG_RETURN(PASS);
10721086
}
10731087
/* }}} */
10741088

ext/mysqlnd/mysqlnd_structs.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1383,11 +1383,14 @@ typedef zend_uchar * (*func_auth_plugin__get_auth_data)(struct st_mysqlnd_authen
13831383
const MYSQLND_PFC_DATA * const pfc_data, const zend_ulong mysql_flags
13841384
);
13851385

1386-
typedef void (*func_auth_plugin__handle_server_response)(struct st_mysqlnd_authentication_plugin * self,
1386+
typedef enum_func_status (*func_auth_plugin__handle_server_response)(struct st_mysqlnd_authentication_plugin * self,
13871387
MYSQLND_CONN_DATA * conn,
13881388
const zend_uchar * auth_plugin_data, size_t auth_plugin_data_len,
13891389
const char * const passwd,
1390-
const size_t passwd_len);
1390+
const size_t passwd_len,
1391+
char **new_auth_protocol, size_t *new_auth_protocol_len,
1392+
zend_uchar **new_auth_protocol_data, size_t *new_auth_protocol_data_len
1393+
);
13911394

13921395
struct st_mysqlnd_authentication_plugin
13931396
{

ext/mysqlnd/mysqlnd_wireprotocol.c

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2178,18 +2178,45 @@ php_mysqlnd_cached_sha2_result_read(MYSQLND_CONN_DATA * conn, void * _packet)
21782178
zend_uchar buf[SHA256_PK_REQUEST_RESP_BUFFER_SIZE];
21792179
zend_uchar *p = buf;
21802180
const zend_uchar * const begin = buf;
2181+
uint8_t main_response_code;
21812182

21822183
DBG_ENTER("php_mysqlnd_cached_sha2_result_read");
21832184
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)) {
21842185
DBG_RETURN(FAIL);
21852186
}
21862187
BAIL_IF_NO_MORE_DATA;
21872188

2189+
main_response_code = uint1korr(p);
21882190
p++;
2189-
packet->response_code = uint1korr(p);
21902191
BAIL_IF_NO_MORE_DATA;
21912192

2193+
if (0xFE == main_response_code) {
2194+
packet->response_code = main_response_code;
2195+
/* Authentication Switch Response */
2196+
if (packet->header.size > (size_t) (p - buf)) {
2197+
packet->new_auth_protocol = mnd_pestrdup((char *)p, FALSE);
2198+
packet->new_auth_protocol_len = strlen(packet->new_auth_protocol);
2199+
p+= packet->new_auth_protocol_len + 1; /* +1 for the \0 */
2200+
2201+
packet->new_auth_protocol_data_len = packet->header.size - (size_t) (p - buf);
2202+
if (packet->new_auth_protocol_data_len) {
2203+
packet->new_auth_protocol_data = mnd_emalloc(packet->new_auth_protocol_data_len);
2204+
memcpy(packet->new_auth_protocol_data, p, packet->new_auth_protocol_data_len);
2205+
}
2206+
DBG_INF_FMT("The server requested switching auth plugin to : %s", packet->new_auth_protocol);
2207+
DBG_INF_FMT("Server salt : [%d][%.*s]", packet->new_auth_protocol_data_len, packet->new_auth_protocol_data_len, packet->new_auth_protocol_data);
2208+
}
2209+
DBG_RETURN(PASS);
2210+
}
2211+
2212+
if (0x1 != main_response_code) {
2213+
DBG_ERR_FMT("Unexpected response code %d", main_response_code);
2214+
}
2215+
2216+
packet->response_code = uint1korr(p);
21922217
p++;
2218+
BAIL_IF_NO_MORE_DATA;
2219+
21932220
packet->result = uint1korr(p);
21942221
BAIL_IF_NO_MORE_DATA;
21952222

ext/mysqlnd/mysqlnd_wireprotocol.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,10 @@ typedef struct st_mysqlnd_packet_cached_sha2_result {
288288
uint8_t request;
289289
zend_uchar * password;
290290
size_t password_len;
291+
char *new_auth_protocol;
292+
size_t new_auth_protocol_len;
293+
zend_uchar *new_auth_protocol_data;
294+
size_t new_auth_protocol_data_len;
291295
} MYSQLND_PACKET_CACHED_SHA2_RESULT;
292296

293297

0 commit comments

Comments
 (0)