Fix to MXS-417: https://mariadb.atlassian.net/browse/MXS-417 Added support for single-character wildcard in IP addresses.
Single character wildcard addresses are now properly handled
This commit is contained in:
@ -137,6 +137,27 @@ int add_wildcard_users(USERS *users,
|
|||||||
|
|
||||||
static int gw_mysql_set_timeouts(MYSQL* handle);
|
static int gw_mysql_set_timeouts(MYSQL* handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the IP address of the user matches the one in the grant. This assumes
|
||||||
|
* that the grant has one or more single-character wildcards in it.
|
||||||
|
* @param userhost User host address
|
||||||
|
* @param wildcardhost Host address in the grant
|
||||||
|
* @return True if the host address matches
|
||||||
|
*/
|
||||||
|
bool host_matches_singlechar_wildcard(const char* user, const char* wild)
|
||||||
|
{
|
||||||
|
while (*user != '\0' && *wild != '\0')
|
||||||
|
{
|
||||||
|
if (*user != *wild && *wild != '_')
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
user++;
|
||||||
|
wild++;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the user/passwd form mysql.user table into the service users' hashtable
|
* Load the user/passwd form mysql.user table into the service users' hashtable
|
||||||
* environment.
|
* environment.
|
||||||
@ -252,6 +273,53 @@ HASHTABLE *oldresources;
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the IP address is a valid MySQL IP address. The IP address can contain
|
||||||
|
* single or multi-character wildcards as used by MySQL.
|
||||||
|
* @param host IP address to check
|
||||||
|
* @return True if the address is a valid, MySQL type IP address
|
||||||
|
*/
|
||||||
|
bool is_ipaddress(const char* host)
|
||||||
|
{
|
||||||
|
while (*host != '\0')
|
||||||
|
{
|
||||||
|
if (!isdigit(*host) && *host != '.' && *host != '_' && *host != '%')
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
host++;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if an IP address has single-character wildcards. A single-character
|
||||||
|
* wildcard is represented by an underscore in the MySQL hostnames.
|
||||||
|
* @param host Hostname to check
|
||||||
|
* @return True if the hostname is a valid IP address with a single character wildcard
|
||||||
|
*/
|
||||||
|
bool host_has_singlechar_wildcard(const char *host)
|
||||||
|
{
|
||||||
|
const char* chrptr = host;
|
||||||
|
bool retval = false;
|
||||||
|
|
||||||
|
while (*chrptr != '\0')
|
||||||
|
{
|
||||||
|
if (!isdigit(*chrptr) && *chrptr != '.')
|
||||||
|
{
|
||||||
|
if (*chrptr == '_')
|
||||||
|
{
|
||||||
|
retval = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chrptr++;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new MySQL user with host, password and netmask into the service users table
|
* Add a new MySQL user with host, password and netmask into the service users table
|
||||||
@ -308,6 +376,12 @@ int add_mysql_users_with_host_ipv4(USERS *users, char *user, char *host, char *p
|
|||||||
if (strcmp(host, "%") == 0) {
|
if (strcmp(host, "%") == 0) {
|
||||||
strcpy(ret_ip, "0.0.0.0");
|
strcpy(ret_ip, "0.0.0.0");
|
||||||
key.netmask = 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 {
|
} else {
|
||||||
/* hostname without % wildcards has netmask = 32 */
|
/* hostname without % wildcards has netmask = 32 */
|
||||||
key.netmask = normalize_hostname(host, ret_ip);
|
key.netmask = normalize_hostname(host, ret_ip);
|
||||||
@ -1719,7 +1793,17 @@ static int uh_cmpfun( void* v1, void* v2) {
|
|||||||
if (hu1->user == NULL || hu2->user == NULL)
|
if (hu1->user == NULL || hu2->user == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (strcmp(hu1->user, hu2->user) == 0 && (hu1->ipv4.sin_addr.s_addr == hu2->ipv4.sin_addr.s_addr) && (hu1->netmask >= hu2->netmask)) {
|
/** 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
|
||||||
|
* address contains wildcards and if the user's address matches that. */
|
||||||
|
|
||||||
|
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 no database name was passed, auth is ok */
|
/* if no database name was passed, auth is ok */
|
||||||
if (hu1->resource == NULL || (hu1->resource && !strlen(hu1->resource))) {
|
if (hu1->resource == NULL || (hu1->resource && !strlen(hu1->resource))) {
|
||||||
@ -1806,6 +1890,10 @@ static void *uh_keydup(void* key) {
|
|||||||
return NULL;
|
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->ipv4, ¤t_key->ipv4, sizeof(struct sockaddr_in));
|
||||||
memcpy(&rval->netmask, ¤t_key->netmask, sizeof(int));
|
memcpy(&rval->netmask, ¤t_key->netmask, sizeof(int));
|
||||||
|
|
||||||
|
@ -62,6 +62,7 @@ typedef struct mysql_user_host_key {
|
|||||||
struct sockaddr_in ipv4;
|
struct sockaddr_in ipv4;
|
||||||
int netmask;
|
int netmask;
|
||||||
char *resource;
|
char *resource;
|
||||||
|
char hostname[MYSQL_HOST_MAXLEN + 1];
|
||||||
} MYSQL_USER_HOST;
|
} MYSQL_USER_HOST;
|
||||||
|
|
||||||
extern int load_mysql_users(SERVICE *service);
|
extern int load_mysql_users(SERVICE *service);
|
||||||
|
@ -1463,6 +1463,10 @@ int gw_find_mysql_user_password_sha1(char *username, uint8_t *gateway_password,
|
|||||||
memcpy(&key.ipv4, client, sizeof(struct sockaddr_in));
|
memcpy(&key.ipv4, client, sizeof(struct sockaddr_in));
|
||||||
key.netmask = 32;
|
key.netmask = 32;
|
||||||
key.resource = client_data->db;
|
key.resource = client_data->db;
|
||||||
|
if(strlen(dcb->remote) < MYSQL_HOST_MAXLEN)
|
||||||
|
{
|
||||||
|
strcpy(key.hostname, dcb->remote);
|
||||||
|
}
|
||||||
|
|
||||||
LOGIF(LD,
|
LOGIF(LD,
|
||||||
(skygw_log_write_flush(
|
(skygw_log_write_flush(
|
||||||
|
Reference in New Issue
Block a user