Skip to content

Commit 8890478

Browse files
committed
WL#15930 remove deprecated mysql_native_password authentication
- remove mysql_native_password entirely from server - convert mysql_native_password client plugin into an optional shared one - remove MTRs, which are no longer needed - adjust MTRs which are still needed, but they use mysql_native_password - in addition to main focus of the worklog there is a small cleanup included, which removes piece of code related to an old 5.6 db layout. Change-Id: Ic1728f7842b5c062aa8141720f463965752272f6
1 parent 05f844f commit 8890478

File tree

530 files changed

+2834
-10786
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

530 files changed

+2834
-10786
lines changed

client/mysqladmin.cc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,8 +1037,7 @@ static int execute_commands(MYSQL *mysql, int argc, char **argv) {
10371037
/*
10381038
In case the password_expired flag is set ('Y'), then there is no way
10391039
to determine the password format. So, assume that setting the
1040-
password using the server's default authentication format
1041-
(mysql_native_password) will work.
1040+
password using the server's default authentication format will work.
10421041
TODO: make sure this always uses SSL and then let the server
10431042
calculate the scramble.
10441043
*/

config.h.cmake

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,4 @@
361361
/* sasl_client_done support */
362362
#cmakedefine SASL_CLIENT_DONE_SUPPORTED @SASL_CLIENT_DONE_SUPPORTED@
363363

364-
/* mysql native password support */
365-
#cmakedefine WITHOUT_MYSQL_NATIVE_PASSWORD @WITHOUT_MYSQL_NATIVE_PASSWORD@
366-
367364
#endif

include/password.h

Lines changed: 0 additions & 53 deletions
This file was deleted.

libmysql/CMakeLists.txt

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -208,12 +208,6 @@ IF (WIN32 AND OPENSSL_APPLINK_C)
208208
)
209209
ENDIF()
210210

211-
IF ((NOT WITHOUT_MYSQL_NATIVE_PASSWORD)
212-
OR (WITHOUT_MYSQL_NATIVE_PASSWORD EQUAL 0))
213-
LIST(APPEND CLIENT_SOURCES
214-
../sql-common/mysql_native_authentication_client.cc)
215-
ENDIF()
216-
217211
#
218212
# Include protocol tracing infrastructure and the test
219213
# trace plugin if enabled by build options.
@@ -307,6 +301,9 @@ ADD_SUBDIRECTORY(authentication_oci_client)
307301
# Fido and Webauthn clients
308302
ADD_SUBDIRECTORY(fido_client)
309303

304+
# authentication mysql_native_password client plug-in
305+
ADD_SUBDIRECTORY(authentication_native_password)
306+
310307
# Merge several convenience libraries into one big mysqlclient
311308
MERGE_CONVENIENCE_LIBRARIES(mysqlclient ${LIBS_TO_MERGE}
312309
COMPONENT Development
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Copyright (c) 2024, Oracle and/or its affiliates.
2+
#
3+
# This program is free software; you can redistribute it and/or modify
4+
# it under the terms of the GNU General Public License, version 2.0,
5+
# as published by the Free Software Foundation.
6+
#
7+
# This program is also distributed with certain software (including
8+
# but not limited to OpenSSL) that is licensed under separate terms,
9+
# as designated in a particular file or component or in included license
10+
# documentation. The authors of MySQL hereby grant you an additional
11+
# permission to link the program and your derivative works with the
12+
# separately licensed software that they have included with MySQL.
13+
#
14+
# This program is distributed in the hope that it will be useful,
15+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
# GNU General Public License, version 2.0, for more details.
18+
#
19+
# You should have received a copy of the GNU General Public License
20+
# along with this program; if not, write to the Free Software
21+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22+
23+
# Skip it if disabled.
24+
IF(NOT WITH_AUTHENTICATION_CLIENT_PLUGINS)
25+
MESSAGE(STATUS "Skipping the NATIVE_PASSWORD client authentication plugin.")
26+
RETURN()
27+
ENDIF()
28+
29+
DISABLE_MISSING_PROFILE_WARNING()
30+
31+
MESSAGE(STATUS "building mysql_native_password client shared plugin")
32+
33+
MYSQL_ADD_PLUGIN(mysql_native_password
34+
mysql_native_password.cc
35+
LINK_LIBRARIES mysys
36+
MODULE_ONLY
37+
CLIENT_ONLY
38+
MODULE_OUTPUT_NAME "mysql_native_password"
39+
)
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
/* Copyright (c) 2024, Oracle and/or its affiliates.
2+
3+
This program is free software; you can redistribute it and/or modify
4+
it under the terms of the GNU General Public License, version 2.0,
5+
as published by the Free Software Foundation.
6+
7+
This program is also distributed with certain software (including
8+
but not limited to OpenSSL) that is licensed under separate terms,
9+
as designated in a particular file or component or in included license
10+
documentation. The authors of MySQL hereby grant you an additional
11+
permission to link the program and your derivative works with the
12+
separately licensed software that they have included with MySQL.
13+
14+
Without limiting anything contained in the foregoing, this file,
15+
which is part of C Driver for MySQL (Connector/C), is also subject to the
16+
Universal FOSS Exception, version 1.0, a copy of which can be found at
17+
http://oss.oracle.com/licenses/universal-foss-exception.
18+
19+
This program is distributed in the hope that it will be useful,
20+
but WITHOUT ANY WARRANTY; without even the implied warranty of
21+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22+
GNU General Public License, version 2.0, for more details.
23+
24+
You should have received a copy of the GNU General Public License
25+
along with this program; if not, write to the Free Software
26+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
27+
28+
/*
29+
This file is included by both libmysql (the MySQL client C API)
30+
and the mysqld server to connect to another MYSQL server.
31+
*/
32+
33+
#include "my_dbug.h"
34+
#include "my_sys.h"
35+
#include "sha1.h"
36+
#include "sql_common.h"
37+
38+
#define MYSQL_NATIVE_PASSWORD_PLUGIN_NAME "mysql_native_password"
39+
40+
/*****************************************************************************
41+
The main idea is that no password are sent between client & server on
42+
connection and that no password are saved in mysql in a decodable form.
43+
44+
On connection a random string is generated and sent to the client.
45+
The client takes the random string from server and password provided
46+
by the user as an input and generates a new 'check' string.
47+
This 'check' string is sent to the server where it is compared with
48+
a string generated from the stored hash_value of the password and the
49+
random string.
50+
51+
The password is saved (in user.authentication_string).
52+
53+
Example:
54+
SET PASSWORD for test = 'haha'
55+
This saves a hashed number as a string in the authentication_string field.
56+
57+
The new authentication is performed in following manner:
58+
59+
SERVER: public_seed=generate_user_salt()
60+
send(public_seed)
61+
62+
CLIENT: recv(public_seed)
63+
hash_stage1=sha1("password")
64+
hash_stage2=sha1(hash_stage1)
65+
reply=xor(hash_stage1, sha1(public_seed,hash_stage2)
66+
67+
// this three steps are done in scramble()
68+
69+
send(reply)
70+
71+
72+
SERVER: recv(reply)
73+
hash_stage1=xor(reply, sha1(public_seed,hash_stage2))
74+
candidate_hash2=sha1(hash_stage1)
75+
check(candidate_hash2==hash_stage2)
76+
77+
// this three steps are done in check_scramble()
78+
79+
*****************************************************************************/
80+
81+
/*
82+
Encrypt/Decrypt function used for password encryption in authentication.
83+
Simple XOR is used here, but it is OK as we crypt random strings. Note
84+
that XOR(s1, XOR(s1, s2)) == s2, XOR(s1, s2) == XOR(s2, s1)
85+
SYNOPSIS
86+
my_crypt()
87+
to OUT buffer to hold encrypted string; must be at least len bytes
88+
long; to and s1 (or s2) may be the same.
89+
s1, s2 IN input strings (of equal length)
90+
len IN length of s1 and s2
91+
*/
92+
93+
static void my_crypt(char *to, const uchar *s1, const uchar *s2, uint len) {
94+
const uint8 *s1_end = s1 + len;
95+
while (s1 < s1_end) *to++ = *s1++ ^ *s2++;
96+
}
97+
98+
/**
99+
Compute two stage SHA1 hash of the password :
100+
101+
hash_stage1=sha1("password")
102+
hash_stage2=sha1(hash_stage1)
103+
104+
@param [in] password Password string.
105+
@param [in] pass_len Length of the password.
106+
@param [out] hash_stage1 sha1(password)
107+
@param [out] hash_stage2 sha1(hash_stage1)
108+
*/
109+
110+
inline void compute_two_stage_sha1_hash(const char *password, size_t pass_len,
111+
uint8 *hash_stage1,
112+
uint8 *hash_stage2) {
113+
/* Stage 1: hash password */
114+
compute_sha1_hash(hash_stage1, password, pass_len);
115+
116+
/* Stage 2 : hash first stage's output. */
117+
compute_sha1_hash(hash_stage2, (const char *)hash_stage1, SHA1_HASH_SIZE);
118+
}
119+
120+
/**
121+
Produce an obscure octet sequence from password and random
122+
string, received from the server. This sequence corresponds to the
123+
password, but password can not be easily restored from it. The sequence
124+
is then sent to the server for validation. Trailing zero is not stored
125+
in the buf as it is not needed.
126+
This function is used by client to create authenticated reply to the
127+
server's greeting.
128+
129+
@param[out] to store scrambled string here. The buf must be at least
130+
SHA1_HASH_SIZE bytes long.
131+
@param message random message, must be exactly SCRAMBLE_LENGTH long and
132+
NULL-terminated.
133+
@param password users' password, NULL-terminated
134+
*/
135+
136+
void scramble(char *to, const char *message, const char *password) {
137+
uint8 hash_stage1[SHA1_HASH_SIZE];
138+
uint8 hash_stage2[SHA1_HASH_SIZE];
139+
140+
/* Two stage SHA1 hash of the password. */
141+
compute_two_stage_sha1_hash(password, strlen(password), hash_stage1,
142+
hash_stage2);
143+
144+
/* create crypt string as sha1(message, hash_stage2) */;
145+
compute_sha1_hash_multi((uint8 *)to, message, SCRAMBLE_LENGTH,
146+
(const char *)hash_stage2, SHA1_HASH_SIZE);
147+
my_crypt(to, (const uchar *)to, hash_stage1, SCRAMBLE_LENGTH);
148+
}
149+
150+
/**
151+
Client authentication plugin that does native MySQL authentication
152+
using a 20-byte (4.1+) scramble
153+
154+
@param vio the channel to operate on
155+
@param mysql the MYSQL structure to operate on
156+
157+
@retval -1 ::CR_OK : Success
158+
@retval 1 ::CR_ERROR : error reading
159+
@retval 2012 ::CR_SERVER_HANDSHAKE_ERR : malformed handshake data
160+
*/
161+
static int native_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql) {
162+
int pkt_len;
163+
uchar *pkt;
164+
165+
DBUG_TRACE;
166+
167+
/* read the scramble */
168+
if ((pkt_len = vio->read_packet(vio, &pkt)) < 0) return CR_ERROR;
169+
170+
if (pkt_len != SCRAMBLE_LENGTH + 1) return CR_SERVER_HANDSHAKE_ERR;
171+
172+
/* save it in MYSQL */
173+
memcpy(mysql->scramble, pkt, SCRAMBLE_LENGTH);
174+
mysql->scramble[SCRAMBLE_LENGTH] = 0;
175+
176+
if (mysql->passwd[0]) {
177+
char scrambled[SCRAMBLE_LENGTH + 1];
178+
DBUG_PRINT("info", ("sending scramble"));
179+
scramble(scrambled, (char *)pkt, mysql->passwd);
180+
if (vio->write_packet(vio, (uchar *)scrambled, SCRAMBLE_LENGTH))
181+
return CR_ERROR;
182+
} else {
183+
DBUG_PRINT("info", ("no password"));
184+
if (vio->write_packet(vio, nullptr, 0)) /* no password */
185+
return CR_ERROR;
186+
}
187+
188+
return CR_OK;
189+
}
190+
191+
mysql_declare_client_plugin(AUTHENTICATION) MYSQL_NATIVE_PASSWORD_PLUGIN_NAME
192+
, /* name */
193+
MYSQL_CLIENT_PLUGIN_AUTHOR_ORACLE, /* author */
194+
"MySQL Native Authentication Client", /* description */
195+
{0, 1, 0}, /* version */
196+
"GPL", /* license */
197+
nullptr, /* mysql_api */
198+
nullptr, /* init */
199+
nullptr, /* deinit */
200+
nullptr, /* options */
201+
nullptr, /* get_options */
202+
native_password_auth_client, /* authenticate_user */
203+
nullptr, /* authenticate_user_nonblocking */
204+
mysql_end_client_plugin;

mysql-test/collections/disabled.def

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ main.dd_upgrade_error_ci : Bug#36312666 Several InnoDB testca
104104
main.dd_upgrade_ci : Bug#36312666 Several InnoDB testcases fail after the change to 9.0
105105
main.dd_upgrade_error_debug : Bug#36312666 Several InnoDB testcases fail after the change to 9.0
106106
main.dd_schema_definition_after_upgrade_80_debug : Bug#36312666 Several InnoDB testcases fail after the change to 9.0
107-
main.mysql_upgrade_grant : Bug#36312666 Several InnoDB testcases fail after the change to 9.0
108107
main.mysql_inplace_upgrade : Bug#36312666 Several InnoDB testcases fail after the change to 9.0
109108
main.mysql_80_inplace_upgrade : Bug#36312666 Several InnoDB testcases fail after the change to 9.0
110109
main.upgrade_with_float_auto_increment : Bug#36312666 Several InnoDB testcases fail after the change to 9.0

mysql-test/common/binlog/ddl.inc

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,11 @@
3030

3131
--let $binlog_file=
3232

33-
--let $ddl_query=CREATE USER user1 IDENTIFIED WITH 'mysql_native_password'
33+
#--let $ddl_query=CREATE USER user1 IDENTIFIED WITH 'caching_sha2_password'
34+
#--let $ddl_query=CREATE USER user1 IDENTIFIED WITH 'sha256_password'
35+
#--let $ddl_query=CREATE USER user1;
36+
#--let $ddl_query=CREATE USER user1 IDENTIFIED WITH 'cleartext_plugin_server'
37+
--let $ddl_query=CREATE USER user1 IDENTIFIED WITH 'caching_sha2_password'
3438
--let $pre_binlog_crash_check=SELECT count(*) = 0 FROM mysql.user WHERE user = 'user1'
3539
--let $post_binlog_crash_check=SELECT count(*) = 1 FROM mysql.user WHERE user = 'user1'
3640
--source common/binlog/crash_safe_ddl.inc
@@ -48,17 +52,29 @@
4852
--source common/binlog/crash_safe_ddl.inc
4953

5054
--let $id_string='123456'
51-
--let $old_auth_str=`SELECT authentication_string FROM mysql.user WHERE user LIKE 'user1'`
55+
--let $old_auth_str=`SELECT HEX(authentication_string) FROM mysql.user WHERE user LIKE 'user1'`
5256
--let $ddl_query=ALTER USER user1 IDENTIFIED BY $id_string
53-
--let $pre_binlog_crash_check=SELECT authentication_string = '$old_auth_str' FROM mysql.user WHERE user LIKE 'user1'
54-
--let $post_binlog_crash_check=SELECT authentication_string != '$old_auth_str' FROM mysql.user WHERE user LIKE 'user1'
57+
# [KH] replace test
58+
#--replace_regex /AS '(.*)' REQUIRE/AS '<non-deterministic-password-hash>' REQUIRE/
59+
--replace_regex / = '(.*)' FROM/ = '<non-deterministic-password-hash>' FROM/
60+
--let $pre_binlog_crash_check=SELECT HEX(authentication_string) = '$old_auth_str' FROM mysql.user WHERE user LIKE 'user1'
61+
# [KH] replace test
62+
#--replace_regex /AS '(.*)' REQUIRE/AS '<non-deterministic-password-hash>' REQUIRE/
63+
--replace_regex / = '(.*)' FROM/ = '<non-deterministic-password-hash>' FROM/
64+
--let $post_binlog_crash_check=SELECT HEX(authentication_string) != '$old_auth_str' FROM mysql.user WHERE user LIKE 'user1'
5565
--source common/binlog/crash_safe_ddl.inc
5666

5767
--let $id_string='abcdef'
58-
--let $old_auth_str=`SELECT authentication_string FROM mysql.user WHERE user LIKE 'user1'`
68+
--let $old_auth_str=`SELECT HEX(authentication_string) FROM mysql.user WHERE user LIKE 'user1'`
5969
--let $ddl_query=SET PASSWORD FOR user1=$id_string
60-
--let $pre_binlog_crash_check=SELECT authentication_string = '$old_auth_str' FROM mysql.user WHERE user LIKE 'user1'
61-
--let $post_binlog_crash_check=SELECT authentication_string != '$old_auth_str' FROM mysql.user WHERE user LIKE 'user1'
70+
# [KH] replace test
71+
#--replace_regex /AS '(.*)' REQUIRE/AS '<non-deterministic-password-hash>' REQUIRE/
72+
--replace_regex / = '(.*)' FROM/ = '<non-deterministic-password-hash>' FROM/
73+
--let $pre_binlog_crash_check=SELECT HEX(authentication_string) = '$old_auth_str' FROM mysql.user WHERE user LIKE 'user1'
74+
# [KH] replace test
75+
#--replace_regex /AS '(.*)' REQUIRE/AS '<non-deterministic-password-hash>' REQUIRE/
76+
--replace_regex / = '(.*)' FROM/ = '<non-deterministic-password-hash>' FROM/
77+
--let $post_binlog_crash_check=SELECT HEX(authentication_string) != '$old_auth_str' FROM mysql.user WHERE user LIKE 'user1'
6278
--source common/binlog/crash_safe_ddl.inc
6379

6480
--let $ddl_query=RENAME USER user1 TO user2

0 commit comments

Comments
 (0)