Commit e0c908eb authored by Vicențiu Ciorbaru's avatar Vicențiu Ciorbaru Committed by Sergei Golubchik

Changed acl_roles to be stored into a HASH.

There is an issue with correct searching of keys in the HASH.
parent 334860cc
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
#include "hostname.h" #include "hostname.h"
#include "sql_db.h" #include "sql_db.h"
#include "sql_array.h" #include "sql_array.h"
#include "sql_hset.h"
#include "sql_plugin_compat.h" #include "sql_plugin_compat.h"
...@@ -520,6 +521,13 @@ static uchar* acl_entry_get_key(acl_entry *entry, size_t *length, ...@@ -520,6 +521,13 @@ static uchar* acl_entry_get_key(acl_entry *entry, size_t *length,
return (uchar*) entry->key; return (uchar*) entry->key;
} }
uchar* acl_role_get_key(ACL_USER *entry, size_t *length,
my_bool not_used __attribute__((unused)))
{
*length=(uint) (entry->user ? strlen(entry->user) : 0);
return (uchar*) entry->user;
}
#define IP_ADDR_STRLEN (3 + 1 + 3 + 1 + 3 + 1 + 3) #define IP_ADDR_STRLEN (3 + 1 + 3 + 1 + 3 + 1 + 3)
#define ACL_KEY_LENGTH (IP_ADDR_STRLEN + 1 + NAME_LEN + \ #define ACL_KEY_LENGTH (IP_ADDR_STRLEN + 1 + NAME_LEN + \
1 + USERNAME_LENGTH + 1) 1 + USERNAME_LENGTH + 1)
...@@ -542,7 +550,10 @@ static uchar* acl_entry_get_key(acl_entry *entry, size_t *length, ...@@ -542,7 +550,10 @@ static uchar* acl_entry_get_key(acl_entry *entry, size_t *length,
#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */ #endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
#define NORMAL_HANDSHAKE_SIZE 6 #define NORMAL_HANDSHAKE_SIZE 6
static DYNAMIC_ARRAY acl_hosts, acl_users, acl_dbs, acl_proxy_users, acl_roles; #define ROLE_ASSIGN_COLUMN_IDX 42
static DYNAMIC_ARRAY acl_hosts, acl_users, acl_dbs, acl_proxy_users;
static HASH acl_roles;
/* XXX /* XXX
***** Potential optimization ***** ***** Potential optimization *****
role_grants could potentially be a HASH with keys as usernames and values role_grants could potentially be a HASH with keys as usernames and values
...@@ -560,14 +571,14 @@ static DYNAMIC_ARRAY acl_wild_hosts; ...@@ -560,14 +571,14 @@ static DYNAMIC_ARRAY acl_wild_hosts;
static hash_filo *acl_cache; static hash_filo *acl_cache;
static uint grant_version=0; /* Version of priv tables. incremented by acl_load */ static uint grant_version=0; /* Version of priv tables. incremented by acl_load */
static ulong get_access(TABLE *form,uint fieldnr, uint *next_field=0); static ulong get_access(TABLE *form,uint fieldnr, uint *next_field=0);
static bool check_is_role(TABLE *form);
static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b); static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b);
static ulong get_sort(uint count,...); static ulong get_sort(uint count,...);
static void init_check_host(void); static void init_check_host(void);
static void rebuild_check_host(void); static void rebuild_check_host(void);
static ACL_USER *find_acl_user(const char *host, const char *user, static ACL_USER *find_acl_user(const char *host, const char *user,
my_bool exact); my_bool exact);
static ACL_USER *find_acl_role(const char *host, const char *user, static ACL_USER *find_acl_role(const char *user);
my_bool exact);
static bool update_user_table(THD *thd, TABLE *table, const char *host, static bool update_user_table(THD *thd, TABLE *table, const char *host,
const char *user, const char *new_password, const char *user, const char *new_password,
uint new_password_len); uint new_password_len);
...@@ -847,7 +858,9 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) ...@@ -847,7 +858,9 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
table->use_all_columns(); table->use_all_columns();
(void) my_init_dynamic_array(&acl_users,sizeof(ACL_USER), 50, 100, MYF(0)); (void) my_init_dynamic_array(&acl_users,sizeof(ACL_USER), 50, 100, MYF(0));
(void) my_init_dynamic_array(&acl_roles,sizeof(ACL_USER), 50, 100, MYF(0)); (void) my_hash_init2(&acl_roles,50,system_charset_info,
0,0,0, (my_hash_get_key) acl_role_get_key, 0,0);
username_char_length= min(table->field[1]->char_length(), USERNAME_CHAR_LENGTH); username_char_length= min(table->field[1]->char_length(), USERNAME_CHAR_LENGTH);
password_length= table->field[2]->field_length / password_length= table->field[2]->field_length /
table->field[2]->charset()->mbmaxlen; table->field[2]->charset()->mbmaxlen;
...@@ -902,9 +915,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) ...@@ -902,9 +915,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
/* If the user entry is a role, skip password and hostname checks /* If the user entry is a role, skip password and hostname checks
A user can not log in with a role so some checks are not necessary A user can not log in with a role so some checks are not necessary
*/ */
if (!user.host.hostname) { is_role= check_is_role(table);
is_role= TRUE;
}
if (!is_role && check_no_resolve && if (!is_role && check_no_resolve &&
hostname_requires_resolving(user.host.hostname)) hostname_requires_resolving(user.host.hostname))
...@@ -1046,7 +1057,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) ...@@ -1046,7 +1057,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
} }
if (is_role) { if (is_role) {
sql_print_information("Found role %s", user.user); sql_print_information("Found role %s", user.user);
(void) push_dynamic(&acl_roles,(uchar*) &user); my_hash_insert(&acl_roles, (uchar*) &user);
} }
else else
{ {
...@@ -1169,7 +1180,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) ...@@ -1169,7 +1180,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
table->use_all_columns(); table->use_all_columns();
/* account for every role mapping */ /* account for every role mapping */
/* acquire lock for the find_acl_user/role functions /* acquire lock for the find_acl_user functions
XXX XXX
Perhaps new wrapper functions should be created that do not check Perhaps new wrapper functions should be created that do not check
for the lock in this case as it either is already taken or for the lock in this case as it either is already taken or
...@@ -1186,12 +1197,10 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) ...@@ -1186,12 +1197,10 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
p.user_username= get_field(&mem, table->field[1]); p.user_username= get_field(&mem, table->field[1]);
p.role_hostname= get_field(&mem, table->field[2]); p.role_hostname= get_field(&mem, table->field[2]);
p.role_username= get_field(&mem, table->field[3]); p.role_username= get_field(&mem, table->field[3]);
ACL_USER *user = find_acl_user((p.user_hostname) ? p.user_hostname: "", ACL_USER *user= find_acl_user((p.user_hostname) ? p.user_hostname: "",
(p.user_username) ? p.user_username: "", (p.user_username) ? p.user_username: "",
TRUE); TRUE);
ACL_USER *role = find_acl_role((p.role_hostname) ? p.role_hostname: "", ACL_USER *role= find_acl_role(p.role_username ? p.role_username: "");
(p.role_username) ? p.role_username: "",
TRUE);
if (user == NULL || role == NULL) if (user == NULL || role == NULL)
{ {
sql_print_error("Invalid roles_mapping table entry '%s@%s', '%s@%s'", sql_print_error("Invalid roles_mapping table entry '%s@%s', '%s@%s'",
...@@ -1397,6 +1406,38 @@ static ulong get_access(TABLE *form, uint fieldnr, uint *next_field) ...@@ -1397,6 +1406,38 @@ static ulong get_access(TABLE *form, uint fieldnr, uint *next_field)
return access_bits; return access_bits;
} }
/*
Check if a user entry in the user table is marked as being a role entry
IMPLEMENTATION
Access the coresponding column and check the coresponding ENUM of the form
ENUM('N', 'Y')
SYNOPSIS
check_is_role()
form an open table to read the entry from.
The record should be already read in table->record[0]
RETURN VALUE
TRUE if the user is marked as a role
FALSE otherwise
*/
static inline bool check_is_role(TABLE *form)
{
char buff[2];
String res(buff, sizeof(buff), &my_charset_latin1);
/* Table version does not support roles */
if (form->s->fields <= 42)
return FALSE;
form->field[ROLE_ASSIGN_COLUMN_IDX]->val_str(&res);
if (my_toupper(&my_charset_latin1, res[0]) == 'Y')
return TRUE;
return FALSE;
}
/* /*
Return a number which, if sorted 'desc', puts strings in this order: Return a number which, if sorted 'desc', puts strings in this order:
...@@ -2138,22 +2179,19 @@ bool is_acl_user(const char *host, const char *user) ...@@ -2138,22 +2179,19 @@ bool is_acl_user(const char *host, const char *user)
/* /*
Find first entry that matches the current user or role Find first entry that matches the current user
*/ */
static ACL_USER * static ACL_USER *
find_acl_user_table_entry(const char *host, const char *user, my_bool exact, find_acl_user(const char *host, const char *user, my_bool exact)
my_bool is_role)
{ {
DBUG_ENTER("find_acl_user"); DBUG_ENTER("find_acl_user");
DBUG_PRINT("enter",("host: '%s' user: '%s'",host,user)); DBUG_PRINT("enter",("host: '%s' user: '%s'",host,user));
mysql_mutex_assert_owner(&acl_cache->lock); mysql_mutex_assert_owner(&acl_cache->lock);
DYNAMIC_ARRAY *target = (is_role) ? &acl_roles : &acl_users; for (uint i=0 ; i < acl_users.elements ; i++)
for (uint i=0 ; i < target->elements ; i++)
{ {
ACL_USER *acl_user=dynamic_element(target,i,ACL_USER*); ACL_USER *acl_user=dynamic_element(&acl_users,i,ACL_USER*);
DBUG_PRINT("info",("strcmp('%s','%s'), compare_hostname('%s','%s'),", DBUG_PRINT("info",("strcmp('%s','%s'), compare_hostname('%s','%s'),",
user, acl_user->user ? acl_user->user : "", user, acl_user->user ? acl_user->user : "",
host, host,
...@@ -2174,18 +2212,24 @@ find_acl_user_table_entry(const char *host, const char *user, my_bool exact, ...@@ -2174,18 +2212,24 @@ find_acl_user_table_entry(const char *host, const char *user, my_bool exact,
DBUG_RETURN(0); DBUG_RETURN(0);
} }
/*
Find first entry that matches the current user
*/
static ACL_USER * static ACL_USER *
find_acl_role(const char *host, const char *user, my_bool exact) find_acl_role(const char *user)
{
return find_acl_user_table_entry(host, user, exact, TRUE);
}
static ACL_USER *
find_acl_user(const char *host, const char *user, my_bool exact)
{ {
return find_acl_user_table_entry(host, user, exact, FALSE); DBUG_ENTER("find_acl_role");
DBUG_PRINT("enter",("user: '%s'", user));
mysql_mutex_assert_owner(&acl_cache->lock);
DBUG_RETURN((ACL_USER *)my_hash_search(&acl_roles, (uchar *)user,
user ? strlen(user) : 0));
} }
/* /*
Comparing of hostnames Comparing of hostnames
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment