mirror of
https://github.com/MariaDB/server.git
synced 2025-01-18 04:53:01 +01:00
Changed acl_roles to be stored into a HASH.
There is an issue with correct searching of keys in the HASH.
This commit is contained in:
parent
334860cccf
commit
e0c908ebe7
1 changed files with 71 additions and 27 deletions
|
@ -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,
|
||||||
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,
|
||||||
#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;
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
/* 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)
|
||||||
}
|
}
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
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,
|
||||||
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);
|
DBUG_ENTER("find_acl_role");
|
||||||
}
|
DBUG_PRINT("enter",("user: '%s'", user));
|
||||||
static ACL_USER *
|
|
||||||
find_acl_user(const char *host, const char *user, my_bool exact)
|
mysql_mutex_assert_owner(&acl_cache->lock);
|
||||||
{
|
|
||||||
return find_acl_user_table_entry(host, user, exact, FALSE);
|
DBUG_RETURN((ACL_USER *)my_hash_search(&acl_roles, (uchar *)user,
|
||||||
|
user ? strlen(user) : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Comparing of hostnames
|
Comparing of hostnames
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue