diff --git a/Documentation/Getting-Started/Configuration-Guide.md b/Documentation/Getting-Started/Configuration-Guide.md index 6c6d0b16c..03a4b8ede 100644 --- a/Documentation/Getting-Started/Configuration-Guide.md +++ b/Documentation/Getting-Started/Configuration-Guide.md @@ -244,6 +244,15 @@ serverB | 15 | 27% serverC | 10 | 18% serverD | 20 | 36% +### `auth_all_servers` + +This parameter controls whether only a single server or all of the servers are used when loading the users from the backend servers. This takes a boolean value and when enabled, creates a union of all the users and grants on all the servers. + +### `strip_db_esc` + +The strip_db_esc parameter strips escape characters from database names of grants when loading the users from the backend server. Some visual database management tools automatically escape some characters and this might cause conflicts when MaxScale tries to authenticate users. + +This parameter takes a boolean value and when enabled, will strip all `\` characters from the database names. ## Server diff --git a/server/core/config.c b/server/core/config.c index d3c7e8a0c..43674075d 100644 --- a/server/core/config.c +++ b/server/core/config.c @@ -279,6 +279,7 @@ int error_count = 0; char *auth; char *enable_root_user; char *auth_all_servers; + char *strip_db_esc; char *weightby; char *version_string; bool is_rwsplit = false; @@ -294,6 +295,9 @@ int error_count = 0; auth_all_servers = config_get_value( obj->parameters, "auth_all_servers"); + strip_db_esc = config_get_value( + obj->parameters, + "strip_db_esc"); allow_localhost_match_wildcard_host = config_get_value(obj->parameters, "localhost_match_wildcard_host"); @@ -359,6 +363,9 @@ int error_count = 0; if(auth_all_servers) serviceAuthAllServers(obj->element, config_truth_value(auth_all_servers)); + if(strip_db_esc) + serviceStripDbEsc(obj->element, + config_truth_value(strip_db_esc)); if (weightby) serviceWeightBy(obj->element, weightby); @@ -1359,6 +1366,7 @@ SERVER *server; char *auth; char *enable_root_user; char* auth_all_servers; + char* strip_db_esc; char* max_slave_conn_str; char* max_slave_rlag_str; char *version_string; @@ -1372,7 +1380,7 @@ SERVER *server; "passwd"); auth_all_servers = config_get_value(obj->parameters, "auth_all_servers"); - + strip_db_esc = config_get_value(obj->parameters, "strip_db_esc"); version_string = config_get_value(obj->parameters, "version_string"); allow_localhost_match_wildcard_host = @@ -1396,6 +1404,8 @@ SERVER *server; serviceEnableRootUser(service, atoi(enable_root_user)); if(auth_all_servers) serviceAuthAllServers(service, atoi(auth_all_servers)); + if(strip_db_esc) + serviceStripDbEsc(service, atoi(strip_db_esc)); if (allow_localhost_match_wildcard_host) serviceEnableLocalhostMatchWildcardHost( service, @@ -1505,10 +1515,17 @@ SERVER *server; char *enable_root_user; char *allow_localhost_match_wildcard_host; char *auth_all_servers; - + char *strip_db_esc; enable_root_user = config_get_value(obj->parameters, "enable_root_user"); + + auth_all_servers = + config_get_value(obj->parameters, + "auth_all_servers"); + strip_db_esc = + config_get_value(obj->parameters, + "strip_db_esc"); allow_localhost_match_wildcard_host = config_get_value(obj->parameters, "localhost_match_wildcard_host"); @@ -1530,6 +1547,8 @@ SERVER *server; atoi(enable_root_user)); if(auth_all_servers) serviceAuthAllServers(obj->element, atoi(auth_all_servers)); + if(strip_db_esc) + serviceStripDbEsc(obj->element, atoi(strip_db_esc)); if (allow_localhost_match_wildcard_host) serviceEnableLocalhostMatchWildcardHost( @@ -1755,6 +1774,7 @@ static char *service_params[] = "passwd", "enable_root_user", "auth_all_servers", + "strip_db_esc", "localhost_match_wildcard_host", "max_slave_connections", "max_slave_replication_lag", diff --git a/server/core/dbusers.c b/server/core/dbusers.c index a8728d0f8..9f4528eb5 100644 --- a/server/core/dbusers.c +++ b/server/core/dbusers.c @@ -274,7 +274,7 @@ int add_mysql_users_with_host_ipv4(USERS *users, char *user, char *host, char *p } else { if (strcmp(anydb, "N") == 0) { if (db != NULL) - key.resource = strdup(db); + key.resource = strdup(db); else key.resource = NULL; } else { @@ -428,7 +428,7 @@ getDatabases(SERVICE *service, MYSQL *con) /* insert key and value "" */ while ((row = mysql_fetch_row(result))) { skygw_log_write(LOGFILE_DEBUG,"%s: Adding database %s to the resouce hash.",service->name,row[0]); - resource_add(service->resources, row[0], ""); + resource_add(service->resources, row[0], ""); } mysql_free_result(result); @@ -460,6 +460,7 @@ getUsers(SERVICE *service, USERS *users) 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 + @@ -796,8 +797,17 @@ getUsers(SERVICE *service, USERS *users) if (db_grants) { /* we have dbgrants, store them */ - rc = add_mysql_users_with_host_ipv4(users, row[0], row[1], password, row[4], row[5]); - skygw_log_write(LOGFILE_DEBUG,"%s: Adding user:%s host:%s anydb:%s db:%s.",service->name,row[0],row[1],row[4],row[5]); + if(row[5]){ + strcpy(dbnm,row[5]); + if(service->strip_db_esc) { + strip_escape_chars(dbnm); + } + } + else { + *dbnm = 0; + } + rc = add_mysql_users_with_host_ipv4(users, row[0], row[1], password, row[4], dbnm); + skygw_log_write(LOGFILE_DEBUG,"%s: Adding user:%s host:%s anydb:%s db:%s.",service->name,row[0],row[1],row[4],dbnm); } 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); diff --git a/server/core/service.c b/server/core/service.c index 967d1c53f..cc929ea90 100644 --- a/server/core/service.c +++ b/server/core/service.c @@ -822,6 +822,23 @@ serviceAuthAllServers(SERVICE *service, int action) return 1; } +/** + * Whether to strip escape characters from the name of the database the client + * is connecting to. + * @param service Service to configure + * @param action 0 for disabled, 1 for enabled + * @return 1 if successful, 0 on error + */ +int serviceStripDbEsc(SERVICE* service, int action) +{ + if (action != 0 && action != 1) + return 0; + + service->strip_db_esc = action; + + return 1; +} + /** * Trim whitespace from the from an rear of a string * diff --git a/server/include/service.h b/server/include/service.h index 497e6512f..8916a1529 100644 --- a/server/include/service.h +++ b/server/include/service.h @@ -137,6 +137,9 @@ typedef struct service { int svc_config_version; /*< Version number of configuration */ bool svc_do_shutdown; /*< tells the service to exit loops etc. */ bool users_from_all; /*< Load users from one server or all of them */ + bool strip_db_esc; /*< Remove the '\' characters from database names + * when querying them from the server. MySQL Workbench seems + * to escape at least the underscore character. */ SPINLOCK users_table_spin; /**< The spinlock for users data refresh */ SERVICE_REFRESH_RATE diff --git a/server/modules/routing/dbshard/dbshard.c b/server/modules/routing/dbshard/dbshard.c index a4473c733..7ac0a5fb5 100644 --- a/server/modules/routing/dbshard/dbshard.c +++ b/server/modules/routing/dbshard/dbshard.c @@ -2276,7 +2276,7 @@ static void clientReply ( } } - gwbuf_free(writebuf); + gwbuf_free(writebuf); if(mapped) { diff --git a/utils/skygw_utils.cc b/utils/skygw_utils.cc index 00b63b368..702832186 100644 --- a/utils/skygw_utils.cc +++ b/utils/skygw_utils.cc @@ -2083,4 +2083,32 @@ bool is_valid_posix_path(char* path) } } return true; +} + +/** + * Strip escape characters from a character string. + * @param String to parse. + * @return True if parsing was successful, false on errors. + */ +bool +strip_escape_chars (char* val) +{ + int cur, end; + + if (val == NULL) + return false; + + end = strlen (val) + 1; + cur = 0; + + while (cur < end) + { + if (val[cur] == '\\') + { + memmove (val + cur, val + cur + 1,end - cur - 1); + end--; + } + cur++; + } + return true; } \ No newline at end of file diff --git a/utils/skygw_utils.h b/utils/skygw_utils.h index cd3793048..7de3d12ba 100644 --- a/utils/skygw_utils.h +++ b/utils/skygw_utils.h @@ -199,6 +199,7 @@ char* replace_literal(char* haystack, const char* needle, const char* replacement); bool is_valid_posix_path(char* path); +bool strip_escape_chars(char*); EXTERN_C_BLOCK_END #endif /* SKYGW_UTILS_H */