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 \ ON user.user=db.user AND user.host=db.host \
WHERE user.user IS NOT NULL" MYSQL_USERS_WITH_DB_ORDER 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 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 * \ #define LOAD_MYSQL_USERS_WITH_DB_QUERY_NO_ROOT "SELECT * \
FROM (" LOAD_MYSQL_USERS_WITH_DB_QUERY ") AS t1 \ FROM (" LOAD_MYSQL_USERS_WITH_DB_QUERY ") AS t1 \
WHERE user NOT IN ('root')" MYSQL_USERS_WITH_DB_ORDER 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 * \ #define LOAD_MYSQL_DATABASE_NAMES "SELECT * \
FROM ( (SELECT COUNT(1) AS ndbs \ FROM ( (SELECT COUNT(1) AS ndbs \
FROM INFORMATION_SCHEMA.SCHEMATA) AS tbl1, \ FROM INFORMATION_SCHEMA.SCHEMATA) AS tbl1, \
@ -133,6 +149,39 @@ int add_wildcard_users(USERS *users,
static int gw_mysql_set_timeouts(MYSQL* handle); 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 * 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. * that the grant has one or more single-character wildcards in it.
@ -651,7 +700,8 @@ getAllUsers(SERVICE *service, USERS *users)
char *dpwd = NULL; char *dpwd = NULL;
int total_users = 0; int total_users = 0;
SERVER_REF *server; SERVER_REF *server;
char *users_query, *tmp; const char *users_query;
char *tmp;
unsigned char hash[SHA_DIGEST_LENGTH]=""; unsigned char hash[SHA_DIGEST_LENGTH]="";
char *users_data = NULL; char *users_data = NULL;
char *final_data = NULL; char *final_data = NULL;
@ -825,9 +875,19 @@ getAllUsers(SERVICE *service, USERS *users)
mysql_close(con); mysql_close(con);
goto cleanup; 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 */ /** 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) { if (mysql_errno(con) != ER_TABLEACCESS_DENIED_ERROR) {
/* This is an error we cannot handle, return */ /* This is an error we cannot handle, return */
LOGIF(LE, (skygw_log_write_flush( LOGIF(LE, (skygw_log_write_flush(
@ -883,13 +943,10 @@ getAllUsers(SERVICE *service, USERS *users)
mysql_close(con); mysql_close(con);
goto cleanup; goto cleanup;
} }
if(service->enable_root) { users_query = get_mysql_users_query(server->server->server_string,
/* enable_root for MySQL protocol module means load the root user credentials from backend databases */ service->enable_root);
users_query = LOAD_MYSQL_USERS_WITH_DB_QUERY;
} else {
users_query = LOAD_MYSQL_USERS_WITH_DB_QUERY_NO_ROOT;
}
/* send first the query that fetches users and db grants */ /* send first the query that fetches users and db grants */
if (mysql_query(con, users_query)) { if (mysql_query(con, users_query)) {
@ -1197,7 +1254,7 @@ getUsers(SERVICE *service, USERS *users)
char *dpwd; char *dpwd;
int total_users = 0; int total_users = 0;
SERVER_REF *server; SERVER_REF *server;
char *users_query; const char *users_query;
unsigned char hash[SHA_DIGEST_LENGTH]=""; unsigned char hash[SHA_DIGEST_LENGTH]="";
char *users_data = NULL; char *users_data = NULL;
int nusers = 0; int nusers = 0;
@ -1343,10 +1400,21 @@ getUsers(SERVICE *service, USERS *users)
service->name))); service->name)));
mysql_close(con); mysql_close(con);
return -1; 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 */ /** 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) { if (mysql_errno(con) != ER_TABLEACCESS_DENIED_ERROR) {
/* This is an error we cannot handle, return */ /* This is an error we cannot handle, return */
LOGIF(LE, (skygw_log_write_flush( LOGIF(LE, (skygw_log_write_flush(
@ -1403,13 +1471,8 @@ getUsers(SERVICE *service, USERS *users)
return -1; return -1;
} }
if(service->enable_root) { users_query = get_mysql_users_query(server->server->server_string,
/* enable_root for MySQL protocol module means load the root user credentials from backend databases */ service->enable_root);
users_query = LOAD_MYSQL_USERS_WITH_DB_QUERY;
} else {
users_query = LOAD_MYSQL_USERS_WITH_DB_QUERY_NO_ROOT;
}
/* send first the query that fetches users and db grants */ /* send first the query that fetches users and db grants */
if (mysql_query(con, users_query)) { if (mysql_query(con, users_query)) {
/* /*

View File

@ -942,3 +942,24 @@ int i;
return ServerBits[i].bit; return ServerBits[i].bit;
return 0; 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 void server_update_port(SERVER *, unsigned short);
extern RESULTSET *serverGetList(); extern RESULTSET *serverGetList();
extern unsigned int server_map_status(char *str); extern unsigned int server_map_status(char *str);
extern bool server_set_version_string(SERVER* server, const char* string);
#endif #endif

View File

@ -308,11 +308,10 @@ char *server_string;
/* get server version string */ /* get server version string */
server_string = (char *)mysql_get_server_info(database->con); server_string = (char *)mysql_get_server_info(database->con);
if (server_string) { if (server_string)
database->server->server_string = realloc(database->server->server_string, strlen(server_string)+1); {
if (database->server->server_string) server_set_version_string(database->server, server_string);
strcpy(database->server->server_string, server_string); }
}
/* Check if the the Galera FSM shows this node is joined to the cluster */ /* 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 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 */ /* get server version string */
server_string = (char *)mysql_get_server_info(database->con); server_string = (char *)mysql_get_server_info(database->con);
if (server_string) { if (server_string)
database->server->server_string = realloc(database->server->server_string, strlen(server_string)+1); {
if (database->server->server_string) server_set_version_string(database->server, server_string);
strcpy(database->server->server_string, server_string); }
}
/* get server_id form current node */ /* get server_id form current node */
if (mysql_query(database->con, "SELECT @@server_id") == 0 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 */ /* get server version string */
server_string = (char *)mysql_get_server_info(database->con); server_string = (char *)mysql_get_server_info(database->con);
if (server_string) { if (server_string)
database->server->server_string = realloc(database->server->server_string, strlen(server_string)+1); {
if (database->server->server_string) server_set_version_string(database->server, server_string);
strcpy(database->server->server_string, server_string);
} }
/* get server_id form current node */ /* get server_id form current node */

View File

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