From bb5cdd9b7469b37ceef0627100a415ead68f0030 Mon Sep 17 00:00:00 2001
From: Nikita Popov <nikita.ppv@gmail.com>
Date: Fri, 24 Jan 2020 14:52:28 +0100
Subject: [PATCH] Fixed bug #79011

auth_plugin_data_len here is 21, including the trailing null byte.
Directly use SCRAMBLE_LENGTH instead. Also add a sanity check that
the provided scramble is long enough.
---
 NEWS                       | 2 ++
 ext/mysqlnd/mysqlnd_auth.c | 8 +++++++-
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/NEWS b/NEWS
index a0e02b9290..de126e54c3 100644
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,8 @@ PHP                                                                        NEWS
 - MySQLnd:
   . Fixed bug #79084 (mysqlnd may fetch wrong column indexes with MYSQLI_BOTH).
     (cmb)
+  . Fixed bug #79011 (MySQL caching_sha2_password Access denied for password
+    with more than 20 chars). (Nikita)
 
 - Opcache:
   . Fixed #79114 (Eval class during preload causes class to be only half
diff --git a/ext/mysqlnd/mysqlnd_auth.c b/ext/mysqlnd/mysqlnd_auth.c
index 55bdb1d3fe..24c77220fc 100644
--- a/ext/mysqlnd/mysqlnd_auth.c
+++ b/ext/mysqlnd/mysqlnd_auth.c
@@ -915,6 +915,12 @@ mysqlnd_caching_sha2_get_auth_data(struct st_mysqlnd_authentication_plugin * sel
 	DBG_INF_FMT("salt(%d)=[%.*s]", auth_plugin_data_len, auth_plugin_data_len, auth_plugin_data);
 	*auth_data_len = 0;
 
+	if (auth_plugin_data_len < SCRAMBLE_LENGTH) {
+		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);
+	}
+
 	DBG_INF("First auth step: send hashed password");
 	/* copy scrambled pass*/
 	if (passwd && passwd_len) {
@@ -1022,7 +1028,7 @@ mysqlnd_caching_sha2_get_and_use_key(MYSQLND_CONN_DATA *conn,
 		char xor_str[passwd_len + 1];
 		memcpy(xor_str, passwd, passwd_len);
 		xor_str[passwd_len] = '\0';
-		mysqlnd_xor_string(xor_str, passwd_len, (char *) auth_plugin_data, auth_plugin_data_len);
+		mysqlnd_xor_string(xor_str, passwd_len, (char *) auth_plugin_data, SCRAMBLE_LENGTH);
 
 		server_public_key_len = RSA_size(server_public_key);
 		/*
-- 
2.40.0