Skip to content

Commit 813d4a0

Browse files
committed
Handle error response during caching_sha2_password auth
In particular, this fixes handling of expired passwords.
1 parent e7e1254 commit 813d4a0

File tree

3 files changed

+24
-6
lines changed

3 files changed

+24
-6
lines changed

ext/mysqlnd/mysqlnd_auth.c

+7
Original file line numberDiff line numberDiff line change
@@ -1073,6 +1073,13 @@ mysqlnd_caching_sha2_handle_server_response(struct st_mysqlnd_authentication_plu
10731073
}
10741074

10751075
switch (result_packet.response_code) {
1076+
case 0xFF:
1077+
if (result_packet.sqlstate[0]) {
1078+
strlcpy(conn->error_info->sqlstate, result_packet.sqlstate, sizeof(conn->error_info->sqlstate));
1079+
DBG_ERR_FMT("ERROR:%u [SQLSTATE:%s] %s", result_packet.error_no, result_packet.sqlstate, result_packet.error);
1080+
}
1081+
SET_CLIENT_ERROR(conn->error_info, result_packet.error_no, UNKNOWN_SQLSTATE, result_packet.error);
1082+
DBG_RETURN(FAIL);
10761083
case 0xFE:
10771084
DBG_INF("auth switch response");
10781085
*new_auth_protocol = result_packet.new_auth_protocol;

ext/mysqlnd/mysqlnd_wireprotocol.c

+12-6
Original file line numberDiff line numberDiff line change
@@ -2178,20 +2178,25 @@ 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;
21822181

21832182
DBG_ENTER("php_mysqlnd_cached_sha2_result_read");
21842183
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)) {
21852184
DBG_RETURN(FAIL);
21862185
}
21872186
BAIL_IF_NO_MORE_DATA;
21882187

2189-
main_response_code = uint1korr(p);
2188+
packet->response_code = uint1korr(p);
21902189
p++;
21912190
BAIL_IF_NO_MORE_DATA;
21922191

2193-
if (0xFE == main_response_code) {
2194-
packet->response_code = main_response_code;
2192+
if (ERROR_MARKER == packet->response_code) {
2193+
php_mysqlnd_read_error_from_line(p, packet->header.size - 1,
2194+
packet->error, sizeof(packet->error),
2195+
&packet->error_no, packet->sqlstate
2196+
);
2197+
DBG_RETURN(PASS);
2198+
}
2199+
if (0xFE == packet->response_code) {
21952200
/* Authentication Switch Response */
21962201
if (packet->header.size > (size_t) (p - buf)) {
21972202
packet->new_auth_protocol = mnd_pestrdup((char *)p, FALSE);
@@ -2209,10 +2214,11 @@ php_mysqlnd_cached_sha2_result_read(MYSQLND_CONN_DATA * conn, void * _packet)
22092214
DBG_RETURN(PASS);
22102215
}
22112216

2212-
if (0x1 != main_response_code) {
2213-
DBG_ERR_FMT("Unexpected response code %d", main_response_code);
2217+
if (0x1 != packet->response_code) {
2218+
DBG_ERR_FMT("Unexpected response code %d", packet->response_code);
22142219
}
22152220

2221+
/* This is not really the response code, but we reuse the field. */
22162222
packet->response_code = uint1korr(p);
22172223
p++;
22182224
BAIL_IF_NO_MORE_DATA;

ext/mysqlnd/mysqlnd_wireprotocol.h

+5
Original file line numberDiff line numberDiff line change
@@ -288,10 +288,15 @@ typedef struct st_mysqlnd_packet_cached_sha2_result {
288288
uint8_t request;
289289
zend_uchar * password;
290290
size_t password_len;
291+
/* Used for auth switch request */
291292
char *new_auth_protocol;
292293
size_t new_auth_protocol_len;
293294
zend_uchar *new_auth_protocol_data;
294295
size_t new_auth_protocol_data_len;
296+
/* Used for error result */
297+
char error[MYSQLND_ERRMSG_SIZE+1];
298+
char sqlstate[MYSQLND_SQLSTATE_LENGTH + 1];
299+
unsigned int error_no;
295300
} MYSQLND_PACKET_CACHED_SHA2_RESULT;
296301

297302

0 commit comments

Comments
 (0)