From 275580d6a865ffc9a37c09ab378b2b4e86c30974 Mon Sep 17 00:00:00 2001 From: Markus Makela Date: Mon, 30 Nov 2015 11:46:31 +0200 Subject: [PATCH] Formatted dbusers.c according to the style guide Fixed indentation, missing/misaligned brackets and made sure line length is kept as close to 80 characters as possible. --- server/core/dbusers.c | 3272 ++++++++++++++++++++++------------------- 1 file changed, 1741 insertions(+), 1531 deletions(-) diff --git a/server/core/dbusers.c b/server/core/dbusers.c index 1eca857ed..adbdc57ec 100644 --- a/server/core/dbusers.c +++ b/server/core/dbusers.c @@ -17,7 +17,8 @@ */ /** - * @file dbusers.c - Loading MySQL users from a MySQL backend server, this needs libmysqlclient.so and header files + * @file dbusers.c - Loading MySQL users from a MySQL backend server, this needs + * libmysqlclient.so and header files * * @verbatim * Revision History @@ -54,8 +55,9 @@ #define USERS_QUERY_NO_ROOT " AND user NOT IN ('root')" +/** Alternate query which resolves user grants at the table level */ #if 0 -# define LOAD_MYSQL_USERS_QUERY \ +#define LOAD_MYSQL_USERS_QUERY \ "SELECT DISTINCT \ user.user AS user, \ user.host AS host, \ @@ -72,13 +74,16 @@ WHERE user.user IS NOT NULL AND user.user <> ''" #else -# define LOAD_MYSQL_USERS_QUERY "SELECT \ +#define LOAD_MYSQL_USERS_QUERY "SELECT \ user, host, password, concat(user,host,password,Select_priv) AS userdata, \ Select_priv AS anydb FROM mysql.user WHERE user IS NOT NULL AND user <> ''" + #endif + #define MYSQL_USERS_COUNT "SELECT COUNT(1) AS nusers FROM mysql.user" #define MYSQL_USERS_WITH_DB_ORDER " ORDER BY host DESC" + #define LOAD_MYSQL_USERS_WITH_DB_QUERY "SELECT \ user.user AS user, \ user.host AS host, \ @@ -101,8 +106,11 @@ 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 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 \ @@ -123,13 +131,14 @@ To correct this GRANT SHOW DATABASES ON *.* privilege to the user %s." static int getUsers(SERVICE *service, USERS *users); -static int uh_cmpfun( void* v1, void* v2); +static int uh_cmpfun(void* v1, void* v2); static void *uh_keydup(void* key); -static void uh_keyfree( void* key); -static int uh_hfun( void* key); +static void uh_keyfree(void* key); +static int uh_hfun(void* key); char *mysql_users_fetch(USERS *users, MYSQL_USER_HOST *key); char *mysql_format_user_entry(void *data); -int add_mysql_users_with_host_ipv4(USERS *users, char *user, char *host, char *passwd, char *anydb, char *db); +int add_mysql_users_with_host_ipv4(USERS *users, char *user, char *host, + char *passwd, char *anydb, char *db); static int getDatabases(SERVICE *, MYSQL *); HASHTABLE *resource_alloc(); void resource_free(HASHTABLE *resource); @@ -138,15 +147,8 @@ int resource_add(HASHTABLE *, char *, char *); int resource_hash(char *); static int normalize_hostname(char *input_host, char *output_host); int wildcard_db_grant(char* str); - -int add_wildcard_users(USERS *users, - char* name, - char* host, - char* password, - char* anydb, - char* db, - HASHTABLE* hash); - +int add_wildcard_users(USERS *users, char* name, char* host, char* password, + char* anydb, char* db, HASHTABLE* hash); static int gw_mysql_set_timeouts(MYSQL* handle); /** @@ -210,10 +212,10 @@ bool host_matches_singlechar_wildcard(const char* user, const char* wild) * @param service The current service * @return -1 on any error or the number of users inserted (0 means no users at all) */ -int +int load_mysql_users(SERVICE *service) { - return getUsers(service, service->users); + return getUsers(service, service->users); } /** @@ -223,33 +225,35 @@ load_mysql_users(SERVICE *service) * @param service The current service * @return -1 on any error or the number of users inserted (0 means no users at all) */ -int +int reload_mysql_users(SERVICE *service) { -int i; -USERS *newusers, *oldusers; -HASHTABLE *oldresources; + int i; + USERS *newusers, *oldusers; + HASHTABLE *oldresources; - if ((newusers = mysql_users_alloc()) == NULL) - return 0; + if ((newusers = mysql_users_alloc()) == NULL) + { + return 0; + } - oldresources = service->resources; + oldresources = service->resources; - i = getUsers(service, newusers); + i = getUsers(service, newusers); - spinlock_acquire(&service->spin); - oldusers = service->users; + spinlock_acquire(&service->spin); + oldusers = service->users; - service->users = newusers; + service->users = newusers; - spinlock_release(&service->spin); + spinlock_release(&service->spin); - /* free the old table */ - users_free(oldusers); - /* free old resources */ - resource_free(oldresources); + /* free the old table */ + users_free(oldusers); + /* free old resources */ + resource_free(oldresources); - return i; + return i; } /** @@ -260,58 +264,66 @@ HASHTABLE *oldresources; * @param service The current service * @return -1 on any error or the number of users inserted (0 means no users at all) */ -int +int replace_mysql_users(SERVICE *service) { -int i; -USERS *newusers, *oldusers; -HASHTABLE *oldresources; + int i; + USERS *newusers, *oldusers; + HASHTABLE *oldresources; - if ((newusers = mysql_users_alloc()) == NULL) - return -1; + if ((newusers = mysql_users_alloc()) == NULL) + { + return -1; + } - oldresources = service->resources; + oldresources = service->resources; - /* load db users ad db grants */ - i = getUsers(service, newusers); + /* load db users ad db grants */ + i = getUsers(service, newusers); - if (i <= 0) { - users_free(newusers); - /* restore resources */ - service->resources = oldresources; - return i; - } + if (i <= 0) + { + users_free(newusers); + /* restore resources */ + service->resources = oldresources; + return i; + } - spinlock_acquire(&service->spin); - oldusers = service->users; + spinlock_acquire(&service->spin); + oldusers = service->users; - /* digest compare */ - if (oldusers != NULL && memcmp(oldusers->cksum, newusers->cksum, SHA_DIGEST_LENGTH) == 0) { - /* same data, nothing to do */ - MXS_DEBUG("%lu [replace_mysql_users] users' tables not switched, checksum is the same", - pthread_self()); + /* digest compare */ + if (oldusers != NULL && memcmp(oldusers->cksum, newusers->cksum, + SHA_DIGEST_LENGTH) == 0) + { + /* same data, nothing to do */ + MXS_DEBUG("%lu [replace_mysql_users] users' tables not switched, checksum is the same", + pthread_self()); - /* free the new table */ - users_free(newusers); - i = 0; - } else { - /* replace the service with effective new data */ - MXS_DEBUG("%lu [replace_mysql_users] users' tables replaced, checksum differs", - pthread_self()); - service->users = newusers; - } + /* free the new table */ + users_free(newusers); + i = 0; + } + else + { + /* replace the service with effective new data */ + MXS_DEBUG("%lu [replace_mysql_users] users' tables replaced, checksum differs", + pthread_self()); + service->users = newusers; + } - /* free old resources */ - resource_free(oldresources); + /* free old resources */ + resource_free(oldresources); - spinlock_release(&service->spin); + spinlock_release(&service->spin); - if (i && oldusers) { - /* free the old table */ - users_free(oldusers); - } + if (i && oldusers) + { + /* free the old table */ + users_free(oldusers); + } - return i; + return i; } /** @@ -376,89 +388,111 @@ bool host_has_singlechar_wildcard(const char *host) * @return 1 on success, 0 on failure and -1 on duplicate user */ -int add_mysql_users_with_host_ipv4(USERS *users, char *user, char *host, char *passwd, char *anydb, char *db) { - struct sockaddr_in serv_addr; - MYSQL_USER_HOST key; - char ret_ip[400]=""; - int ret = 0; +int add_mysql_users_with_host_ipv4(USERS *users, char *user, char *host, + char *passwd, char *anydb, char *db) +{ + struct sockaddr_in serv_addr; + MYSQL_USER_HOST key; + char ret_ip[400] = ""; + int ret = 0; - if (users == NULL || user == NULL || host == NULL) { - return ret; - } + if (users == NULL || user == NULL || host == NULL) + { + return ret; + } - /* prepare the user@host data struct */ - memset(&serv_addr, 0, sizeof(serv_addr)); - memset(&key, '\0', sizeof(key)); + /* prepare the user@host data struct */ + memset(&serv_addr, 0, sizeof(serv_addr)); + memset(&key, '\0', sizeof(key)); - /* set user */ - key.user = strdup(user); + /* set user */ + key.user = strdup(user); - if(key.user == NULL) { - return ret; - } + if (key.user == NULL) + { + return ret; + } - /* for anydb == Y key.resource is '\0' as set by memset */ - if (anydb == NULL) { - key.resource = NULL; - } else { - if (strcmp(anydb, "N") == 0) { - if (db != NULL) - key.resource = strdup(db); - else - key.resource = NULL; - } else { - key.resource = strdup(""); - } - } + /* for anydb == Y key.resource is '\0' as set by memset */ + if (anydb == NULL) + { + key.resource = NULL; + } + else + { + if (strcmp(anydb, "N") == 0) + { + if (db != NULL) + { + key.resource = strdup(db); + } + else + { + key.resource = NULL; + } + } + else + { + key.resource = strdup(""); + } + } - /* handle ANY, Class C,B,A */ + /* handle ANY, Class C,B,A */ - /* ANY */ - if (strcmp(host, "%") == 0) { - strcpy(ret_ip, "0.0.0.0"); - key.netmask = 0; - } else if (strnlen(host, MYSQL_HOST_MAXLEN + 1) <= MYSQL_HOST_MAXLEN && - is_ipaddress(host) && - host_has_singlechar_wildcard(host)) { + /* ANY */ + if (strcmp(host, "%") == 0) + { + strcpy(ret_ip, "0.0.0.0"); + key.netmask = 0; + } + else if (strnlen(host, MYSQL_HOST_MAXLEN + 1) <= MYSQL_HOST_MAXLEN && + is_ipaddress(host) && + host_has_singlechar_wildcard(host)) + { strcpy(key.hostname, host); strcpy(ret_ip, "0.0.0.0"); - key.netmask = 0; - } else { - /* hostname without % wildcards has netmask = 32 */ - key.netmask = normalize_hostname(host, ret_ip); + key.netmask = 0; + } + else + { + /* hostname without % wildcards has netmask = 32 */ + key.netmask = normalize_hostname(host, ret_ip); - if (key.netmask == -1) { - MXS_ERROR("strdup() failed in normalize_hostname for %s@%s", user, host); - } - } + if (key.netmask == -1) + { + MXS_ERROR("strdup() failed in normalize_hostname for %s@%s", user, host); + } + } - /* fill IPv4 data struct */ - if (setipaddress(&serv_addr.sin_addr, ret_ip) && strlen(ret_ip)) { + /* fill IPv4 data struct */ + if (setipaddress(&serv_addr.sin_addr, ret_ip) && strlen(ret_ip)) + { - /* copy IPv4 data into key.ipv4 */ - memcpy(&key.ipv4, &serv_addr, sizeof(serv_addr)); + /* copy IPv4 data into key.ipv4 */ + memcpy(&key.ipv4, &serv_addr, sizeof(serv_addr)); - /* if netmask < 32 there are % wildcards */ - if (key.netmask < 32) { - /* let's zero the last IP byte: a.b.c.0 we may have set above to 1*/ - key.ipv4.sin_addr.s_addr &= 0x00FFFFFF; - } - - /* add user@host as key and passwd as value in the MySQL users hash table */ - if (mysql_users_add(users, &key, passwd)) { - ret = 1; - } - else if(key.user) - { - ret = -1; - } - } + /* if netmask < 32 there are % wildcards */ + if (key.netmask < 32) + { + /* let's zero the last IP byte: a.b.c.0 we may have set above to 1*/ + key.ipv4.sin_addr.s_addr &= 0x00FFFFFF; + } - free(key.user); - if (key.resource) - free(key.resource); + /* add user@host as key and passwd as value in the MySQL users hash table */ + if (mysql_users_add(users, &key, passwd)) + { + ret = 1; + } + else if (key.user) + { + ret = -1; + } + } - return ret; + free(key.user); + free(key.resource); + + return ret; } /** @@ -472,87 +506,98 @@ int add_mysql_users_with_host_ipv4(USERS *users, char *user, char *host, char *p static int addDatabases(SERVICE *service, MYSQL *con) { - MYSQL_ROW row; - MYSQL_RES *result = NULL; - char *service_user = NULL; - char *service_passwd = NULL; - int ndbs = 0; + MYSQL_ROW row; + MYSQL_RES *result = NULL; + char *service_user = NULL; + char *service_passwd = NULL; + int ndbs = 0; - char *get_showdbs_priv_query = LOAD_MYSQL_DATABASE_NAMES; + char *get_showdbs_priv_query = LOAD_MYSQL_DATABASE_NAMES; - serviceGetUser(service, &service_user, &service_passwd); + serviceGetUser(service, &service_user, &service_passwd); - if (service_user == NULL || service_passwd == NULL) - return -1; + if (service_user == NULL || service_passwd == NULL) + { + return -1; + } - if (mysql_query(con, get_showdbs_priv_query)) { - MXS_ERROR("Loading database names for service %s encountered " - "error: %s.", - service->name, - mysql_error(con)); - return -1; - } + if (mysql_query(con, get_showdbs_priv_query)) + { + MXS_ERROR("Loading database names for service %s encountered " + "error: %s.", + service->name, + mysql_error(con)); + return -1; + } - result = mysql_store_result(con); + result = mysql_store_result(con); - if (result == NULL) { - MXS_ERROR("Loading database names for service %s encountered " - "error: %s.", - service->name, - mysql_error(con)); - return -1; - } + if (result == NULL) + { + MXS_ERROR("Loading database names for service %s encountered " + "error: %s.", + service->name, + mysql_error(con)); + return -1; + } - /* Result has only one row */ - row = mysql_fetch_row(result); + /* Result has only one row */ + row = mysql_fetch_row(result); - if (row) { - ndbs = atoi(row[0]); - } else { - ndbs = 0; + if (row) + { + ndbs = atoi(row[0]); + } + else + { + ndbs = 0; - MXS_ERROR(ERROR_NO_SHOW_DATABASES, service->name, service_user); - } + MXS_ERROR(ERROR_NO_SHOW_DATABASES, service->name, service_user); + } - /* free resut set */ - mysql_free_result(result); + /* free resut set */ + mysql_free_result(result); - if (!ndbs) { - /* return if no db names are available */ - return 0; - } + if (!ndbs) + { + /* return if no db names are available */ + return 0; + } - if (mysql_query(con, "SHOW DATABASES")) { - MXS_ERROR("Loading database names for service %s encountered " - "error: %s.", - service->name, - mysql_error(con)); + if (mysql_query(con, "SHOW DATABASES")) + { + MXS_ERROR("Loading database names for service %s encountered " + "error: %s.", + service->name, + mysql_error(con)); - return -1; - } + return -1; + } - result = mysql_store_result(con); + result = mysql_store_result(con); - if (result == NULL) { - MXS_ERROR("Loading database names for service %s encountered " - "error: %s.", - service->name, - mysql_error(con)); + if (result == NULL) + { + MXS_ERROR("Loading database names for service %s encountered " + "error: %s.", + service->name, + mysql_error(con)); - return -1; - } + return -1; + } - /* insert key and value "" */ - while ((row = mysql_fetch_row(result))) { - if(resource_add(service->resources, row[0], "")) - { - MXS_DEBUG("%s: Adding database %s to the resouce hash.", service->name, row[0]); - } - } + /* insert key and value "" */ + while ((row = mysql_fetch_row(result))) + { + if (resource_add(service->resources, row[0], "")) + { + MXS_DEBUG("%s: Adding database %s to the resouce hash.", service->name, row[0]); + } + } - mysql_free_result(result); + mysql_free_result(result); - return ndbs; + return ndbs; } /** @@ -566,88 +611,99 @@ addDatabases(SERVICE *service, MYSQL *con) static int getDatabases(SERVICE *service, MYSQL *con) { - MYSQL_ROW row; - MYSQL_RES *result = NULL; - char *service_user = NULL; - char *service_passwd = NULL; - int ndbs = 0; + MYSQL_ROW row; + MYSQL_RES *result = NULL; + char *service_user = NULL; + char *service_passwd = NULL; + int ndbs = 0; - char *get_showdbs_priv_query = LOAD_MYSQL_DATABASE_NAMES; + char *get_showdbs_priv_query = LOAD_MYSQL_DATABASE_NAMES; - serviceGetUser(service, &service_user, &service_passwd); + serviceGetUser(service, &service_user, &service_passwd); - if (service_user == NULL || service_passwd == NULL) - return -1; + if (service_user == NULL || service_passwd == NULL) + { + return -1; + } - if (mysql_query(con, get_showdbs_priv_query)) { - MXS_ERROR("Loading database names for service %s encountered " - "error when querying database privileges: %s.", - service->name, - mysql_error(con)); - return -1; - } + if (mysql_query(con, get_showdbs_priv_query)) + { + MXS_ERROR("Loading database names for service %s encountered " + "error when querying database privileges: %s.", + service->name, + mysql_error(con)); + return -1; + } - result = mysql_store_result(con); + result = mysql_store_result(con); - if (result == NULL) { - MXS_ERROR("Loading database names for service %s encountered " - "error when storing result set of database privilege query: %s.", - service->name, - mysql_error(con)); - return -1; - } + if (result == NULL) + { + MXS_ERROR("Loading database names for service %s encountered " + "error when storing result set of database privilege query: %s.", + service->name, + mysql_error(con)); + return -1; + } - /* Result has only one row */ - row = mysql_fetch_row(result); + /* Result has only one row */ + row = mysql_fetch_row(result); - if (row) { - ndbs = atoi(row[0]); - } else { - ndbs = 0; + if (row) + { + ndbs = atoi(row[0]); + } + else + { + ndbs = 0; - MXS_ERROR(ERROR_NO_SHOW_DATABASES, service->name, service_user); - } + MXS_ERROR(ERROR_NO_SHOW_DATABASES, service->name, service_user); + } - /* free resut set */ - mysql_free_result(result); + /* free resut set */ + mysql_free_result(result); - if (!ndbs) { - /* return if no db names are available */ - return 0; - } + if (!ndbs) + { + /* return if no db names are available */ + return 0; + } - if (mysql_query(con, "SHOW DATABASES")) { - MXS_ERROR("Loading database names for service %s encountered " - "error when executing SHOW DATABASES query: %s.", - service->name, - mysql_error(con)); + if (mysql_query(con, "SHOW DATABASES")) + { + MXS_ERROR("Loading database names for service %s encountered " + "error when executing SHOW DATABASES query: %s.", + service->name, + mysql_error(con)); - return -1; - } + return -1; + } - result = mysql_store_result(con); - - if (result == NULL) { - MXS_ERROR("Loading database names for service %s encountered " - "error when storing the result set: %s.", - service->name, - mysql_error(con)); + result = mysql_store_result(con); - return -1; - } + if (result == NULL) + { + MXS_ERROR("Loading database names for service %s encountered " + "error when storing the result set: %s.", + service->name, + mysql_error(con)); - /* Now populate service->resources hashatable with db names */ - service->resources = resource_alloc(); + return -1; + } - /* insert key and value "" */ - while ((row = mysql_fetch_row(result))) { - MXS_DEBUG("%s: Adding database %s to the resouce hash.", service->name, row[0]); - resource_add(service->resources, row[0], ""); - } + /* Now populate service->resources hashatable with db names */ + service->resources = resource_alloc(); - mysql_free_result(result); + /* insert key and value "" */ + while ((row = mysql_fetch_row(result))) + { + MXS_DEBUG("%s: Adding database %s to the resouce hash.", service->name, row[0]); + resource_add(service->resources, row[0], ""); + } - return ndbs; + mysql_free_result(result); + + return ndbs; } /** @@ -656,439 +712,468 @@ getDatabases(SERVICE *service, MYSQL *con) * * @param service The current service * @param users The users table into which to load the users - * @return -1 on any error or the number of users inserted + * @return -1 on any error or the number of users inserted * (0 means no users at all) */ static int getAllUsers(SERVICE *service, USERS *users) { - MYSQL *con = NULL; - MYSQL_ROW row; - MYSQL_RES *result = NULL; - char *service_user = NULL; - char *service_passwd = NULL; - char *dpwd = NULL; - int total_users = 0; - SERVER_REF *server; - const char *users_query; + MYSQL *con = NULL; + MYSQL_ROW row; + MYSQL_RES *result = NULL; + char *service_user = NULL; + char *service_passwd = NULL; + char *dpwd = NULL; + int total_users = 0; + SERVER_REF *server; + const char *users_query; char *tmp; - unsigned char hash[SHA_DIGEST_LENGTH]=""; - char *users_data = NULL; - char *final_data = NULL; - char dbnm[MYSQL_DATABASE_MAXLEN+1]; - int nusers = -1; - int users_data_row_len = MYSQL_USER_MAXLEN + - MYSQL_HOST_MAXLEN + - MYSQL_PASSWORD_LEN + - sizeof(char) + - MYSQL_DATABASE_MAXLEN; - int dbnames = 0; - int db_grants = 0; - bool anon_user = false; + unsigned char hash[SHA_DIGEST_LENGTH] = ""; + char *users_data = NULL; + char *final_data = NULL; + char dbnm[MYSQL_DATABASE_MAXLEN + 1]; + int nusers = -1; + int users_data_row_len = MYSQL_USER_MAXLEN + MYSQL_HOST_MAXLEN + + MYSQL_PASSWORD_LEN + sizeof(char) +MYSQL_DATABASE_MAXLEN; + int dbnames = 0; + int db_grants = 0; + bool anon_user = false; - if (serviceGetUser(service, &service_user, &service_passwd) == 0) - { - ss_dassert(service_passwd == NULL || service_user == NULL); - return -1; - } - - if (service->svc_do_shutdown) - { - return -1; - } - - dpwd = decryptPassword(service_passwd); - final_data = (char*) malloc(sizeof(char)); - *final_data = '\0'; - - /** - * Attempt to connect to one of the databases database or until we run - * out of databases - * to try - */ - server = service->dbref; - - if(server == NULL) + if (serviceGetUser(service, &service_user, &service_passwd) == 0) + { + ss_dassert(service_passwd == NULL || service_user == NULL); + return -1; + } + + if (service->svc_do_shutdown) + { + return -1; + } + + dpwd = decryptPassword(service_passwd); + final_data = (char*) malloc(sizeof(char)); + *final_data = '\0'; + + /** + * Attempt to connect to one of the databases database or until we run + * out of databases + * to try + */ + server = service->dbref; + + if (server == NULL) + { + goto cleanup; + } + + service->resources = resource_alloc(); + + while (server != NULL) + { + + con = mysql_init(NULL); + + if (con == NULL) { + MXS_ERROR("mysql_init: %s", mysql_error(con)); goto cleanup; } - service->resources = resource_alloc(); - - while(server != NULL) + /** Set read, write and connect timeout values */ + if (gw_mysql_set_timeouts(con)) { + MXS_ERROR("Failed to set timeout values for backend connection."); + mysql_close(con); + goto cleanup; + } - con = mysql_init(NULL); - - if (con == NULL) - { - MXS_ERROR("mysql_init: %s", mysql_error(con)); - goto cleanup; - } - - /** Set read, write and connect timeout values */ - if (gw_mysql_set_timeouts(con)) - { - MXS_ERROR("Failed to set timeout values for backend connection."); - mysql_close(con); - goto cleanup; - } - - if (mysql_options(con, MYSQL_OPT_USE_REMOTE_CONNECTION, NULL)) - { - MXS_ERROR("Failed to set external connection. " - "It is needed for backend server connections."); - mysql_close(con); - goto cleanup; - } - - - while(!service->svc_do_shutdown && - server != NULL && - (mysql_real_connect(con, - server->server->name, - service_user, - dpwd, - NULL, - server->server->port, - NULL, - 0) == NULL)) - { - server = server->next; - } - - - if (server == NULL) - { - MXS_ERROR("Unable to get user data from backend database " - "for service [%s]. Missing server information.", - service->name); - mysql_close(con); - goto cleanup; - } - - addDatabases(service, con); - mysql_close(con); - server = server->next; - } - - server = service->dbref; - - while(server != NULL) + if (mysql_options(con, MYSQL_OPT_USE_REMOTE_CONNECTION, NULL)) { - - con = mysql_init(NULL); - - if (con == NULL) - { - MXS_ERROR("mysql_init: %s", mysql_error(con)); - goto cleanup; - } - - /** Set read, write and connect timeout values */ - if (gw_mysql_set_timeouts(con)) - { - MXS_ERROR("Failed to set timeout values for backend connection."); - mysql_close(con); - goto cleanup; - } - - if (mysql_options(con, MYSQL_OPT_USE_REMOTE_CONNECTION, NULL)) - { - MXS_ERROR("Failed to set external connection. " - "It is needed for backend server connections."); - mysql_close(con); - goto cleanup; - } - - - while(!service->svc_do_shutdown && - server != NULL && - (mysql_real_connect(con, - server->server->name, - service_user, - dpwd, - NULL, - server->server->port, - NULL, - 0) == NULL)) - { - server = server->next; - } - - - if (server == NULL) - { - MXS_ERROR("Unable to get user data from backend database " - "for service [%s]. Missing server information.", - service->name); - mysql_close(con); - goto cleanup; - } + MXS_ERROR("Failed to set external connection. " + "It is needed for backend server connections."); + mysql_close(con); + goto cleanup; + } - if (server->server->server_string == NULL) + + while (!service->svc_do_shutdown && + server != NULL && + (mysql_real_connect(con, + server->server->name, + service_user, + dpwd, + NULL, + server->server->port, + NULL, + 0) == NULL)) + { + server = server->next; + } + + + if (server == NULL) + { + MXS_ERROR("Unable to get user data from backend database " + "for service [%s]. Missing server information.", + service->name); + mysql_close(con); + goto cleanup; + } + + addDatabases(service, con); + mysql_close(con); + server = server->next; + } + + server = service->dbref; + + while (server != NULL) + { + + con = mysql_init(NULL); + + if (con == NULL) + { + MXS_ERROR("mysql_init: %s", mysql_error(con)); + goto cleanup; + } + + /** Set read, write and connect timeout values */ + if (gw_mysql_set_timeouts(con)) + { + MXS_ERROR("Failed to set timeout values for backend connection."); + mysql_close(con); + goto cleanup; + } + + if (mysql_options(con, MYSQL_OPT_USE_REMOTE_CONNECTION, NULL)) + { + MXS_ERROR("Failed to set external connection. " + "It is needed for backend server connections."); + mysql_close(con); + goto cleanup; + } + + + while (!service->svc_do_shutdown && server != NULL && + (mysql_real_connect(con, server->server->name, service_user, dpwd, + NULL, server->server->port, NULL, 0) == NULL)) + { + server = server->next; + } + + + if (server == NULL) + { + MXS_ERROR("Unable to get user data from backend database " + "for service [%s]. Missing server information.", + service->name); + 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)) { - 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 */ + 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 */ + MXS_ERROR("Loading users for service [%s] encountered error: [%s].", + service->name, + mysql_error(con)); + mysql_close(con); + goto cleanup; + } + else + { + /* + * We have got ER_TABLEACCESS_DENIED_ERROR + * try counting users from mysql.user without DB names. + */ + if (mysql_query(con, MYSQL_USERS_COUNT)) { - mysql_close(con); - goto cleanup; - } - } - /** Count users. Start with users and db grants for users */ - 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 */ MXS_ERROR("Loading users for service [%s] encountered error: [%s].", service->name, mysql_error(con)); mysql_close(con); goto cleanup; - } else { - /* - * We have got ER_TABLEACCESS_DENIED_ERROR - * try counting users from mysql.user without DB names. - */ - if (mysql_query(con, MYSQL_USERS_COUNT)) { - MXS_ERROR("Loading users for service [%s] encountered error: [%s].", - service->name, - mysql_error(con)); - mysql_close(con); - goto cleanup; - } - } + } } - - result = mysql_store_result(con); - - if (result == NULL) { - MXS_ERROR("Loading users for service [%s] encountered error: [%s].", + } + + result = mysql_store_result(con); + + if (result == NULL) + { + MXS_ERROR("Loading users for service [%s] encountered error: [%s].", + service->name, + mysql_error(con)); + mysql_close(con); + goto cleanup; + } + + row = mysql_fetch_row(result); + + nusers = atoi(row[0]); + + mysql_free_result(result); + + if (!nusers) + { + MXS_ERROR("Counting users for service %s returned 0.", service->name); + mysql_close(con); + goto cleanup; + } + + 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)) + { + /* + * An error occurred executing the query + * + * Check mysql_errno() against ER_TABLEACCESS_DENIED_ERROR) + */ + + if (1142 != mysql_errno(con)) + { + /* This is an error we cannot handle, return */ + + MXS_ERROR("Loading users with dbnames for service [%s] encountered " + "error: [%s], MySQL errno %i", service->name, - mysql_error(con)); - mysql_close(con); - goto cleanup; - } - - row = mysql_fetch_row(result); - - nusers = atoi(row[0]); - - mysql_free_result(result); - - if (!nusers) { - MXS_ERROR("Counting users for service %s returned 0.", service->name); - mysql_close(con); - goto cleanup; - } + mysql_error(con), + mysql_errno(con)); - users_query = get_mysql_users_query(server->server->server_string, - service->enable_root); + mysql_close(con); - - /* send first the query that fetches users and db grants */ - if (mysql_query(con, users_query)) { - /* - * An error occurred executing the query - * - * Check mysql_errno() against ER_TABLEACCESS_DENIED_ERROR) + goto cleanup; + } + else + { + /* + * We have got ER_TABLEACCESS_DENIED_ERROR + * try loading users from mysql.user without DB names. */ - - if (1142 != mysql_errno(con)) { - /* This is an error we cannot handle, return */ - - MXS_ERROR("Loading users with dbnames for service [%s] encountered " - "error: [%s], MySQL errno %i", + + MXS_ERROR(ERROR_NO_SHOW_DATABASES, service->name, service_user); + + /* check for root user select */ + if (service->enable_root) + { + users_query = LOAD_MYSQL_USERS_QUERY " ORDER BY HOST DESC"; + } + else + { + users_query = LOAD_MYSQL_USERS_QUERY USERS_QUERY_NO_ROOT " ORDER BY HOST DESC"; + } + + if (mysql_query(con, users_query)) + { + MXS_ERROR("Loading users for service [%s] encountered " + "error: [%s], code %i", service->name, mysql_error(con), mysql_errno(con)); - + mysql_close(con); - + goto cleanup; - } else { - /* - * We have got ER_TABLEACCESS_DENIED_ERROR - * try loading users from mysql.user without DB names. - */ - - MXS_ERROR(ERROR_NO_SHOW_DATABASES, service->name, service_user); - - /* check for root user select */ - if(service->enable_root) { - users_query = LOAD_MYSQL_USERS_QUERY " ORDER BY HOST DESC"; - } else { - users_query = LOAD_MYSQL_USERS_QUERY USERS_QUERY_NO_ROOT " ORDER BY HOST DESC"; - } - - if (mysql_query(con, users_query)) { - MXS_ERROR("Loading users for service [%s] encountered " - "error: [%s], code %i", - service->name, - mysql_error(con), - mysql_errno(con)); - - mysql_close(con); - - goto cleanup; - } - - /* users successfully loaded but without db grants */ - - MXS_NOTICE("Loading users from [mysql.user] without access to [mysql.db] for " - "service [%s]. MaxScale Authentication with DBname on connect " - "will not consider database grants.", - service->name); - } - } else { - /* - * users successfully loaded with db grants. - */ - MXS_DEBUG("[%s] Loading users with db grants.",service->name); - db_grants = 1; + } + + /* users successfully loaded but without db grants */ + + MXS_NOTICE("Loading users from [mysql.user] without access to [mysql.db] for " + "service [%s]. MaxScale Authentication with DBname on connect " + "will not consider database grants.", + service->name); } - - result = mysql_store_result(con); - - if (result == NULL) { - MXS_ERROR("Loading users for service %s encountered error: %s.", - service->name, - mysql_error(con)); - - mysql_free_result(result); - mysql_close(con); - - goto cleanup; - } - - users_data = (char *)calloc(nusers, (users_data_row_len * sizeof(char)) + 1); - - if (users_data == NULL) { - char errbuf[STRERROR_BUFLEN]; - MXS_ERROR("Memory allocation for user data failed due to %d, %s.", - errno, - strerror_r(errno, errbuf, sizeof(errbuf))); - mysql_free_result(result); - mysql_close(con); - - goto cleanup; + } + else + { + /* + * users successfully loaded with db grants. + */ + MXS_DEBUG("[%s] Loading users with db grants.", service->name); + db_grants = 1; + } + + result = mysql_store_result(con); + + if (result == NULL) + { + MXS_ERROR("Loading users for service %s encountered error: %s.", + service->name, + mysql_error(con)); + + mysql_free_result(result); + mysql_close(con); + + goto cleanup; + } + + users_data = (char *) calloc(nusers, (users_data_row_len * sizeof(char)) + 1); + + if (users_data == NULL) + { + char errbuf[STRERROR_BUFLEN]; + MXS_ERROR("Memory allocation for user data failed due to %d, %s.", + errno, + strerror_r(errno, errbuf, sizeof(errbuf))); + mysql_free_result(result); + mysql_close(con); + + goto cleanup; + } + + while ((row = mysql_fetch_row(result))) + { + + /** + * Up to six fields could be returned. + * user,host,passwd,concat(),anydb,db + * passwd+1 (escaping the first byte that is '*') + */ + + int rc = 0; + char *password = NULL; + + /** If the username is empty, the backend server still has anonymous + * user in it. This will mean that localhost addresses do not match + * the wildcard host '%' */ + if (strlen(row[0]) == 0) + { + anon_user = true; + continue; } - while ((row = mysql_fetch_row(result))) { - - /** - * Up to six fields could be returned. - * user,host,passwd,concat(),anydb,db - * passwd+1 (escaping the first byte that is '*') - */ - - int rc = 0; - char *password = NULL; - - /** If the username is empty, the backend server still has anonymous - * user in it. This will mean that localhost addresses do not match - * the wildcard host '%' */ - if(strlen(row[0]) == 0) + if (row[2] != NULL) + { + /* detect mysql_old_password (pre 4.1 protocol) */ + if (strlen(row[2]) == 16) { - anon_user = true; + MXS_ERROR("%s: The user %s@%s has on old password in the " + "backend database. MaxScale does not support these " + "old passwords. This user will not be able to connect " + "via MaxScale. Update the users password to correct " + "this.", + service->name, + row[0], + row[1]); continue; } - if (row[2] != NULL) { - /* detect mysql_old_password (pre 4.1 protocol) */ - if (strlen(row[2]) == 16) { - MXS_ERROR("%s: The user %s@%s has on old password in the " - "backend database. MaxScale does not support these " - "old passwords. This user will not be able to connect " - "via MaxScale. Update the users password to correct " - "this.", + if (strlen(row[2]) > 1) + { + password = row[2] + 1; + } + else + { + password = row[2]; + } + } + + /* + * add user@host and DB global priv and specificsa grant (if possible) + */ + bool havedb = false; + + if (db_grants) + { + /* we have dbgrants, store them */ + if (row[5]) + { + unsigned long *rowlen = mysql_fetch_lengths(result); + memcpy(dbnm, row[5], rowlen[5]); + memset(dbnm + rowlen[5], 0, 1); + havedb = true; + if (service->strip_db_esc) + { + strip_escape_chars(dbnm); + MXS_DEBUG("[%s]: %s -> %s", service->name, - row[0], - row[1]); - continue; + row[5], + dbnm); } - - if (strlen(row[2]) > 1) - password = row[2] +1; - else - password = row[2]; - } - - /* - * add user@host and DB global priv and specificsa grant (if possible) - */ - bool havedb = false; + } - if (db_grants) { - /* we have dbgrants, store them */ - if(row[5]){ - unsigned long *rowlen = mysql_fetch_lengths(result); - memcpy(dbnm,row[5],rowlen[5]); - memset(dbnm + rowlen[5],0,1); - havedb = true; - if(service->strip_db_esc) { - strip_escape_chars(dbnm); - MXS_DEBUG("[%s]: %s -> %s", - service->name, - row[5], - dbnm); - } - } + if (havedb && wildcard_db_grant(dbnm) && service->optimize_wildcard) + { + rc = add_wildcard_users(users, row[0], row[1], password, + row[4], dbnm, service->resources); + MXS_INFO("%s: Converted '%s' to %d individual database grants.", + service->name, dbnm, rc); + } + else + { + rc = add_mysql_users_with_host_ipv4(users, row[0], row[1], + password, row[4], + havedb ? dbnm : NULL); + } - if(havedb && wildcard_db_grant(dbnm) && service->optimize_wildcard) - { - rc = add_wildcard_users(users, row[0], row[1], password, row[4], dbnm, service->resources); - MXS_INFO("%s: Converted '%s' to %d individual database grants.",service->name,dbnm,rc); - } - else - { - rc = add_mysql_users_with_host_ipv4(users, row[0], row[1], password, row[4], havedb ? dbnm : NULL); - } - - MXS_DEBUG("%s: Adding user:%s host:%s anydb:%s db:%s.", - service->name,row[0],row[1],row[4], - havedb ? dbnm : NULL); - } else { - /* we don't have dbgrants, simply set ANY DB for the user */ - rc = add_mysql_users_with_host_ipv4(users, row[0], row[1], password, "Y", NULL); - } - - if (rc == 1) { - if (db_grants) { - char dbgrant[MYSQL_DATABASE_MAXLEN + 1]=""; - if (row[4] != NULL) { - if (strcmp(row[4], "Y")) - strcpy(dbgrant, "ANY"); - else { - if (row[5]) - strncpy(dbgrant, row[5], MYSQL_DATABASE_MAXLEN); - } + MXS_DEBUG("%s: Adding user:%s host:%s anydb:%s db:%s.", + service->name, row[0], row[1], row[4], + havedb ? dbnm : NULL); + } + else + { + /* we don't have dbgrants, simply set ANY DB for the user */ + rc = add_mysql_users_with_host_ipv4(users, row[0], row[1], + password, "Y", NULL); + } + + if (rc == 1) + { + if (db_grants) + { + char dbgrant[MYSQL_DATABASE_MAXLEN + 1] = ""; + if (row[4] != NULL) + { + if (strcmp(row[4], "Y")) + { + strcpy(dbgrant, "ANY"); + } + else if (row[5]) + { + strncpy(dbgrant, row[5], MYSQL_DATABASE_MAXLEN); } - - if (!strlen(dbgrant)) - strcpy(dbgrant, "no db"); - - /* Log the user being added with its db grants */ - MXS_INFO("%s: User %s@%s for database %s added to service user table.", - service->name, - row[0], - row[1], - dbgrant); - } else { - /* Log the user being added (without db grants) */ - MXS_INFO("%s: User %s@%s added to service user table.", - service->name, - row[0], - row[1]); } - - /* Append data in the memory area for SHA1 digest */ - strncat(users_data, row[3], users_data_row_len); - - total_users++; - } else if(rc == -1) { - /** Duplicate user*/ + if (!strlen(dbgrant)) + { + strcpy(dbgrant, "no db"); + } + + /* Log the user being added with its db grants */ + MXS_INFO("%s: User %s@%s for database %s added to service user table.", + service->name, row[0], row[1], dbgrant); + } + else + { + /* Log the user being added (without db grants) */ + MXS_INFO("%s: User %s@%s added to service user table.", + service->name, row[0], row[1]); + } + + /* Append data in the memory area for SHA1 digest */ + strncat(users_data, row[3], users_data_row_len); + total_users++; + } + else if (rc == -1) + { + /** Duplicate user*/ if (service->log_auth_warnings) { MXS_NOTICE("Duplicate MySQL user found for service" @@ -1096,208 +1181,198 @@ getAllUsers(SERVICE *service, USERS *users) row[1], havedb ? " for database: " : "", havedb ? dbnm : ""); } - } else { - if (service->log_auth_warnings) - { - MXS_NOTICE("Warning: Failed to add user %s@%s" - " for service [%s]. This user will be " - "unavailable via MaxScale.", row[0], - row[1], service->name); - } - } - } - - mysql_free_result(result); - mysql_close(con); - - if((tmp = realloc(final_data, (strlen(final_data) + strlen(users_data) + 1) * sizeof(char))) == NULL) - { - free(users_data); - goto cleanup; - } - - final_data = tmp; - - strcat(final_data,users_data); - free(users_data); - - if(service->users_from_all) - { - server = server->next; } else { - server = NULL; + if (service->log_auth_warnings) + { + MXS_NOTICE("Warning: Failed to add user %s@%s for service [%s]." + " This user will be unavailable via MaxScale.", + row[0], row[1], service->name); + } } - } - - /* compute SHA1 digest for users' data */ - SHA1((const unsigned char *) final_data, strlen(final_data), hash); + } - memcpy(users->cksum, hash, SHA_DIGEST_LENGTH); + mysql_free_result(result); + mysql_close(con); - /** Set the parameter if it is not configured by the user */ - if(service->localhost_match_wildcard_host == SERVICE_PARAM_UNINIT) - service->localhost_match_wildcard_host = anon_user ? 0 : 1; - cleanup: - - free(dpwd); - free(final_data); - - return total_users; + if ((tmp = realloc(final_data, (strlen(final_data) + strlen(users_data) + + 1) * sizeof(char))) == NULL) + { + free(users_data); + goto cleanup; + } + + final_data = tmp; + + strcat(final_data, users_data); + free(users_data); + + if (service->users_from_all) + { + server = server->next; + } + else + { + server = NULL; + } + } + + /* compute SHA1 digest for users' data */ + SHA1((const unsigned char *) final_data, strlen(final_data), hash); + + memcpy(users->cksum, hash, SHA_DIGEST_LENGTH); + + /** Set the parameter if it is not configured by the user */ + if (service->localhost_match_wildcard_host == SERVICE_PARAM_UNINIT) + { + service->localhost_match_wildcard_host = anon_user ? 0 : 1; + } +cleanup: + + free(dpwd); + free(final_data); + + return total_users; } - /** * Load the user/passwd form mysql.user table into the service users' hashtable * environment. * * @param service The current service * @param users The users table into which to load the users - * @return -1 on any error or the number of users inserted + * @return -1 on any error or the number of users inserted * (0 means no users at all) */ static int getUsers(SERVICE *service, USERS *users) { - MYSQL *con = NULL; - MYSQL_ROW row; - MYSQL_RES *result = NULL; - char *service_user = NULL; - char *service_passwd = NULL; - char *dpwd; - int total_users = 0; - SERVER_REF *server; - const char *users_query; - unsigned char hash[SHA_DIGEST_LENGTH]=""; - char *users_data = NULL; - int nusers = 0; - int users_data_row_len = MYSQL_USER_MAXLEN + - MYSQL_HOST_MAXLEN + - MYSQL_PASSWORD_LEN + - sizeof(char) + - MYSQL_DATABASE_MAXLEN; - int dbnames = 0; - int db_grants = 0; - char dbnm[MYSQL_DATABASE_MAXLEN+1]; - bool anon_user = false; - - if (serviceGetUser(service, &service_user, &service_passwd) == 0) - { - ss_dassert(service_passwd == NULL || service_user == NULL); - return -1; - } + MYSQL *con = NULL; + MYSQL_ROW row; + MYSQL_RES *result = NULL; + char *service_user = NULL; + char *service_passwd = NULL; + char *dpwd; + int total_users = 0; + SERVER_REF *server; + const char *users_query; + unsigned char hash[SHA_DIGEST_LENGTH] = ""; + char *users_data = NULL; + int nusers = 0; + int users_data_row_len = MYSQL_USER_MAXLEN + + MYSQL_HOST_MAXLEN + + MYSQL_PASSWORD_LEN + + sizeof(char) + + MYSQL_DATABASE_MAXLEN; + int dbnames = 0; + int db_grants = 0; + char dbnm[MYSQL_DATABASE_MAXLEN + 1]; + bool anon_user = false; - if(service->users_from_all) - { - return getAllUsers(service,users); - } + if (serviceGetUser(service, &service_user, &service_passwd) == 0) + { + ss_dassert(service_passwd == NULL || service_user == NULL); + return -1; + } - con = mysql_init(NULL); + if (service->users_from_all) + { + return getAllUsers(service, users); + } - if (con == NULL) { - MXS_ERROR("mysql_init: %s", mysql_error(con)); - return -1; - } - /** Set read, write and connect timeout values */ - if (gw_mysql_set_timeouts(con)) - { - MXS_ERROR("Failed to set timeout values for backend connection."); + con = mysql_init(NULL); + + if (con == NULL) + { + MXS_ERROR("mysql_init: %s", mysql_error(con)); + return -1; + } + /** Set read, write and connect timeout values */ + if (gw_mysql_set_timeouts(con)) + { + MXS_ERROR("Failed to set timeout values for backend connection."); + mysql_close(con); + return -1; + } + + if (mysql_options(con, MYSQL_OPT_USE_REMOTE_CONNECTION, NULL)) + { + MXS_ERROR("Failed to set external connection. " + "It is needed for backend server connections."); + mysql_close(con); + return -1; + } + /** + * Attempt to connect to one of the databases database or until we run + * out of databases + * to try + */ + server = service->dbref; + dpwd = decryptPassword(service_passwd); + + /* Select a server with Master bit, if available */ + while (server != NULL && !(server->server->status & SERVER_MASTER)) + { + server = server->next; + } + + if (service->svc_do_shutdown) + { + free(dpwd); + mysql_close(con); + return -1; + } + + /* Try loading data from master server */ + if (server != NULL && + (mysql_real_connect(con, server->server->name, service_user, dpwd, NULL, + server->server->port, NULL, 0) != NULL)) + { + MXS_DEBUG("Dbusers : Loading data from backend database with " + "Master role [%s:%i] for service [%s]", + server->server->name, + server->server->port, + service->name); + } + else + { + /* load data from other servers via loop */ + server = service->dbref; + + while (!service->svc_do_shutdown && server != NULL && + (mysql_real_connect(con, server->server->name, service_user, dpwd, + NULL, server->server->port, NULL, 0) == NULL)) + { + MXS_ERROR("Failure loading users data from backend " + "[%s:%i] for service [%s]. MySQL error %i, %s", + server->server->name, server->server->port, + service->name, mysql_errno(con), mysql_error(con)); + server = server->next; + } + + if (service->svc_do_shutdown) + { + free(dpwd); mysql_close(con); return -1; - } + } - if (mysql_options(con, MYSQL_OPT_USE_REMOTE_CONNECTION, NULL)) { - MXS_ERROR("Failed to set external connection. " - "It is needed for backend server connections."); - mysql_close(con); - return -1; - } - /** - * Attempt to connect to one of the databases database or until we run - * out of databases - * to try - */ - server = service->dbref; - dpwd = decryptPassword(service_passwd); + if (server != NULL) + { + MXS_DEBUG("Loading data from backend database [%s:%i] for service [%s]", + server->server->name, server->server->port, service->name); + } + } - /* Select a server with Master bit, if available */ - while (server != NULL && !(server->server->status & SERVER_MASTER)) { - server = server->next; - } + free(dpwd); - if (service->svc_do_shutdown) - { - free(dpwd); - mysql_close(con); - return -1; - } - - /* Try loading data from master server */ - if (server != NULL && - (mysql_real_connect(con, - server->server->name, service_user, - dpwd, - NULL, - server->server->port, - NULL, 0) != NULL)) - { - MXS_DEBUG("Dbusers : Loading data from backend database with " - "Master role [%s:%i] for service [%s]", - server->server->name, - server->server->port, - service->name); - } else { - /* load data from other servers via loop */ - server = service->dbref; - - while (!service->svc_do_shutdown && - server != NULL && - (mysql_real_connect(con, - server->server->name, - service_user, - dpwd, - NULL, - server->server->port, - NULL, - 0) == NULL)) - { - MXS_ERROR("Failure loading users data from backend " - "[%s:%i] for service [%s]. MySQL error %i, %s", - server->server->name, - server->server->port, - service->name, - mysql_errno(con), - mysql_error(con)); - - server = server->next; - } - - if (service->svc_do_shutdown) - { - free(dpwd); - mysql_close(con); - return -1; - } - - if (server != NULL) { - MXS_DEBUG("Loading data from backend database " - "[%s:%i] for service [%s]", - server->server->name, - server->server->port, - service->name); - } - } - - free(dpwd); - - if (server == NULL) - { - MXS_ERROR("Unable to get user data from backend database " - "for service [%s]. Failed to connect to any of the backend databases.", - service->name); - mysql_close(con); - return -1; + if (server == NULL) + { + MXS_ERROR("Unable to get user data from backend database for service [%s]." + " Failed to connect to any of the backend databases.", service->name); + mysql_close(con); + return -1; } if (server->server->server_string == NULL) @@ -1311,271 +1386,296 @@ getUsers(SERVICE *service, USERS *users) } 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, user_with_db_count)) { - if (mysql_errno(con) != ER_TABLEACCESS_DENIED_ERROR) { - /* This is an error we cannot handle, return */ - MXS_ERROR("Loading users for service [%s] encountered error: [%s].", - service->name, - mysql_error(con)); - mysql_close(con); - return -1; - } else { - /* - * We have got ER_TABLEACCESS_DENIED_ERROR - * try counting users from mysql.user without DB names. - */ - if (mysql_query(con, MYSQL_USERS_COUNT)) { - MXS_ERROR("Loading users for service [%s] encountered error: [%s].", - service->name, - mysql_error(con)); - mysql_close(con); - return -1; - } - } - } - - result = mysql_store_result(con); - - if (result == NULL) { + /** Count users. Start with users and db grants for users */ + if (mysql_query(con, user_with_db_count)) + { + if (mysql_errno(con) != ER_TABLEACCESS_DENIED_ERROR) + { + /* This is an error we cannot handle, return */ MXS_ERROR("Loading users for service [%s] encountered error: [%s].", - service->name, - mysql_error(con)); + service->name, mysql_error(con)); mysql_close(con); return -1; - } + } + else + { + /* + * We have got ER_TABLEACCESS_DENIED_ERROR + * try counting users from mysql.user without DB names. + */ + if (mysql_query(con, MYSQL_USERS_COUNT)) + { + MXS_ERROR("Loading users for service [%s] encountered error: [%s].", + service->name, mysql_error(con)); + mysql_close(con); + return -1; + } + } + } - row = mysql_fetch_row(result); + result = mysql_store_result(con); - nusers = atoi(row[0]); + if (result == NULL) + { + MXS_ERROR("Loading users for service [%s] encountered error: [%s].", + service->name, mysql_error(con)); + mysql_close(con); + return -1; + } - mysql_free_result(result); + row = mysql_fetch_row(result); - if (!nusers) { - MXS_ERROR("Counting users for service %s returned 0.", service->name); - mysql_close(con); - return -1; - } + nusers = atoi(row[0]); + + mysql_free_result(result); + + if (!nusers) + { + MXS_ERROR("Counting users for service %s returned 0.", service->name); + mysql_close(con); + return -1; + } 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)) { - /* - * An error occurred executing the query - * - * Check mysql_errno() against ER_TABLEACCESS_DENIED_ERROR) - */ + /* send first the query that fetches users and db grants */ + if (mysql_query(con, users_query)) + { + /* + * An error occurred executing the query + * + * Check mysql_errno() against ER_TABLEACCESS_DENIED_ERROR) + */ - if (1142 != mysql_errno(con)) { - /* This is an error we cannot handle, return */ + if (1142 != mysql_errno(con)) + { + /* This is an error we cannot handle, return */ - MXS_ERROR("Loading users with dbnames for service [%s] encountered " - "error: [%s], MySQL errno %i", - service->name, - mysql_error(con), - mysql_errno(con)); + MXS_ERROR("Loading users with dbnames for service [%s] encountered " + "error: [%s], MySQL errno %i", service->name, + mysql_error(con), mysql_errno(con)); - mysql_close(con); - return -1; - } else { - /* - * We have got ER_TABLEACCESS_DENIED_ERROR - * try loading users from mysql.user without DB names. - */ - - MXS_ERROR(ERROR_NO_SHOW_DATABASES, service->name, service_user); - - /* check for root user select */ - if(service->enable_root) { - users_query = LOAD_MYSQL_USERS_QUERY " ORDER BY HOST DESC"; - } else { - users_query = LOAD_MYSQL_USERS_QUERY USERS_QUERY_NO_ROOT " ORDER BY HOST DESC"; - } - - if (mysql_query(con, users_query)) { - MXS_ERROR("Loading users for service [%s] encountered " - "error: [%s], code %i", - service->name, - mysql_error(con), - mysql_errno(con)); - - mysql_close(con); - return -1; - } - - /* users successfully loaded but without db grants */ - - MXS_NOTICE("Loading users from [mysql.user] without access to [mysql.db] for " - "service [%s]. MaxScale Authentication with DBname on connect " - "will not consider database grants.", - service->name); - } - } else { - /* - * users successfully loaded with db grants. - */ - - db_grants = 1; - } - - result = mysql_store_result(con); - - if (result == NULL) { - MXS_ERROR("Loading users for service %s encountered error: %s.", - service->name, - mysql_error(con)); - - mysql_free_result(result); mysql_close(con); return -1; - } + } + else + { + /* + * We have got ER_TABLEACCESS_DENIED_ERROR + * try loading users from mysql.user without DB names. + */ + MXS_ERROR(ERROR_NO_SHOW_DATABASES, service->name, service_user); - users_data = (char *)calloc(nusers, (users_data_row_len * sizeof(char)) + 1); + /* check for root user select */ + if (service->enable_root) + { + users_query = LOAD_MYSQL_USERS_QUERY " ORDER BY HOST DESC"; + } + else + { + users_query = LOAD_MYSQL_USERS_QUERY USERS_QUERY_NO_ROOT " ORDER BY HOST DESC"; + } - if (users_data == NULL) { - char errbuf[STRERROR_BUFLEN]; - MXS_ERROR("Memory allocation for user data failed due to %d, %s.", - errno, - strerror_r(errno, errbuf, sizeof(errbuf))); - mysql_free_result(result); - mysql_close(con); - return -1; - } + if (mysql_query(con, users_query)) + { + MXS_ERROR("Loading users for service [%s] encountered error: " + "[%s], code %i", service->name, mysql_error(con), + mysql_errno(con)); - if (db_grants) { - /* load all mysql database names */ - dbnames = getDatabases(service, con); + mysql_close(con); + return -1; + } - MXS_DEBUG("Loaded %d MySQL Database Names for service [%s]", - dbnames, - service->name); - } else { - service->resources = NULL; - } + /* users successfully loaded but without db grants */ - while ((row = mysql_fetch_row(result))) { + MXS_NOTICE("Loading users from [mysql.user] without access to [mysql.db] for " + "service [%s]. MaxScale Authentication with DBname on connect " + "will not consider database grants.", service->name); + } + } + else + { + /** Users successfully loaded with database grants */ + db_grants = 1; + } - /** - * Up to six fields could be returned. - * user,host,passwd,concat(),anydb,db - * passwd+1 (escaping the first byte that is '*') - */ - - int rc = 0; - char *password = NULL; + result = mysql_store_result(con); - /** If the username is empty, the backend server still has anonymous - * user in it. This will mean that localhost addresses do not match - * the wildcard host '%' */ - if(strlen(row[0]) == 0) + if (result == NULL) + { + MXS_ERROR("Loading users for service %s encountered error: %s.", + service->name, mysql_error(con)); + + mysql_free_result(result); + mysql_close(con); + return -1; + } + + users_data = (char *) calloc(nusers, (users_data_row_len * sizeof(char)) + 1); + + if (users_data == NULL) + { + char errbuf[STRERROR_BUFLEN]; + MXS_ERROR("Memory allocation for user data failed due to %d, %s.", + errno, strerror_r(errno, errbuf, sizeof(errbuf))); + mysql_free_result(result); + mysql_close(con); + return -1; + } + + if (db_grants) + { + /* load all mysql database names */ + dbnames = getDatabases(service, con); + MXS_DEBUG("Loaded %d MySQL Database Names for service [%s]", + dbnames, service->name); + } + else + { + service->resources = NULL; + } + + while ((row = mysql_fetch_row(result))) + { + + /** + * Up to six fields could be returned. + * user,host,passwd,concat(),anydb,db + * passwd+1 (escaping the first byte that is '*') + */ + + int rc = 0; + char *password = NULL; + + /** If the username is empty, the backend server still has anonymous + * user in it. This will mean that localhost addresses do not match + * the wildcard host '%' */ + if (strlen(row[0]) == 0) + { + anon_user = true; + continue; + } + + if (row[2] != NULL) + { + /* detect mysql_old_password (pre 4.1 protocol) */ + if (strlen(row[2]) == 16) + { + MXS_ERROR("%s: The user %s@%s has on old password in the " + "backend database. MaxScale does not support these " + "old passwords. This user will not be able to connect " + "via MaxScale. Update the users password to correct " + "this.", service->name, row[0], row[1]); + continue; + } + + if (strlen(row[2]) > 1) + { + password = row[2] + 1; + } + else + { + password = row[2]; + } + } + + /* + * add user@host and DB global priv and specificsa grant (if possible) + */ + if (db_grants) + { + bool havedb = false; + /* we have dbgrants, store them */ + if (row[5]) + { + unsigned long *rowlen = mysql_fetch_lengths(result); + memcpy(dbnm, row[5], rowlen[5]); + memset(dbnm + rowlen[5], 0, 1); + havedb = true; + if (service->strip_db_esc) { - anon_user = true; - continue; + strip_escape_chars(dbnm); + MXS_DEBUG("[%s]: %s -> %s", service->name, row[5], dbnm); + } + } + + if (havedb && wildcard_db_grant(row[5])) + { + if (service->optimize_wildcard) + { + rc = add_wildcard_users(users, row[0], row[1], password, row[4], + dbnm, service->resources); + MXS_INFO("%s: Converted '%s' to %d individual database grants.", + service->name, row[5], rc); + } + else + { + /** Use ANYDB for wildcard grants */ + rc = add_mysql_users_with_host_ipv4(users, row[0], row[1], + password, "Y", NULL); + } + } + else + { + rc = add_mysql_users_with_host_ipv4(users, row[0], row[1], + password, row[4], + havedb ? dbnm : NULL); + } + + } + else + { + /* we don't have dbgrants, simply set ANY DB for the user */ + rc = add_mysql_users_with_host_ipv4(users, row[0], row[1], password, + "Y", NULL); + } + + if (rc == 1) + { + if (db_grants) + { + char dbgrant[MYSQL_DATABASE_MAXLEN + 1] = ""; + if (row[4] != NULL) + { + if (strcmp(row[4], "Y")) + { + strcpy(dbgrant, "ANY"); + } + else if (row[5]) + { + strncpy(dbgrant, row[5], MYSQL_DATABASE_MAXLEN); + } } - if (row[2] != NULL) { - /* detect mysql_old_password (pre 4.1 protocol) */ - if (strlen(row[2]) == 16) { - MXS_ERROR("%s: The user %s@%s has on old password in the " - "backend database. MaxScale does not support these " - "old passwords. This user will not be able to connect " - "via MaxScale. Update the users password to correct " - "this.", - service->name, - row[0], - row[1]); - continue; - } + if (!strlen(dbgrant)) + { + strcpy(dbgrant, "no db"); + } - if (strlen(row[2]) > 1) - password = row[2] +1; - else - password = row[2]; - } + /* Log the user being added with its db grants */ + MXS_INFO("%s: User %s@%s for database %s added to " + "service user table.", + service->name, + row[0], + row[1], + dbgrant); + } + else + { + /* Log the user being added (without db grants) */ + MXS_INFO("%s: User %s@%s added to service user table.", + service->name, + row[0], + row[1]); + } - /* - * add user@host and DB global priv and specificsa grant (if possible) - */ - - if (db_grants) { - bool havedb = false; - /* we have dbgrants, store them */ - if(row[5]){ - unsigned long *rowlen = mysql_fetch_lengths(result); - memcpy(dbnm,row[5],rowlen[5]); - memset(dbnm + rowlen[5],0,1); - havedb = true; - if(service->strip_db_esc) { - strip_escape_chars(dbnm); - MXS_DEBUG("[%s]: %s -> %s", - service->name, - row[5], - dbnm); - } - } - - if(havedb && wildcard_db_grant(row[5])) - { - if(service->optimize_wildcard) - { - rc = add_wildcard_users(users, row[0], row[1], password, row[4], dbnm, service->resources); - MXS_INFO("%s: Converted '%s' to %d individual database grants.", - service->name, row[5], rc); - } - else - { - /** Use ANYDB for wildcard grants */ - rc = add_mysql_users_with_host_ipv4(users, row[0], row[1], password, "Y", NULL); - } - } - else - { - rc = add_mysql_users_with_host_ipv4(users, row[0], row[1], password, row[4], havedb ? dbnm : NULL); - } - - } else { - /* we don't have dbgrants, simply set ANY DB for the user */ - rc = add_mysql_users_with_host_ipv4(users, row[0], row[1], password, "Y", NULL); - } - - if (rc == 1) { - if (db_grants) { - char dbgrant[MYSQL_DATABASE_MAXLEN + 1]=""; - if (row[4] != NULL) { - if (strcmp(row[4], "Y")) - strcpy(dbgrant, "ANY"); - else { - if (row[5]) - strncpy(dbgrant, row[5], MYSQL_DATABASE_MAXLEN); - } - } - - if (!strlen(dbgrant)) - strcpy(dbgrant, "no db"); - - /* Log the user being added with its db grants */ - MXS_INFO("%s: User %s@%s for database %s added to " - "service user table.", - service->name, - row[0], - row[1], - dbgrant); - } else { - /* Log the user being added (without db grants) */ - MXS_INFO("%s: User %s@%s added to service user table.", - service->name, - row[0], - row[1]); - } - - /* Append data in the memory area for SHA1 digest */ - strncat(users_data, row[3], users_data_row_len); - - total_users++; - - } else if(rc == -1) { - /** Duplicate user*/ + /* Append data in the memory area for SHA1 digest */ + strncat(users_data, row[3], users_data_row_len); + total_users++; + } + else if (rc == -1) + { + /** Duplicate user*/ if (service->log_auth_warnings) { MXS_WARNING("Duplicate MySQL user found for " @@ -1583,33 +1683,36 @@ getUsers(SERVICE *service, USERS *users) row[1], db_grants ? " for database: " : "", db_grants ? row[5] : ""); } - } else { + } + else + { if (service->log_auth_warnings) { MXS_WARNING("Failed to add user %s@%s for" " service [%s]. This user will be unavailable" " via MaxScale.", row[0], row[1], service->name); } - } - } + } + } - /* compute SHA1 digest for users' data */ - SHA1((const unsigned char *) users_data, strlen(users_data), hash); + /* compute SHA1 digest for users' data */ + SHA1((const unsigned char *) users_data, strlen(users_data), hash); - memcpy(users->cksum, hash, SHA_DIGEST_LENGTH); + memcpy(users->cksum, hash, SHA_DIGEST_LENGTH); - /** Set the parameter if it is not configured by the user */ - if(service->localhost_match_wildcard_host == SERVICE_PARAM_UNINIT) - service->localhost_match_wildcard_host = anon_user ? 0 : 1; + /** Set the parameter if it is not configured by the user */ + if (service->localhost_match_wildcard_host == SERVICE_PARAM_UNINIT) + { + service->localhost_match_wildcard_host = anon_user ? 0 : 1; + } - free(users_data); - mysql_free_result(result); - mysql_close(con); + free(users_data); + mysql_free_result(result); + mysql_close(con); - return total_users; + return total_users; } - /** * Allocate a new MySQL users table for mysql specific users@host as key * @@ -1618,25 +1721,31 @@ getUsers(SERVICE *service, USERS *users) USERS * mysql_users_alloc() { -USERS *rval; + USERS *rval; - if ((rval = calloc(1, sizeof(USERS))) == NULL) - return NULL; + if ((rval = calloc(1, sizeof(USERS))) == NULL) + { + return NULL; + } - if ((rval->data = hashtable_alloc(USERS_HASHTABLE_DEFAULT_SIZE, uh_hfun, uh_cmpfun)) == NULL) { - free(rval); - return NULL; - } + if ((rval->data = hashtable_alloc(USERS_HASHTABLE_DEFAULT_SIZE, uh_hfun, + uh_cmpfun)) == NULL) + { + free(rval); + return NULL; + } - /* set the MySQL user@host print routine for the debug interface */ - rval->usersCustomUserFormat = mysql_format_user_entry; + /* set the MySQL user@host print routine for the debug interface */ + rval->usersCustomUserFormat = mysql_format_user_entry; - /* the key is handled by uh_keydup/uh_keyfree. - * the value is a (char *): it's handled by strdup/free - */ - hashtable_memory_fns(rval->data, (HASHMEMORYFN)uh_keydup, (HASHMEMORYFN) strdup, (HASHMEMORYFN)uh_keyfree, (HASHMEMORYFN)free); + /* the key is handled by uh_keydup/uh_keyfree. + * the value is a (char *): it's handled by strdup/free + */ + hashtable_memory_fns(rval->data, (HASHMEMORYFN) uh_keydup, + (HASHMEMORYFN) strdup, (HASHMEMORYFN) uh_keyfree, + (HASHMEMORYFN) free); - return rval; + return rval; } /** @@ -1650,16 +1759,18 @@ USERS *rval; int mysql_users_add(USERS *users, MYSQL_USER_HOST *key, char *auth) { -int add; + int add; - if (key == NULL || key->user == NULL) - return 0; + if (key == NULL || key->user == NULL) + { + return 0; + } - atomic_add(&users->stats.n_adds, 1); - add = hashtable_add(users->data, key, auth); - atomic_add(&users->stats.n_entries, add); + atomic_add(&users->stats.n_adds, 1); + add = hashtable_add(users->data, key, auth); + atomic_add(&users->stats.n_entries, add); - return add; + return add; } /** @@ -1669,11 +1780,14 @@ int add; * @param key The key with user@host * @return The authentication data or NULL on error */ -char *mysql_users_fetch(USERS *users, MYSQL_USER_HOST *key) { - if (key == NULL) - return NULL; - atomic_add(&users->stats.n_fetches, 1); - return hashtable_fetch(users->data, key); +char *mysql_users_fetch(USERS *users, MYSQL_USER_HOST *key) +{ + if (key == NULL) + { + return NULL; + } + atomic_add(&users->stats.n_fetches, 1); + return hashtable_fetch(users->data, key); } /** @@ -1684,14 +1798,19 @@ char *mysql_users_fetch(USERS *users, MYSQL_USER_HOST *key) { * @return The hash key */ -static int uh_hfun( void* key) { - MYSQL_USER_HOST *hu = (MYSQL_USER_HOST *) key; +static int uh_hfun(void* key) +{ + MYSQL_USER_HOST *hu = (MYSQL_USER_HOST *) key; - if (key == NULL || hu == NULL || hu->user == NULL) { - return 0; - } else { - return (*hu->user + *(hu->user + 1) + (unsigned int) (hu->ipv4.sin_addr.s_addr & 0xFF000000 / (256 * 256 * 256))); - } + if (key == NULL || hu == NULL || hu->user == NULL) + { + return 0; + } + else + { + return(*hu->user + *(hu->user + 1) + + (unsigned int) (hu->ipv4.sin_addr.s_addr & 0xFF000000 / (256 * 256 * 256))); + } } /** @@ -1699,19 +1818,24 @@ static int uh_hfun( void* key) { * Currently only IPv4 addresses are supported * * @param key1 The key value, i.e. username@host (IPv4) - * @param key2 The key value, i.e. username@host (IPv4) + * @param key2 The key value, i.e. username@host (IPv4) * @return The compare value */ -static int uh_cmpfun( void* v1, void* v2) { - MYSQL_USER_HOST *hu1 = (MYSQL_USER_HOST *) v1; - MYSQL_USER_HOST *hu2 = (MYSQL_USER_HOST *) v2; +static int uh_cmpfun(void* v1, void* v2) +{ + MYSQL_USER_HOST *hu1 = (MYSQL_USER_HOST *) v1; + MYSQL_USER_HOST *hu2 = (MYSQL_USER_HOST *) v2; - if (v1 == NULL || v2 == NULL) - return 0; - - if (hu1->user == NULL || hu2->user == NULL) - return 0; + if (v1 == NULL || v2 == NULL) + { + return 0; + } + + if (hu1->user == NULL || hu2->user == NULL) + { + return 0; + } /** If the stored user has the unmodified address stored, that means we were not able * to resolve it at the time we loaded the users. We need to check if the @@ -1719,70 +1843,80 @@ static int uh_cmpfun( void* v1, void* v2) { const bool wildcard_host = strlen(hu2->hostname) > 0 && strlen(hu1->hostname) > 0; - if ((strcmp(hu1->user, hu2->user) == 0) && - /** Check for wildcard hostnames */ - ((wildcard_host && host_matches_singlechar_wildcard(hu1->hostname, hu2->hostname)) || - /** If no wildcard hostname is stored, check for network address. */ - (!wildcard_host && (hu1->ipv4.sin_addr.s_addr == hu2->ipv4.sin_addr.s_addr) && (hu1->netmask >= hu2->netmask)))) { + if ((strcmp(hu1->user, hu2->user) == 0) && + /** Check for wildcard hostnames */ + ((wildcard_host && host_matches_singlechar_wildcard(hu1->hostname,hu2->hostname)) || + /** If no wildcard hostname is stored, check for network address. */ + (!wildcard_host && (hu1->ipv4.sin_addr.s_addr == hu2->ipv4.sin_addr.s_addr) && + (hu1->netmask >= hu2->netmask)))) + { + /* if no database name was passed, auth is ok */ + if (hu1->resource == NULL || (hu1->resource && !strlen(hu1->resource))) + { + return 0; + } + else + { + /* (1) check for no database grants at all and deny auth */ + if (hu2->resource == NULL) + { + return 1; + } + /* (2) check for ANY database grant and allow auth */ + if (!strlen(hu2->resource)) + { + return 0; + } + /* (3) check for database name specific grant and allow auth */ + if (hu1->resource && hu2->resource && strcmp(hu1->resource, + hu2->resource) == 0) + { + return 0; + } - /* if no database name was passed, auth is ok */ - if (hu1->resource == NULL || (hu1->resource && !strlen(hu1->resource))) { - return 0; - } else { - /* (1) check for no database grants at all and deny auth */ - if (hu2->resource == NULL) { - return 1; - } - /* (2) check for ANY database grant and allow auth */ - if (!strlen(hu2->resource)) { - return 0; - } - /* (3) check for database name specific grant and allow auth */ - if (hu1->resource && hu2->resource && strcmp(hu1->resource,hu2->resource) == 0) { - return 0; - } + if (hu2->resource && strlen(hu2->resource) && strchr(hu2->resource, '%') != NULL) + { + regex_t re; + char db[MYSQL_DATABASE_MAXLEN * 2 + 1]; + strcpy(db, hu2->resource); + int len = strlen(db); + char* ptr = strrchr(db, '%'); - if(hu2->resource && strlen(hu2->resource) && strchr(hu2->resource,'%') != NULL) - { - regex_t re; - char db[MYSQL_DATABASE_MAXLEN*2 +1]; - strcpy(db,hu2->resource); - int len = strlen(db); - char* ptr = strrchr(db,'%'); + if (ptr == NULL) + { + return 1; + } - if(ptr == NULL) - { - return 1; - } + while (ptr) + { + memmove(ptr + 1, ptr, (len - (ptr - db)) + 1); + *ptr = '.'; + *(ptr + 1) = '*'; + len = strlen(db); + ptr = strrchr(db, '%'); + } - while(ptr) - { - memmove(ptr+1,ptr,(len - (ptr - db)) + 1); - *ptr = '.'; - *(ptr + 1) = '*'; - len = strlen(db); - ptr = strrchr(db,'%'); - } + if ((regcomp(&re, db, REG_ICASE | REG_NOSUB))) + { + return 1; + } - if((regcomp(&re,db,REG_ICASE|REG_NOSUB))) - { - return 1; - } + if (regexec(&re, hu1->resource, 0, NULL, 0) == 0) + { + regfree(&re); + return 0; + } + regfree(&re); + } - if(regexec(&re,hu1->resource,0,NULL,0) == 0) - { - regfree(&re); - return 0; - } - regfree(&re); - } - - /* no matches, deny auth */ - return 1; - } - } else { - return 1; - } + /* no matches, deny auth */ + return 1; + } + } + else + { + return 1; + } } /** @@ -1791,37 +1925,46 @@ static int uh_cmpfun( void* v1, void* v2) { * @param key The key value, i.e. username@host ip4/ip6 data */ -static void *uh_keydup(void* key) { - MYSQL_USER_HOST *rval = (MYSQL_USER_HOST *) calloc(1, sizeof(MYSQL_USER_HOST)); - MYSQL_USER_HOST *current_key = (MYSQL_USER_HOST *)key; +static void *uh_keydup(void* key) +{ + MYSQL_USER_HOST *rval = (MYSQL_USER_HOST *) calloc(1, sizeof(MYSQL_USER_HOST)); + MYSQL_USER_HOST *current_key = (MYSQL_USER_HOST *) key; - if (key == NULL || rval == NULL || current_key == NULL || current_key->user == NULL) { - if (rval) { - free(rval); - } + if (key == NULL || rval == NULL || current_key == NULL || current_key->user == NULL) + { + if (rval) + { + free(rval); + } - return NULL; - } + return NULL; + } - rval->user = strdup(current_key->user); + rval->user = strdup(current_key->user); - if (rval->user == NULL) { - free(rval); - return NULL; - } + if (rval->user == NULL) + { + free(rval); + return NULL; + } ss_dassert(strnlen(rval->hostname, MYSQL_HOST_MAXLEN + 1) <= MYSQL_HOST_MAXLEN); strncpy(rval->hostname, current_key->hostname, MYSQL_HOST_MAXLEN); rval->hostname[MYSQL_HOST_MAXLEN] = '\0'; - memcpy(&rval->ipv4, ¤t_key->ipv4, sizeof(struct sockaddr_in)); - memcpy(&rval->netmask, ¤t_key->netmask, sizeof(int)); + memcpy(&rval->ipv4, ¤t_key->ipv4, sizeof(struct sockaddr_in)); + memcpy(&rval->netmask, ¤t_key->netmask, sizeof(int)); - if (current_key->resource) - rval->resource = strdup(current_key->resource); - else rval->resource = NULL; + if (current_key->resource) + { + rval->resource = strdup(current_key->resource); + } + else + { + rval->resource = NULL; + } - return (void *) rval; + return(void *) rval; } /** @@ -1829,19 +1972,26 @@ static void *uh_keydup(void* key) { * * @param key The key value, i.e. username@host ip4 data */ -static void uh_keyfree( void* key) { - MYSQL_USER_HOST *current_key = (MYSQL_USER_HOST *)key; +static void uh_keyfree(void* key) +{ + MYSQL_USER_HOST *current_key = (MYSQL_USER_HOST *) key; - if (key == NULL) - return; + if (key == NULL) + { + return; + } - if (current_key && current_key->user) - free(current_key->user); + if (current_key && current_key->user) + { + free(current_key->user); + } - if (current_key && current_key->resource) - free(current_key->resource); + if (current_key && current_key->resource) + { + free(current_key->resource); + } - free(key); + free(key); } /** @@ -1853,42 +2003,66 @@ static void uh_keyfree( void* key) { */ char *mysql_format_user_entry(void *data) { - MYSQL_USER_HOST *entry; - char *mysql_user; - /* the returned user string is "USER" + "@" + "HOST" + '\0' */ - int mysql_user_len = MYSQL_USER_MAXLEN + 1 + INET_ADDRSTRLEN + 10 + MYSQL_USER_MAXLEN + 1; + MYSQL_USER_HOST *entry; + char *mysql_user; + /* the returned user string is "USER" + "@" + "HOST" + '\0' */ + int mysql_user_len = MYSQL_USER_MAXLEN + 1 + INET_ADDRSTRLEN + 10 + + MYSQL_USER_MAXLEN + 1; - if (data == NULL) - return NULL; - - entry = (MYSQL_USER_HOST *) data; + if (data == NULL) + { + return NULL; + } - mysql_user = (char *) calloc(mysql_user_len, sizeof(char)); + entry = (MYSQL_USER_HOST *) data; - if (mysql_user == NULL) - return NULL; + mysql_user = (char *) calloc(mysql_user_len, sizeof(char)); - /* format user@host based on wildcards */ - - if (entry->ipv4.sin_addr.s_addr == INADDR_ANY && entry->netmask == 0) { - snprintf(mysql_user, mysql_user_len-1, "%s@%%", entry->user); - } else if ( (entry->ipv4.sin_addr.s_addr & 0xFF000000) == 0 && entry->netmask == 24) { - snprintf(mysql_user, mysql_user_len-1, "%s@%i.%i.%i.%%", entry->user, entry->ipv4.sin_addr.s_addr & 0x000000FF, (entry->ipv4.sin_addr.s_addr & 0x0000FF00) / (256), (entry->ipv4.sin_addr.s_addr & 0x00FF0000) / (256 * 256)); - } else if ( (entry->ipv4.sin_addr.s_addr & 0xFFFF0000) == 0 && entry->netmask == 16) { - snprintf(mysql_user, mysql_user_len-1, "%s@%i.%i.%%.%%", entry->user, entry->ipv4.sin_addr.s_addr & 0x000000FF, (entry->ipv4.sin_addr.s_addr & 0x0000FF00) / (256)); - } else if ( (entry->ipv4.sin_addr.s_addr & 0xFFFFFF00) == 0 && entry->netmask == 8) { - snprintf(mysql_user, mysql_user_len-1, "%s@%i.%%.%%.%%", entry->user, entry->ipv4.sin_addr.s_addr & 0x000000FF); - } else if (entry->netmask == 32) { - strncpy(mysql_user, entry->user, MYSQL_USER_MAXLEN); - strcat(mysql_user, "@"); - inet_ntop(AF_INET, &(entry->ipv4).sin_addr, mysql_user+strlen(mysql_user), INET_ADDRSTRLEN); - } else { - snprintf(mysql_user, MYSQL_USER_MAXLEN-5, "Err: %s", entry->user); - strcat(mysql_user, "@"); - inet_ntop(AF_INET, &(entry->ipv4).sin_addr, mysql_user+strlen(mysql_user), INET_ADDRSTRLEN); - } + if (mysql_user == NULL) + { + return NULL; + } - return mysql_user; + /* format user@host based on wildcards */ + + if (entry->ipv4.sin_addr.s_addr == INADDR_ANY && entry->netmask == 0) + { + snprintf(mysql_user, mysql_user_len - 1, "%s@%%", entry->user); + } + else if ((entry->ipv4.sin_addr.s_addr & 0xFF000000) == 0 && entry->netmask == 24) + { + snprintf(mysql_user, mysql_user_len - 1, "%s@%i.%i.%i.%%", entry->user, + entry->ipv4.sin_addr.s_addr & 0x000000FF, + (entry->ipv4.sin_addr.s_addr & 0x0000FF00) / (256), + (entry->ipv4.sin_addr.s_addr & 0x00FF0000) / (256 * 256)); + } + else if ((entry->ipv4.sin_addr.s_addr & 0xFFFF0000) == 0 && entry->netmask == 16) + { + snprintf(mysql_user, mysql_user_len - 1, "%s@%i.%i.%%.%%", entry->user, + entry->ipv4.sin_addr.s_addr & 0x000000FF, + (entry->ipv4.sin_addr.s_addr & 0x0000FF00) / (256)); + } + else if ((entry->ipv4.sin_addr.s_addr & 0xFFFFFF00) == 0 && entry->netmask == 8) + { + snprintf(mysql_user, mysql_user_len - 1, "%s@%i.%%.%%.%%", entry->user, + entry->ipv4.sin_addr.s_addr & 0x000000FF); + } + else if (entry->netmask == 32) + { + strncpy(mysql_user, entry->user, MYSQL_USER_MAXLEN); + strcat(mysql_user, "@"); + inet_ntop(AF_INET, &(entry->ipv4).sin_addr, mysql_user + strlen(mysql_user), + INET_ADDRSTRLEN); + } + else + { + snprintf(mysql_user, MYSQL_USER_MAXLEN - 5, "Err: %s", entry->user); + strcat(mysql_user, "@"); + inet_ntop(AF_INET, &(entry->ipv4).sin_addr, mysql_user + strlen(mysql_user), + INET_ADDRSTRLEN); + } + + return mysql_user; } /** @@ -1899,9 +2073,10 @@ char *mysql_format_user_entry(void *data) void resource_free(HASHTABLE *resources) { - if (resources) { - hashtable_free(resources); - } + if (resources) + { + hashtable_free(resources); + } } /** @@ -1912,21 +2087,22 @@ resource_free(HASHTABLE *resources) HASHTABLE * resource_alloc() { -HASHTABLE *resources; + HASHTABLE *resources; - if ((resources = hashtable_alloc(10, simple_str_hash, strcmp)) == NULL) - { - return NULL; - } + if ((resources = hashtable_alloc(10, simple_str_hash, strcmp)) == NULL) + { + return NULL; + } - hashtable_memory_fns(resources, (HASHMEMORYFN)strdup, (HASHMEMORYFN)strdup, (HASHMEMORYFN)free, (HASHMEMORYFN)free); + hashtable_memory_fns(resources, (HASHMEMORYFN) strdup, (HASHMEMORYFN) strdup, + (HASHMEMORYFN) free, (HASHMEMORYFN) free); - return resources; + return resources; } /** - * Add a new MySQL database name to the resources table. The resource name must be unique - * + * Add a new MySQL database name to the resources table. The resource name must + * be unique. * @param resources The resources table * @param key The resource name * @param value The value for resource (not used) @@ -1935,7 +2111,7 @@ HASHTABLE *resources; int resource_add(HASHTABLE *resources, char *key, char *value) { - return hashtable_add(resources, key, value); + return hashtable_add(resources, key, value); } /** @@ -1948,7 +2124,7 @@ resource_add(HASHTABLE *resources, char *key, char *value) void * resource_fetch(HASHTABLE *resources, char *key) { - return hashtable_fetch(resources, key); + return hashtable_fetch(resources, key); } /** @@ -1967,117 +2143,119 @@ resource_fetch(HASHTABLE *resources, char *key) */ static int normalize_hostname(char *input_host, char *output_host) { -int netmask, bytes, bits = 0, found_wildcard = 0; -char *p, *lasts, *tmp; -int useorig = 0; + int netmask, bytes, bits = 0, found_wildcard = 0; + char *p, *lasts, *tmp; + int useorig = 0; - output_host[0] = 0; - bytes = 0; + output_host[0] = 0; + bytes = 0; - tmp = strdup(input_host); + tmp = strdup(input_host); - if (tmp == NULL) { - return -1; - } + if (tmp == NULL) + { + return -1; + } - p = strtok_r(tmp, ".", &lasts); - while (p != NULL) - { + p = strtok_r(tmp, ".", &lasts); + while (p != NULL) + { - if (strcmp(p, "%")) - { - if (! isdigit(*p)) - useorig = 1; + if (strcmp(p, "%")) + { + if (!isdigit(*p)) + { + useorig = 1; + } - strcat(output_host, p); - bits += 8; - } - else if (bytes == 3) - { - found_wildcard = 1; - strcat(output_host, "1"); - } - else - { - found_wildcard = 1; - strcat(output_host, "0"); - } - bytes++; - p = strtok_r(NULL, ".", &lasts); - if (p) - strcat(output_host, "."); - } - if (found_wildcard) - { - netmask = bits; - while (bytes++ < 4) - { - if (bytes == 4) - { - strcat(output_host, ".1"); - } - else - { - strcat(output_host, ".0"); - } - } - } - else - netmask = 32; + strcat(output_host, p); + bits += 8; + } + else if (bytes == 3) + { + found_wildcard = 1; + strcat(output_host, "1"); + } + else + { + found_wildcard = 1; + strcat(output_host, "0"); + } + bytes++; + p = strtok_r(NULL, ".", &lasts); + if (p) + { + strcat(output_host, "."); + } + } + if (found_wildcard) + { + netmask = bits; + while (bytes++ < 4) + { + if (bytes == 4) + { + strcat(output_host, ".1"); + } + else + { + strcat(output_host, ".0"); + } + } + } + else + netmask = 32; - if (useorig == 1) - { - netmask = 32; - strcpy(output_host, input_host); - } + if (useorig == 1) + { + netmask = 32; + strcpy(output_host, input_host); + } - free(tmp); + free(tmp); - return netmask; + return netmask; } /** * Set read, write and connect timeout values for MySQL database connection. - * + * * @param handle MySQL handle * @param read_timeout Read timeout value in seconds * @param write_timeout Write timeout value in seconds * @param connect_timeout Connect timeout value in seconds - * + * * @return 0 if succeed, 1 if failed */ static int gw_mysql_set_timeouts(MYSQL* handle) -{ - int rc; - +{ + int rc; + GATEWAY_CONF* cnf = config_get_global_options(); - if ((rc = mysql_options(handle, - MYSQL_OPT_READ_TIMEOUT, - (void *)&cnf->auth_read_timeout))) - { - MXS_ERROR("Failed to set read timeout for backend connection."); - goto retblock; - } - - if ((rc = mysql_options(handle, - MYSQL_OPT_CONNECT_TIMEOUT, - (void *)&cnf->auth_conn_timeout))) - { - MXS_ERROR("Failed to set connect timeout for backend connection."); - goto retblock; - } - - if ((rc = mysql_options(handle, - MYSQL_OPT_WRITE_TIMEOUT, - (void *)&cnf->auth_write_timeout))) - { - MXS_ERROR("Failed to set write timeout for backend connection."); - goto retblock; - } - - retblock: - return rc; + if ((rc = mysql_options(handle, MYSQL_OPT_READ_TIMEOUT, + (void *) &cnf->auth_read_timeout))) + { + MXS_ERROR("Failed to set read timeout for backend connection."); + goto retblock; + } + + if ((rc = mysql_options(handle, MYSQL_OPT_CONNECT_TIMEOUT, + (void *) &cnf->auth_conn_timeout))) + { + MXS_ERROR("Failed to set connect timeout for backend connection."); + goto retblock; + } + + if ((rc = mysql_options(handle, MYSQL_OPT_WRITE_TIMEOUT, + (void *) &cnf->auth_write_timeout))) + { + MXS_ERROR("Failed to set write timeout for backend connection."); + goto retblock; + } + +retblock: + return rc; } /* @@ -2090,33 +2268,47 @@ static int gw_mysql_set_timeouts(MYSQL* handle) static int dbusers_keywrite(int fd, void *key) { -MYSQL_USER_HOST *dbkey = (MYSQL_USER_HOST *)key; -int tmp; + MYSQL_USER_HOST *dbkey = (MYSQL_USER_HOST *) key; + int tmp; - tmp = strlen(dbkey->user); - if (write(fd, &tmp, sizeof(tmp)) != sizeof(tmp)) - return 0; - if (write(fd, dbkey->user, tmp) != tmp) - return 0; - if (write(fd, &dbkey->ipv4, sizeof(dbkey->ipv4)) != sizeof(dbkey->ipv4)) - return 0; - if (write(fd, &dbkey->netmask, sizeof(dbkey->netmask)) != sizeof(dbkey->netmask)) - return 0; - if (dbkey->resource) - { - tmp = strlen(dbkey->resource); - if (write(fd, &tmp, sizeof(tmp)) != sizeof(tmp)) - return 0; - if (write(fd, dbkey->resource, tmp) != tmp) - return 0; - } - else // NULL is valid, so represent with a length of -1 - { - tmp = -1; - if (write(fd, &tmp, sizeof(tmp)) != sizeof(tmp)) - return 0; - } - return 1; + tmp = strlen(dbkey->user); + if (write(fd, &tmp, sizeof(tmp)) != sizeof(tmp)) + { + return 0; + } + if (write(fd, dbkey->user, tmp) != tmp) + { + return 0; + } + if (write(fd, &dbkey->ipv4, sizeof(dbkey->ipv4)) != sizeof(dbkey->ipv4)) + { + return 0; + } + if (write(fd, &dbkey->netmask, sizeof(dbkey->netmask)) != sizeof(dbkey->netmask)) + { + return 0; + } + if (dbkey->resource) + { + tmp = strlen(dbkey->resource); + if (write(fd, &tmp, sizeof(tmp)) != sizeof(tmp)) + { + return 0; + } + if (write(fd, dbkey->resource, tmp) != tmp) + { + return 0; + } + } + else // NULL is valid, so represent with a length of -1 + { + tmp = -1; + if (write(fd, &tmp, sizeof(tmp)) != sizeof(tmp)) + { + return 0; + } + } + return 1; } /** @@ -2129,14 +2321,18 @@ int tmp; static int dbusers_valuewrite(int fd, void *value) { -int tmp; + int tmp; - tmp = strlen(value); - if (write(fd, &tmp, sizeof(tmp)) != sizeof(tmp)) - return 0; - if (write(fd, value, tmp) != tmp) - return 0; - return 1; + tmp = strlen(value); + if (write(fd, &tmp, sizeof(tmp)) != sizeof(tmp)) + { + return 0; + } + if (write(fd, value, tmp) != tmp) + { + return 0; + } + return 1; } /** @@ -2148,68 +2344,70 @@ int tmp; static void * dbusers_keyread(int fd) { -MYSQL_USER_HOST *dbkey; -int tmp; + MYSQL_USER_HOST *dbkey; + int tmp; - if ((dbkey = (MYSQL_USER_HOST *)malloc(sizeof(MYSQL_USER_HOST))) == NULL) - return NULL; - if (read(fd, &tmp, sizeof(tmp)) != sizeof(tmp)) - { - free(dbkey); - return NULL; - } - if ((dbkey->user = (char *)malloc(tmp + 1)) == NULL) - { - free(dbkey); - return NULL; - } - if (read(fd, dbkey->user, tmp) != tmp) - { - free(dbkey->user); - free(dbkey); - return NULL; - } - dbkey->user[tmp] = 0; // NULL Terminate - if (read(fd, &dbkey->ipv4, sizeof(dbkey->ipv4)) != sizeof(dbkey->ipv4)) - { - free(dbkey->user); - free(dbkey); - return NULL; - } - if (read(fd, &dbkey->netmask, sizeof(dbkey->netmask)) != sizeof(dbkey->netmask)) - { - free(dbkey->user); - free(dbkey); - return NULL; - } - if (read(fd, &tmp, sizeof(tmp)) != sizeof(tmp)) - { - free(dbkey->user); - free(dbkey); - return NULL; - } - if (tmp != -1) - { - if ((dbkey->resource = (char *)malloc(tmp + 1)) == NULL) - { - free(dbkey->user); - free(dbkey); - return NULL; - } - if (read(fd, dbkey->resource, tmp) != tmp) - { - free(dbkey->resource); - free(dbkey->user); - free(dbkey); - return NULL; - } - dbkey->resource[tmp] = 0; // NULL Terminate - } - else // NULL is valid, so represent with a length of -1 - { - dbkey->resource = NULL; - } - return (void *)dbkey; + if ((dbkey = (MYSQL_USER_HOST *) malloc(sizeof(MYSQL_USER_HOST))) == NULL) + { + return NULL; + } + if (read(fd, &tmp, sizeof(tmp)) != sizeof(tmp)) + { + free(dbkey); + return NULL; + } + if ((dbkey->user = (char *) malloc(tmp + 1)) == NULL) + { + free(dbkey); + return NULL; + } + if (read(fd, dbkey->user, tmp) != tmp) + { + free(dbkey->user); + free(dbkey); + return NULL; + } + dbkey->user[tmp] = 0; // NULL Terminate + if (read(fd, &dbkey->ipv4, sizeof(dbkey->ipv4)) != sizeof(dbkey->ipv4)) + { + free(dbkey->user); + free(dbkey); + return NULL; + } + if (read(fd, &dbkey->netmask, sizeof(dbkey->netmask)) != sizeof(dbkey->netmask)) + { + free(dbkey->user); + free(dbkey); + return NULL; + } + if (read(fd, &tmp, sizeof(tmp)) != sizeof(tmp)) + { + free(dbkey->user); + free(dbkey); + return NULL; + } + if (tmp != -1) + { + if ((dbkey->resource = (char *) malloc(tmp + 1)) == NULL) + { + free(dbkey->user); + free(dbkey); + return NULL; + } + if (read(fd, dbkey->resource, tmp) != tmp) + { + free(dbkey->resource); + free(dbkey->user); + free(dbkey); + return NULL; + } + dbkey->resource[tmp] = 0; // NULL Terminate + } + else // NULL is valid, so represent with a length of -1 + { + dbkey->resource = NULL; + } + return(void *) dbkey; } /** @@ -2221,20 +2419,24 @@ int tmp; static void * dbusers_valueread(int fd) { -char *value; -int tmp; + char *value; + int tmp; - if (read(fd, &tmp, sizeof(tmp)) != sizeof(tmp)) - return NULL; - if ((value = (char *)malloc(tmp + 1)) == NULL) - return NULL; - if (read(fd, value, tmp) != tmp) - { - free(value); - return NULL; - } - value[tmp] = 0; - return (void *)value; + if (read(fd, &tmp, sizeof(tmp)) != sizeof(tmp)) + { + return NULL; + } + if ((value = (char *) malloc(tmp + 1)) == NULL) + { + return NULL; + } + if (read(fd, value, tmp) != tmp) + { + free(value); + return NULL; + } + value[tmp] = 0; + return(void *) value; } /** @@ -2247,7 +2449,7 @@ int tmp; int dbusers_save(USERS *users, char *filename) { - return hashtable_save(users->data, filename, dbusers_keywrite, dbusers_valuewrite); + return hashtable_save(users->data, filename, dbusers_keywrite, dbusers_valuewrite); } /** @@ -2260,7 +2462,7 @@ dbusers_save(USERS *users, char *filename) int dbusers_load(USERS *users, char *filename) { - return hashtable_load(users->data, filename, dbusers_keyread, dbusers_valueread); + return hashtable_load(users->data, filename, dbusers_keyread, dbusers_valueread); } /** @@ -2272,11 +2474,13 @@ int wildcard_db_grant(char* str) { char* ptr = str; - while(ptr && *ptr != '\0') + while (ptr && *ptr != '\0') { - if(*ptr == '%') - return 1; - ptr++; + if (*ptr == '%') + { + return 1; + } + ptr++; } return 0; @@ -2293,60 +2497,66 @@ int wildcard_db_grant(char* str) * @param hash Hashtable with all database names * @return number of unique grants generated from wildcard database name */ -int add_wildcard_users(USERS *users, char* name, char* host, char* password, char* anydb, char* db, HASHTABLE* hash) +int add_wildcard_users(USERS *users, char* name, char* host, char* password, + char* anydb, char* db, HASHTABLE* hash) { HASHITERATOR* iter; HASHTABLE* ht = hash; - char *restr,*ptr,*value; - int len,err,rval = 0; + char *restr, *ptr, *value; + int len, err, rval = 0; char errbuf[1024]; regex_t re; - if(db == NULL || hash == NULL) - return 0; + if (db == NULL || hash == NULL) + { + return 0; + } - if((restr = malloc(sizeof(char)*strlen(db)*2)) == NULL) - return 0; - - strcpy(restr,db); + if ((restr = malloc(sizeof(char)*strlen(db)*2)) == NULL) + { + return 0; + } + + strcpy(restr, db); len = strlen(restr); - ptr = strchr(restr,'%'); + ptr = strchr(restr, '%'); - if(ptr == NULL) + if (ptr == NULL) { - free(restr); - return 0; + free(restr); + return 0; } - while(ptr) + while (ptr) { - memmove(ptr+1,ptr,(len - (ptr - restr)) + 1); - *ptr++ = '.'; - *ptr = '*'; - len = strlen(restr); - ptr = strchr(restr,'%'); + memmove(ptr + 1, ptr, (len - (ptr - restr)) + 1); + *ptr++ = '.'; + *ptr = '*'; + len = strlen(restr); + ptr = strchr(restr, '%'); } - if((err = regcomp(&re,restr,REG_ICASE|REG_NOSUB))) + if ((err = regcomp(&re, restr, REG_ICASE | REG_NOSUB))) { - regerror(err,&re,errbuf,1024); - MXS_ERROR("Failed to compile regex when resolving wildcard database grants: %s", + regerror(err, &re, errbuf, 1024); + MXS_ERROR("Failed to compile regex when resolving wildcard database grants: %s", errbuf); - free(restr); - return 0; + free(restr); + return 0; } iter = hashtable_iterator(ht); - while(iter && (value = hashtable_next(iter))) + while (iter && (value = hashtable_next(iter))) { - if(regexec(&re,value,0,NULL,0) == 0) - { - rval += add_mysql_users_with_host_ipv4(users, name, host, password, anydb, value); - } + if (regexec(&re, value, 0, NULL, 0) == 0) + { + rval += add_mysql_users_with_host_ipv4(users, name, host, password, + anydb, value); + } } - + hashtable_iterator_free(iter); regfree(&re); free(restr); @@ -2367,111 +2577,111 @@ bool check_service_permissions(SERVICE* service) { MYSQL* mysql; MYSQL_RES* res; - char *user,*password,*dpasswd; + char *user, *password, *dpasswd; SERVER_REF* server; int conn_timeout = 1; bool rval = true; - if(isInternalService(service->routerModule)) - return true; - - if(service->dbref == NULL) + if (isInternalService(service->routerModule)) { - MXS_ERROR("%s: Service is missing the servers parameter.", service->name); - return false; + return true; + } + + if (service->dbref == NULL) + { + MXS_ERROR("%s: Service is missing the servers parameter.", service->name); + return false; } server = service->dbref; if (serviceGetUser(service, &user, &password) == 0) { - MXS_ERROR("%s: Service is missing the user credentials for authentication.", - service->name); - return false; + MXS_ERROR("%s: Service is missing the user credentials for authentication.", + service->name); + return false; } dpasswd = decryptPassword(password); - if((mysql = mysql_init(NULL)) == NULL) + if ((mysql = mysql_init(NULL)) == NULL) { - MXS_ERROR("[%s] MySQL connection initialization failed.", __FUNCTION__); - free(dpasswd); - return false; + MXS_ERROR("[%s] MySQL connection initialization failed.", __FUNCTION__); + free(dpasswd); + return false; } - mysql_options(mysql,MYSQL_OPT_USE_REMOTE_CONNECTION,NULL); - mysql_options(mysql,MYSQL_OPT_CONNECT_TIMEOUT,&conn_timeout); + mysql_options(mysql, MYSQL_OPT_USE_REMOTE_CONNECTION, NULL); + mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, &conn_timeout); /** Connect to the first server. This assumes all servers have identical * user permissions. */ - if(mysql_real_connect(mysql,server->server->name,user,dpasswd,NULL,server->server->port,NULL,0) == NULL) + if (mysql_real_connect(mysql, server->server->name, user, dpasswd, NULL, + server->server->port, NULL, 0) == NULL) { int my_errno = mysql_errno(mysql); - MXS_ERROR("%s: Failed to connect to server %s(%s:%d) when" + MXS_ERROR("%s: Failed to connect to server %s(%s:%d) when" " checking authentication user credentials and permissions: %d %s", - service->name, - server->server->unique_name, - server->server->name, - server->server->port, - my_errno, - mysql_error(mysql)); - mysql_close(mysql); - free(dpasswd); + service->name, server->server->unique_name, + server->server->name, server->server->port, + my_errno, mysql_error(mysql)); + mysql_close(mysql); + free(dpasswd); /** We don't know enough about user permissions */ return my_errno != ER_ACCESS_DENIED_ERROR; } - if(mysql_query(mysql,"SELECT user, host, password,Select_priv FROM mysql.user limit 1") != 0) + if (mysql_query(mysql, "SELECT user, host, password,Select_priv FROM mysql.user limit 1") != 0) { - if(mysql_errno(mysql) == ER_TABLEACCESS_DENIED_ERROR) + if (mysql_errno(mysql) == ER_TABLEACCESS_DENIED_ERROR) { MXS_ERROR("%s: User '%s' is missing SELECT privileges" " on mysql.user table. MySQL error message: %s", - service->name,user,mysql_error(mysql)); - rval = false; + service->name, user, mysql_error(mysql)); + rval = false; } else { MXS_ERROR("%s: Error: Failed to query from mysql.user table." " MySQL error message: %s", - service->name,mysql_error(mysql)); - } + service->name, mysql_error(mysql)); + } } else { - if((res = mysql_use_result(mysql)) == NULL) + if ((res = mysql_use_result(mysql)) == NULL) { MXS_ERROR("%s: Error: Result retrieval failed when checking for" " permissions to the mysql.user table: %s", - service->name,mysql_error(mysql)); + service->name, mysql_error(mysql)); mysql_close(mysql); free(dpasswd); return true; } mysql_free_result(res); } - if(mysql_query(mysql,"SELECT user, host, db FROM mysql.db limit 1") != 0) + if (mysql_query(mysql, "SELECT user, host, db FROM mysql.db limit 1") != 0) { - if(mysql_errno(mysql) == ER_TABLEACCESS_DENIED_ERROR) + if (mysql_errno(mysql) == ER_TABLEACCESS_DENIED_ERROR) { MXS_WARNING("%s: User '%s' is missing SELECT privileges on mysql.db table. " "Database name will be ignored in authentication. MySQL error message: %s", - service->name,user,mysql_error(mysql)); + service->name, user, mysql_error(mysql)); } else { MXS_ERROR("%s: Failed to query from mysql.db table. MySQL error message: %s", - service->name,mysql_error(mysql)); - } + service->name, mysql_error(mysql)); + } } else { - if((res = mysql_use_result(mysql)) == NULL) + if ((res = mysql_use_result(mysql)) == NULL) { - MXS_ERROR("%s: Result retrieval failed when checking for permissions to the mysql.db table: %s", - service->name,mysql_error(mysql)); + MXS_ERROR("%s: Result retrieval failed when checking for permissions " + "to the mysql.db table: %s", service->name, mysql_error(mysql)); } else {