Fix to MXS-288: https://mariadb.atlassian.net/browse/MXS-288 Added MySQL 5.7 authentication

The change to the mysql.user table in MySQL 5.7 caused MaxScale to stop
working with it. This commit adds functionality that checks which version of
the user data query should be made. It also moves common code related to
server version strings to server.c
This commit is contained in:
Markus Makela 2015-11-12 11:57:29 +02:00
parent bdfd72404b
commit 5efd564573
7 changed files with 120 additions and 39 deletions

View File

@ -90,12 +90,28 @@
ON user.user=db.user AND user.host=db.host \
WHERE user.user IS NOT NULL" MYSQL_USERS_WITH_DB_ORDER
#define LOAD_MYSQL57_USERS_WITH_DB_QUERY "SELECT \
user.user AS user, \
user.host AS host, \
user.authentication_string AS password, \
concat(user.user,user.host,user.authentication_string,user.Select_priv,IFNULL(db,'')) AS userdata, \
user.Select_priv AS anydb, \
db.db AS db \
FROM mysql.user LEFT JOIN mysql.db \
ON user.user=db.user AND user.host=db.host \
WHERE user.user IS NOT NULL" MYSQL_USERS_WITH_DB_ORDER
#define MYSQL_USERS_WITH_DB_COUNT "SELECT COUNT(1) AS nusers_db FROM (" LOAD_MYSQL_USERS_WITH_DB_QUERY ") AS tbl_count"
#define MYSQL57_USERS_WITH_DB_COUNT "SELECT COUNT(1) AS nusers_db FROM (" LOAD_MYSQL57_USERS_WITH_DB_QUERY ") AS tbl_count"
#define LOAD_MYSQL_USERS_WITH_DB_QUERY_NO_ROOT "SELECT * \
FROM (" LOAD_MYSQL_USERS_WITH_DB_QUERY ") AS t1 \
WHERE user NOT IN ('root')" MYSQL_USERS_WITH_DB_ORDER
#define LOAD_MYSQL57_USERS_WITH_DB_QUERY_NO_ROOT "SELECT * \
FROM (" LOAD_MYSQL57_USERS_WITH_DB_QUERY ") AS t1 \
WHERE user NOT IN ('root')" MYSQL_USERS_WITH_DB_ORDER
#define LOAD_MYSQL_DATABASE_NAMES "SELECT * \
FROM ( (SELECT COUNT(1) AS ndbs \
FROM INFORMATION_SCHEMA.SCHEMATA) AS tbl1, \
@ -133,6 +149,39 @@ int add_wildcard_users(USERS *users,
static int gw_mysql_set_timeouts(MYSQL* handle);
/**
* Get the user data query.
* @param server_version Server version string
* @param include_root Include root user
* @return Users query
*/
const char* get_mysql_users_query(char* server_version, bool include_root)
{
const char* rval;
if (strstr(server_version, "5.7."))
{
rval = include_root ? LOAD_MYSQL57_USERS_WITH_DB_QUERY :
LOAD_MYSQL57_USERS_WITH_DB_QUERY_NO_ROOT;
}
else
{
rval = include_root ? LOAD_MYSQL_USERS_WITH_DB_QUERY :
LOAD_MYSQL_USERS_WITH_DB_QUERY_NO_ROOT;
}
return rval;
}
/**
* Get the user count query.
* @param server_version Server version string
* @return User vount query
* */
const char* get_mysq_users_db_count_query(char* server_version)
{
return strstr(server_version, "5.7.") ?
MYSQL57_USERS_WITH_DB_COUNT : MYSQL_USERS_WITH_DB_COUNT;
}
/**
* Check if the IP address of the user matches the one in the grant. This assumes
* that the grant has one or more single-character wildcards in it.
@ -651,7 +700,8 @@ getAllUsers(SERVICE *service, USERS *users)
char *dpwd = NULL;
int total_users = 0;
SERVER_REF *server;
char *users_query, *tmp;
const char *users_query;
char *tmp;
unsigned char hash[SHA_DIGEST_LENGTH]="";
char *users_data = NULL;
char *final_data = NULL;
@ -825,9 +875,19 @@ getAllUsers(SERVICE *service, USERS *users)
mysql_close(con);
goto cleanup;
}
if (server->server->server_string == NULL)
{
const char *server_string = mysql_get_server_info(con);
if (!server_set_version_string(server->server, server_string))
{
mysql_close(con);
goto cleanup;
}
}
/** Count users. Start with users and db grants for users */
if (mysql_query(con, MYSQL_USERS_WITH_DB_COUNT)) {
const char *user_with_db_count = get_mysq_users_db_count_query(server->server->server_string);
if (mysql_query(con, user_with_db_count)) {
if (mysql_errno(con) != ER_TABLEACCESS_DENIED_ERROR) {
/* This is an error we cannot handle, return */
LOGIF(LE, (skygw_log_write_flush(
@ -883,13 +943,10 @@ getAllUsers(SERVICE *service, USERS *users)
mysql_close(con);
goto cleanup;
}
if(service->enable_root) {
/* enable_root for MySQL protocol module means load the root user credentials from backend databases */
users_query = LOAD_MYSQL_USERS_WITH_DB_QUERY;
} else {
users_query = LOAD_MYSQL_USERS_WITH_DB_QUERY_NO_ROOT;
}
users_query = get_mysql_users_query(server->server->server_string,
service->enable_root);
/* send first the query that fetches users and db grants */
if (mysql_query(con, users_query)) {
@ -1197,7 +1254,7 @@ getUsers(SERVICE *service, USERS *users)
char *dpwd;
int total_users = 0;
SERVER_REF *server;
char *users_query;
const char *users_query;
unsigned char hash[SHA_DIGEST_LENGTH]="";
char *users_data = NULL;
int nusers = 0;
@ -1343,10 +1400,21 @@ getUsers(SERVICE *service, USERS *users)
service->name)));
mysql_close(con);
return -1;
}
}
if (server->server->server_string == NULL)
{
const char *server_string = mysql_get_server_info(con);
if (!server_set_version_string(server->server, server_string))
{
mysql_close(con);
return -1;
}
}
const char *user_with_db_count = get_mysq_users_db_count_query(server->server->server_string);
/** Count users. Start with users and db grants for users */
if (mysql_query(con, MYSQL_USERS_WITH_DB_COUNT)) {
if (mysql_query(con, user_with_db_count)) {
if (mysql_errno(con) != ER_TABLEACCESS_DENIED_ERROR) {
/* This is an error we cannot handle, return */
LOGIF(LE, (skygw_log_write_flush(
@ -1403,13 +1471,8 @@ getUsers(SERVICE *service, USERS *users)
return -1;
}
if(service->enable_root) {
/* enable_root for MySQL protocol module means load the root user credentials from backend databases */
users_query = LOAD_MYSQL_USERS_WITH_DB_QUERY;
} else {
users_query = LOAD_MYSQL_USERS_WITH_DB_QUERY_NO_ROOT;
}
users_query = get_mysql_users_query(server->server->server_string,
service->enable_root);
/* send first the query that fetches users and db grants */
if (mysql_query(con, users_query)) {
/*

View File

@ -942,3 +942,24 @@ int i;
return ServerBits[i].bit;
return 0;
}
/**
* Set the version string of the server.
* @param server Server to update
* @param string Version string
* @return True if the assignment of the version string was successful, false if
* memory allocation failed.
*/
bool server_set_version_string(SERVER* server, const char* string)
{
bool rval = true;
spinlock_acquire(&server->lock);
free(server->server_string);
if ((server->server_string = strdup(string)) == NULL)
{
MXS_ERROR("Memory allocation failed.");
rval = false;
}
spinlock_release(&server->lock);
return rval;
}

View File

@ -212,4 +212,5 @@ extern void server_update_address(SERVER *, char *);
extern void server_update_port(SERVER *, unsigned short);
extern RESULTSET *serverGetList();
extern unsigned int server_map_status(char *str);
extern bool server_set_version_string(SERVER* server, const char* string);
#endif

View File

@ -308,11 +308,10 @@ char *server_string;
/* get server version string */
server_string = (char *)mysql_get_server_info(database->con);
if (server_string) {
database->server->server_string = realloc(database->server->server_string, strlen(server_string)+1);
if (database->server->server_string)
strcpy(database->server->server_string, server_string);
}
if (server_string)
{
server_set_version_string(database->server, server_string);
}
/* Check if the the Galera FSM shows this node is joined to the cluster */
if (mysql_query(database->con, "SHOW STATUS LIKE 'wsrep_local_state'") == 0

View File

@ -295,11 +295,10 @@ char *server_string;
/* get server version string */
server_string = (char *)mysql_get_server_info(database->con);
if (server_string) {
database->server->server_string = realloc(database->server->server_string, strlen(server_string)+1);
if (database->server->server_string)
strcpy(database->server->server_string, server_string);
}
if (server_string)
{
server_set_version_string(database->server, server_string);
}
/* get server_id form current node */
if (mysql_query(database->con, "SELECT @@server_id") == 0

View File

@ -643,10 +643,9 @@ monitorDatabase(MONITOR *mon, MONITOR_SERVERS *database)
/* get server version string */
server_string = (char *)mysql_get_server_info(database->con);
if (server_string) {
database->server->server_string = realloc(database->server->server_string, strlen(server_string)+1);
if (database->server->server_string)
strcpy(database->server->server_string, server_string);
if (server_string)
{
server_set_version_string(database->server, server_string);
}
/* get server_id form current node */

View File

@ -263,11 +263,10 @@ char *server_string;
/* get server version string */
server_string = (char *)mysql_get_server_info(database->con);
if (server_string) {
database->server->server_string = realloc(database->server->server_string, strlen(server_string)+1);
if (database->server->server_string)
strcpy(database->server->server_string, server_string);
}
if (server_string)
{
server_set_version_string(database->server, server_string);
}
/* Check if the the SQL node is able to contact one or more data nodes */
if (mysql_query(database->con, "SHOW STATUS LIKE 'Ndb_number_of_ready_data_nodes'") == 0