diff --git a/server/core/dbusers.c b/server/core/dbusers.c index 2dc434329..a4e48afa0 100644 --- a/server/core/dbusers.c +++ b/server/core/dbusers.c @@ -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)) { /* diff --git a/server/core/server.c b/server/core/server.c index 063ed6452..5d5a42f6e 100644 --- a/server/core/server.c +++ b/server/core/server.c @@ -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; +} diff --git a/server/include/server.h b/server/include/server.h index 263522959..84151ccad 100644 --- a/server/include/server.h +++ b/server/include/server.h @@ -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 diff --git a/server/modules/monitor/galeramon.c b/server/modules/monitor/galeramon.c index 4df951430..e81339832 100644 --- a/server/modules/monitor/galeramon.c +++ b/server/modules/monitor/galeramon.c @@ -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 diff --git a/server/modules/monitor/mmmon.c b/server/modules/monitor/mmmon.c index 7718f1435..2339a69a9 100644 --- a/server/modules/monitor/mmmon.c +++ b/server/modules/monitor/mmmon.c @@ -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 diff --git a/server/modules/monitor/mysql_mon.c b/server/modules/monitor/mysql_mon.c index c45c7604f..bd8e3e54f 100644 --- a/server/modules/monitor/mysql_mon.c +++ b/server/modules/monitor/mysql_mon.c @@ -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 */ diff --git a/server/modules/monitor/ndbclustermon.c b/server/modules/monitor/ndbclustermon.c index aabccf60c..ea9de889f 100644 --- a/server/modules/monitor/ndbclustermon.c +++ b/server/modules/monitor/ndbclustermon.c @@ -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