Implemented Roles Mappings association between users and roles.
No more memory leaks in the code.
This commit is contained in:
parent
deffce1ace
commit
887a1ac862
174
sql/sql_acl.cc
174
sql/sql_acl.cc
@ -250,7 +250,7 @@ public:
|
|||||||
dst->plugin.str= strmake_root(root, plugin.str, plugin.length);
|
dst->plugin.str= strmake_root(root, plugin.str, plugin.length);
|
||||||
dst->auth_string.str= safe_strdup_root(root, auth_string.str);
|
dst->auth_string.str= safe_strdup_root(root, auth_string.str);
|
||||||
dst->host.hostname= safe_strdup_root(root, host.hostname);
|
dst->host.hostname= safe_strdup_root(root, host.hostname);
|
||||||
dst->role_grants= this->role_grants;
|
bzero(&dst->role_grants, sizeof(role_grants));
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -262,7 +262,6 @@ public:
|
|||||||
char *user,*db;
|
char *user,*db;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
static void update_hostname(acl_host_and_ip *host, const char *hostname);
|
static void update_hostname(acl_host_and_ip *host, const char *hostname);
|
||||||
static ulong get_sort(uint count,...);
|
static ulong get_sort(uint count,...);
|
||||||
@ -528,13 +527,29 @@ 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,
|
static uchar* acl_role_get_key(ACL_USER *entry, size_t *length,
|
||||||
my_bool not_used __attribute__((unused)))
|
my_bool not_used __attribute__((unused)))
|
||||||
{
|
{
|
||||||
*length=(uint) entry->user.length;
|
*length=(uint) entry->user.length;
|
||||||
return (uchar*) entry->user.str;
|
return (uchar*) entry->user.str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct st_role_grant
|
||||||
|
{
|
||||||
|
char *u_uname;
|
||||||
|
char *u_hname;
|
||||||
|
char *r_uname;
|
||||||
|
char *r_hname;
|
||||||
|
LEX_STRING hashkey;
|
||||||
|
} ROLE_GRANT_PAIR;
|
||||||
|
|
||||||
|
static uchar* acl_role_map_get_key(ROLE_GRANT_PAIR *entry, size_t *length,
|
||||||
|
my_bool not_used __attribute__((unused)))
|
||||||
|
{
|
||||||
|
*length=(uint) entry->hashkey.length;
|
||||||
|
return (uchar*) entry->hashkey.str;
|
||||||
|
}
|
||||||
|
|
||||||
#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)
|
||||||
@ -561,6 +576,13 @@ uchar* acl_role_get_key(ACL_USER *entry, size_t *length,
|
|||||||
|
|
||||||
static DYNAMIC_ARRAY acl_hosts, acl_users, acl_dbs, acl_proxy_users;
|
static DYNAMIC_ARRAY acl_hosts, acl_users, acl_dbs, acl_proxy_users;
|
||||||
static HASH acl_roles;
|
static HASH acl_roles;
|
||||||
|
/*
|
||||||
|
An hash containing mappings user <--> role
|
||||||
|
|
||||||
|
A hash is used so as to make updates quickly
|
||||||
|
The hashkey used represents all the entries combined
|
||||||
|
*/
|
||||||
|
static HASH acl_roles_mappings;
|
||||||
static MEM_ROOT mem, memex;
|
static MEM_ROOT mem, memex;
|
||||||
static bool initialized=0;
|
static bool initialized=0;
|
||||||
static bool allow_all_hosts=1;
|
static bool allow_all_hosts=1;
|
||||||
@ -584,6 +606,11 @@ static bool update_user_table(THD *thd, TABLE *table, const char *host,
|
|||||||
static my_bool acl_load(THD *thd, TABLE_LIST *tables);
|
static my_bool acl_load(THD *thd, TABLE_LIST *tables);
|
||||||
static my_bool grant_load(THD *thd, TABLE_LIST *tables);
|
static my_bool grant_load(THD *thd, TABLE_LIST *tables);
|
||||||
static inline void get_grantor(THD *thd, char* grantor);
|
static inline void get_grantor(THD *thd, char* grantor);
|
||||||
|
static my_bool acl_user_reset_grant(ACL_USER *user,
|
||||||
|
void * not_used __attribute__((unused)));
|
||||||
|
static my_bool add_role_user_mapping(ROLE_GRANT_PAIR *entry,
|
||||||
|
void * not_used __attribute__((unused)));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Enumeration of various ACL's and Hashes used in handle_grant_struct()
|
Enumeration of various ACL's and Hashes used in handle_grant_struct()
|
||||||
*/
|
*/
|
||||||
@ -597,12 +624,6 @@ enum enum_acl_lists
|
|||||||
PROXY_USERS_ACL
|
PROXY_USERS_ACL
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct st_role_grant
|
|
||||||
{
|
|
||||||
char *username;
|
|
||||||
char *hostname;
|
|
||||||
} ROLE_GRANT_PAIR;
|
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
free_acl_user(ACL_USER *user)
|
free_acl_user(ACL_USER *user)
|
||||||
@ -863,7 +884,8 @@ 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_hash_init2(&acl_roles,50,system_charset_info,
|
(void) my_hash_init2(&acl_roles,50,system_charset_info,
|
||||||
0,0,0, (my_hash_get_key) acl_role_get_key, 0,0);
|
0,0,0, (my_hash_get_key) acl_role_get_key,
|
||||||
|
(void (*)(void *))free_acl_user, 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 /
|
||||||
@ -1062,17 +1084,23 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) my_init_dynamic_array(&user.role_grants,sizeof(ROLE_GRANT_PAIR),
|
(void) my_init_dynamic_array(&user.role_grants,sizeof(ACL_USER *),
|
||||||
50, 100, MYF(0));
|
50, 100, MYF(0));
|
||||||
|
|
||||||
if (is_role) {
|
if (is_role) {
|
||||||
sql_print_information("Found role %s", user.user.str);
|
DBUG_PRINT("info", ("Found role %s", user.user.str));
|
||||||
my_hash_insert(&acl_roles, (uchar*) user.copy(&mem));
|
ACL_USER *entry= user.copy(&mem);
|
||||||
|
entry->role_grants = user.role_grants;
|
||||||
|
my_hash_insert(&acl_roles, (uchar *)entry);
|
||||||
|
HASH_SEARCH_STATE t;
|
||||||
|
entry= (ACL_USER *) my_hash_first(&acl_roles,
|
||||||
|
(uchar *)entry->user.str, entry->user.length, &t);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sql_print_information("Found user %s", user.user.str);
|
DBUG_PRINT("info", ("Found user %s", user.user.str));
|
||||||
(void) push_dynamic(&acl_users,(uchar*) &user);
|
(void) push_dynamic(&acl_users,(uchar*) &user);
|
||||||
}
|
}
|
||||||
if (!user.host.hostname ||
|
if (!user.host.hostname ||
|
||||||
@ -1200,34 +1228,42 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
|
|||||||
if (!initialized)
|
if (!initialized)
|
||||||
mysql_mutex_lock(&acl_cache->lock);
|
mysql_mutex_lock(&acl_cache->lock);
|
||||||
|
|
||||||
|
(void) my_hash_init2(&acl_roles_mappings,50,system_charset_info,
|
||||||
|
0,0,0, (my_hash_get_key) acl_role_map_get_key, 0,0);
|
||||||
while (!(read_record_info.read_record(&read_record_info)))
|
while (!(read_record_info.read_record(&read_record_info)))
|
||||||
{
|
{
|
||||||
ROLE_GRANT_PAIR role_ref;
|
ROLE_GRANT_PAIR *mapping = (ROLE_GRANT_PAIR *)alloc_root(
|
||||||
ROLE_GRANT_PAIR user_ref;
|
&mem,
|
||||||
user_ref.hostname= get_field(&mem, table->field[0]);
|
sizeof(ROLE_GRANT_PAIR));
|
||||||
user_ref.username= get_field(&mem, table->field[1]);
|
mapping->u_hname= get_field(&mem, table->field[0]);
|
||||||
role_ref.hostname= get_field(&mem, table->field[2]);
|
mapping->u_uname= get_field(&mem, table->field[1]);
|
||||||
role_ref.username= get_field(&mem, table->field[3]);
|
mapping->r_hname= get_field(&mem, table->field[2]);
|
||||||
ACL_USER *user= find_acl_user((user_ref.hostname) ? user_ref.hostname: "",
|
mapping->r_uname= get_field(&mem, table->field[3]);
|
||||||
(user_ref.username) ? user_ref.username: "",
|
|
||||||
TRUE);
|
size_t len[4] = {mapping->u_hname ? strlen(mapping->u_hname) : 0,
|
||||||
ACL_USER *role= find_acl_role(role_ref.username ? role_ref.username: "");
|
mapping->u_uname ? strlen(mapping->u_uname) : 0,
|
||||||
if (user == NULL || role == NULL)
|
mapping->r_hname ? strlen(mapping->r_hname) : 0,
|
||||||
{
|
mapping->r_uname ? strlen(mapping->r_uname) : 0};
|
||||||
|
char *buff= (char *)alloc_root(&mem, len[0] + len[1] + len[2] + len[3] + 1);
|
||||||
|
memcpy(buff, mapping->u_hname, len[0]);
|
||||||
|
memcpy(buff + len[0], mapping->u_uname, len[1]);
|
||||||
|
memcpy(buff + len[0] + len[1], mapping->r_hname, len[2]);
|
||||||
|
memcpy(buff + len[0] + len[1] + len[2], mapping->r_uname, len[3]);
|
||||||
|
buff[len[0] + len[1] + len[2] + len[3]] = '\0';
|
||||||
|
mapping->hashkey.str = buff;
|
||||||
|
mapping->hashkey.length = len[0] + len[1] + len[2] + len[3];
|
||||||
|
|
||||||
|
if (add_role_user_mapping(mapping, NULL) == 1) {
|
||||||
sql_print_error("Invalid roles_mapping table entry '%s@%s', '%s@%s'",
|
sql_print_error("Invalid roles_mapping table entry '%s@%s', '%s@%s'",
|
||||||
user_ref.username ? user_ref.username : "",
|
mapping->u_uname ? mapping->u_uname : "",
|
||||||
user_ref.hostname ? user_ref.hostname : "",
|
mapping->u_hname ? mapping->u_hname : "",
|
||||||
role_ref.username ? role_ref.username : "",
|
mapping->r_uname ? mapping->r_uname : "",
|
||||||
role_ref.hostname ? role_ref.hostname : "",
|
mapping->r_hname ? mapping->r_hname : "");
|
||||||
user, role);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
push_dynamic(&user->role_grants, (uchar*) &role_ref);
|
my_hash_insert(&acl_roles_mappings, (uchar*) mapping);
|
||||||
push_dynamic(&role->role_grants, (uchar*) &user_ref);
|
|
||||||
sql_print_information("Found user %s@%s having role granted %s@%s\n",
|
|
||||||
user->user.str, user->host.hostname,
|
|
||||||
role->user.str, role->host.hostname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
end_read_record(&read_record_info);
|
end_read_record(&read_record_info);
|
||||||
@ -1250,14 +1286,15 @@ end:
|
|||||||
|
|
||||||
void acl_free(bool end)
|
void acl_free(bool end)
|
||||||
{
|
{
|
||||||
|
my_hash_free(&acl_roles);
|
||||||
free_root(&mem,MYF(0));
|
free_root(&mem,MYF(0));
|
||||||
delete_dynamic(&acl_hosts);
|
delete_dynamic(&acl_hosts);
|
||||||
delete_dynamic_recursive(&acl_users, (FREE_FUNC)free_acl_user);
|
delete_dynamic_recursive(&acl_users, (FREE_FUNC) free_acl_user);
|
||||||
delete_dynamic(&acl_dbs);
|
delete_dynamic(&acl_dbs);
|
||||||
delete_dynamic(&acl_wild_hosts);
|
delete_dynamic(&acl_wild_hosts);
|
||||||
delete_dynamic(&acl_proxy_users);
|
delete_dynamic(&acl_proxy_users);
|
||||||
my_hash_free(&acl_roles);
|
|
||||||
my_hash_free(&acl_check_hosts);
|
my_hash_free(&acl_check_hosts);
|
||||||
|
my_hash_free(&acl_roles_mappings);
|
||||||
plugin_unlock(0, native_password_plugin);
|
plugin_unlock(0, native_password_plugin);
|
||||||
plugin_unlock(0, old_password_plugin);
|
plugin_unlock(0, old_password_plugin);
|
||||||
if (!end)
|
if (!end)
|
||||||
@ -1293,7 +1330,7 @@ my_bool acl_reload(THD *thd)
|
|||||||
{
|
{
|
||||||
TABLE_LIST tables[5];
|
TABLE_LIST tables[5];
|
||||||
DYNAMIC_ARRAY old_acl_hosts, old_acl_users, old_acl_dbs, old_acl_proxy_users;
|
DYNAMIC_ARRAY old_acl_hosts, old_acl_users, old_acl_dbs, old_acl_proxy_users;
|
||||||
HASH old_acl_roles;
|
HASH old_acl_roles, old_acl_roles_mappings;
|
||||||
MEM_ROOT old_mem;
|
MEM_ROOT old_mem;
|
||||||
bool old_initialized;
|
bool old_initialized;
|
||||||
my_bool return_val= TRUE;
|
my_bool return_val= TRUE;
|
||||||
@ -1350,6 +1387,7 @@ my_bool acl_reload(THD *thd)
|
|||||||
old_acl_hosts= acl_hosts;
|
old_acl_hosts= acl_hosts;
|
||||||
old_acl_users= acl_users;
|
old_acl_users= acl_users;
|
||||||
old_acl_roles= acl_roles;
|
old_acl_roles= acl_roles;
|
||||||
|
old_acl_roles_mappings= acl_roles_mappings;
|
||||||
old_acl_proxy_users= acl_proxy_users;
|
old_acl_proxy_users= acl_proxy_users;
|
||||||
old_acl_dbs= acl_dbs;
|
old_acl_dbs= acl_dbs;
|
||||||
old_mem= mem;
|
old_mem= mem;
|
||||||
@ -1363,6 +1401,7 @@ my_bool acl_reload(THD *thd)
|
|||||||
acl_hosts= old_acl_hosts;
|
acl_hosts= old_acl_hosts;
|
||||||
acl_users= old_acl_users;
|
acl_users= old_acl_users;
|
||||||
acl_roles= old_acl_roles;
|
acl_roles= old_acl_roles;
|
||||||
|
acl_roles_mappings= old_acl_roles_mappings;
|
||||||
acl_proxy_users= old_acl_proxy_users;
|
acl_proxy_users= old_acl_proxy_users;
|
||||||
acl_dbs= old_acl_dbs;
|
acl_dbs= old_acl_dbs;
|
||||||
mem= old_mem;
|
mem= old_mem;
|
||||||
@ -1370,12 +1409,14 @@ my_bool acl_reload(THD *thd)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
my_hash_free(&old_acl_roles);
|
||||||
free_root(&old_mem,MYF(0));
|
free_root(&old_mem,MYF(0));
|
||||||
delete_dynamic(&old_acl_hosts);
|
delete_dynamic(&old_acl_hosts);
|
||||||
delete_dynamic_recursive(&old_acl_users, (FREE_FUNC) free_acl_user);
|
delete_dynamic_recursive(&old_acl_users, (FREE_FUNC) free_acl_user);
|
||||||
delete_dynamic(&old_acl_proxy_users);
|
delete_dynamic(&old_acl_proxy_users);
|
||||||
delete_dynamic(&old_acl_dbs);
|
delete_dynamic(&old_acl_dbs);
|
||||||
my_hash_free(&old_acl_roles);
|
my_hash_free(&old_acl_roles_mappings);
|
||||||
|
my_hash_free(&old_acl_roles_mappings);
|
||||||
}
|
}
|
||||||
if (old_initialized)
|
if (old_initialized)
|
||||||
mysql_mutex_unlock(&acl_cache->lock);
|
mysql_mutex_unlock(&acl_cache->lock);
|
||||||
@ -1916,8 +1957,7 @@ static void init_check_host(void)
|
|||||||
acl_users.elements, 1, MYF(0));
|
acl_users.elements, 1, MYF(0));
|
||||||
(void) my_hash_init(&acl_check_hosts,system_charset_info,
|
(void) my_hash_init(&acl_check_hosts,system_charset_info,
|
||||||
acl_users.elements, 0, 0,
|
acl_users.elements, 0, 0,
|
||||||
(my_hash_get_key) check_get_key,
|
(my_hash_get_key) check_get_key, 0, 0);
|
||||||
(void (*)(void *))free_acl_user, 0);
|
|
||||||
if (!allow_all_hosts)
|
if (!allow_all_hosts)
|
||||||
{
|
{
|
||||||
for (uint i=0 ; i < acl_users.elements ; i++)
|
for (uint i=0 ; i < acl_users.elements ; i++)
|
||||||
@ -1972,7 +2012,55 @@ void rebuild_check_host(void)
|
|||||||
init_check_host();
|
init_check_host();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Rebuild the role grants every time the acl_users is modified
|
||||||
|
|
||||||
|
The role grants in the ACL_USER class need to be rebuilt, as they contain
|
||||||
|
pointers to elements of the acl_users array.
|
||||||
|
*/
|
||||||
|
|
||||||
|
my_bool acl_user_reset_grant(ACL_USER *user,
|
||||||
|
void * not_used __attribute__((unused)))
|
||||||
|
{
|
||||||
|
reset_dynamic(&user->role_grants);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
my_bool add_role_user_mapping(ROLE_GRANT_PAIR *mapping,
|
||||||
|
void * not_used __attribute__((unused)))
|
||||||
|
{
|
||||||
|
ACL_USER *user= find_acl_user((mapping->u_hname) ? mapping->u_hname: "",
|
||||||
|
(mapping->u_uname) ? mapping->u_uname: "",
|
||||||
|
TRUE);
|
||||||
|
ACL_USER *role= find_acl_role(mapping->r_uname ? mapping->r_uname: "");
|
||||||
|
if (user == NULL || role == NULL)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
push_dynamic(&user->role_grants, (uchar*) role);
|
||||||
|
push_dynamic(&role->role_grants, (uchar*) user);
|
||||||
|
|
||||||
|
DBUG_PRINT("info", ("Found user %s@%s having role granted %s@%s\n",
|
||||||
|
user->user.str, user->host.hostname,
|
||||||
|
role->user.str, role->host.hostname));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void rebuild_role_grants(void)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Reset every user's and role's role_grants array
|
||||||
|
*/
|
||||||
|
for (uint i=0; i < acl_users.elements; i++) {
|
||||||
|
ACL_USER * user = dynamic_element(&acl_users, i, ACL_USER *);
|
||||||
|
reset_dynamic(&user->role_grants);
|
||||||
|
}
|
||||||
|
my_hash_iterate(&acl_roles,
|
||||||
|
(my_hash_walk_action) acl_user_reset_grant, NULL);
|
||||||
|
|
||||||
|
my_hash_iterate(&acl_roles_mappings,
|
||||||
|
(my_hash_walk_action) add_role_user_mapping, NULL);
|
||||||
|
}
|
||||||
/* Return true if there is no users that can match the given host */
|
/* Return true if there is no users that can match the given host */
|
||||||
|
|
||||||
bool acl_check_host(const char *host, const char *ip)
|
bool acl_check_host(const char *host, const char *ip)
|
||||||
|
@ -215,7 +215,7 @@ bool check_grant_column (THD *thd, GRANT_INFO *grant,
|
|||||||
const char *name, uint length, Security_context *sctx);
|
const char *name, uint length, Security_context *sctx);
|
||||||
bool check_column_grant_in_table_ref(THD *thd, TABLE_LIST * table_ref,
|
bool check_column_grant_in_table_ref(THD *thd, TABLE_LIST * table_ref,
|
||||||
const char *name, uint length);
|
const char *name, uint length);
|
||||||
bool check_grant_all_columns(THD *thd, ulong want_access,
|
bool check_grant_all_columns(THD *thd, ulong want_access,
|
||||||
Field_iterator_table_ref *fields);
|
Field_iterator_table_ref *fields);
|
||||||
bool check_grant_routine(THD *thd, ulong want_access,
|
bool check_grant_routine(THD *thd, ulong want_access,
|
||||||
TABLE_LIST *procs, bool is_proc, bool no_error);
|
TABLE_LIST *procs, bool is_proc, bool no_error);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user