remove ER_RESERVED_ROLE.
Only allow NONE instead of a role name in SET ROLE. Don't allow PUBLIC as a role name anywhere (to be fixed later) Fix db_access calculations on SET ROLE Reduce the size of role_grants and parent_grantee per-user/role arrays. Fix the wording and specify the correct sqlstate for ER_INVALID_ROLE
This commit is contained in:
parent
4ec26a7c2d
commit
f74b9eca6e
56
mysql-test/r/acl_roles_none_public.result
Normal file
56
mysql-test/r/acl_roles_none_public.result
Normal file
@ -0,0 +1,56 @@
|
||||
create role role1;
|
||||
create role none;
|
||||
ERROR OP000: Invalid role specification `none`.
|
||||
create role public;
|
||||
ERROR OP000: Invalid role specification `public`.
|
||||
drop role none;
|
||||
ERROR HY000: Operation DROP ROLE failed for 'none'
|
||||
grant none to role1;
|
||||
ERROR OP000: Invalid role specification `none`.
|
||||
grant role1 to none;
|
||||
ERROR OP000: Invalid role specification `none`.
|
||||
grant select on *.* to none;
|
||||
ERROR OP000: Invalid role specification `none`.
|
||||
grant public to role1;
|
||||
ERROR OP000: Invalid role specification `public`.
|
||||
grant role1 to public;
|
||||
ERROR OP000: Invalid role specification `public`.
|
||||
grant select on *.* to public;
|
||||
ERROR OP000: Invalid role specification `public`.
|
||||
grant role1 to current_role;
|
||||
ERROR OP000: Invalid role specification `NONE`.
|
||||
revoke none from role1;
|
||||
ERROR OP000: Invalid role specification `none`.
|
||||
revoke role1 from none;
|
||||
ERROR OP000: Invalid role specification `none`.
|
||||
revoke select on *.* from none;
|
||||
ERROR OP000: Invalid role specification `none`.
|
||||
revoke public from role1;
|
||||
ERROR OP000: Invalid role specification `public`.
|
||||
revoke role1 from public;
|
||||
ERROR OP000: Invalid role specification `public`.
|
||||
revoke select on *.* from public;
|
||||
ERROR OP000: Invalid role specification `public`.
|
||||
show grants for none;
|
||||
ERROR OP000: Invalid role specification `none`.
|
||||
show grants for public;
|
||||
ERROR OP000: Invalid role specification `public`.
|
||||
create definer=none view test.v1 as select 1;
|
||||
ERROR OP000: Invalid role specification `none`.
|
||||
create definer=public view test.v1 as select 1;
|
||||
ERROR OP000: Invalid role specification `public`.
|
||||
drop role role1;
|
||||
optimize table mysql.user;
|
||||
Table Op Msg_type Msg_text
|
||||
mysql.user optimize status OK
|
||||
insert mysql.user (user, is_role) values ('none', 'Y'), ('public', 'Y');
|
||||
Warnings:
|
||||
Warning 1364 Field 'ssl_cipher' doesn't have a default value
|
||||
Warning 1364 Field 'x509_issuer' doesn't have a default value
|
||||
Warning 1364 Field 'x509_subject' doesn't have a default value
|
||||
Warning 1364 Field 'authentication_string' doesn't have a default value
|
||||
flush privileges;
|
||||
Warnings:
|
||||
Error 1958 Invalid role specification `none`.
|
||||
Error 1958 Invalid role specification `public`.
|
||||
delete from mysql.user where is_role='Y';
|
@ -66,7 +66,7 @@ Grants for test_user@localhost
|
||||
GRANT USAGE ON *.* TO 'test_user'@'localhost'
|
||||
GRANT test_role1 TO 'test_user'@'localhost'
|
||||
set role test_role2;
|
||||
ERROR HY000: The role 'test_role2' has not been granted or is invalid.
|
||||
ERROR OP000: Invalid role specification `test_role2`.
|
||||
select current_user(), current_role();
|
||||
current_user() current_role()
|
||||
test_user@localhost NULL
|
||||
|
55
mysql-test/t/acl_roles_none_public.test
Normal file
55
mysql-test/t/acl_roles_none_public.test
Normal file
@ -0,0 +1,55 @@
|
||||
create role role1;
|
||||
|
||||
--error ER_INVALID_ROLE
|
||||
create role none;
|
||||
--error ER_INVALID_ROLE
|
||||
create role public;
|
||||
--error ER_CANNOT_USER
|
||||
drop role none;
|
||||
|
||||
--error ER_INVALID_ROLE
|
||||
grant none to role1;
|
||||
--error ER_INVALID_ROLE
|
||||
grant role1 to none;
|
||||
--error ER_INVALID_ROLE
|
||||
grant select on *.* to none;
|
||||
--error ER_INVALID_ROLE
|
||||
grant public to role1;
|
||||
--error ER_INVALID_ROLE
|
||||
grant role1 to public;
|
||||
--error ER_INVALID_ROLE
|
||||
grant select on *.* to public;
|
||||
|
||||
--error ER_INVALID_ROLE
|
||||
grant role1 to current_role;
|
||||
|
||||
--error ER_INVALID_ROLE
|
||||
revoke none from role1;
|
||||
--error ER_INVALID_ROLE
|
||||
revoke role1 from none;
|
||||
--error ER_INVALID_ROLE
|
||||
revoke select on *.* from none;
|
||||
--error ER_INVALID_ROLE
|
||||
revoke public from role1;
|
||||
--error ER_INVALID_ROLE
|
||||
revoke role1 from public;
|
||||
--error ER_INVALID_ROLE
|
||||
revoke select on *.* from public;
|
||||
|
||||
--error ER_INVALID_ROLE
|
||||
show grants for none;
|
||||
--error ER_INVALID_ROLE
|
||||
show grants for public;
|
||||
|
||||
--error ER_INVALID_ROLE
|
||||
create definer=none view test.v1 as select 1;
|
||||
--error ER_INVALID_ROLE
|
||||
create definer=public view test.v1 as select 1;
|
||||
|
||||
drop role role1;
|
||||
|
||||
optimize table mysql.user; # to remove deleted rows and have stable row order
|
||||
insert mysql.user (user, is_role) values ('none', 'Y'), ('public', 'Y');
|
||||
flush privileges;
|
||||
delete from mysql.user where is_role='Y';
|
||||
|
@ -6562,15 +6562,12 @@ ER_NO_SUCH_QUERY
|
||||
eng "Unknown query id: %lld"
|
||||
ger "Unbekannte Abfrage-ID: %lld"
|
||||
rus "Неизвестный номер запроса: %lld"
|
||||
ER_INVALID_ROLE
|
||||
eng "The role '%s' has not been granted or is invalid."
|
||||
rum "Rolul '%s' este invalid sau nu a fost acordat."
|
||||
ER_INVALID_ROLE OP000
|
||||
eng "Invalid role specification %`s."
|
||||
rum "Rolul %`s este invalid."
|
||||
ER_INVALID_CURRENT_USER
|
||||
eng "The current user is invalid."
|
||||
rum "Utilizatorul curent este invalid."
|
||||
ER_RESERVED_ROLE
|
||||
eng "Role name '%s' is reserved."
|
||||
rum "Numele de rol '%s' este rezervat."
|
||||
ER_CANNOT_GRANT_ROLE
|
||||
eng "Cannot grant role '%s' to: %s."
|
||||
rum "Rolul '%s' nu poate fi acordat catre: %s."
|
||||
|
102
sql/sql_acl.cc
102
sql/sql_acl.cc
@ -190,10 +190,6 @@ LEX_STRING *default_auth_plugin_name= &native_password_plugin_name;
|
||||
*/
|
||||
LEX_STRING host_not_specified= { C_STRING_WITH_LEN("%") };
|
||||
|
||||
/*
|
||||
Constant used in the SET ROLE NONE command
|
||||
*/
|
||||
LEX_STRING none_role= { C_STRING_WITH_LEN("NONE") };
|
||||
/*
|
||||
Constants, used in the SHOW GRANTS command.
|
||||
Their actual string values are irrelevant, they're always compared
|
||||
@ -781,6 +777,16 @@ ACL_ROLE::ACL_ROLE(const char * rolename, ulong privileges, MEM_ROOT *root) :
|
||||
}
|
||||
|
||||
|
||||
static bool is_invalid_role_name(const char *str)
|
||||
{
|
||||
if (strcasecmp(str, "PUBLIC") && strcasecmp(str, "NONE"))
|
||||
return false;
|
||||
|
||||
my_error(ER_INVALID_ROLE, MYF(0), str);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void free_acl_user(ACL_USER *user)
|
||||
{
|
||||
delete_dynamic(&(user->role_grants));
|
||||
@ -1115,6 +1121,12 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
|
||||
*/
|
||||
is_role= check_is_role(table);
|
||||
|
||||
if (is_role && is_invalid_role_name(username))
|
||||
{
|
||||
thd->clear_error();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!is_role && check_no_resolve &&
|
||||
hostname_requires_resolving(user.host.hostname))
|
||||
{
|
||||
@ -1254,14 +1266,15 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
|
||||
}
|
||||
|
||||
(void) my_init_dynamic_array(&user.role_grants,sizeof(ACL_ROLE *),
|
||||
50, 100, MYF(0));
|
||||
8, 8, MYF(0));
|
||||
|
||||
if (is_role) {
|
||||
if (is_role)
|
||||
{
|
||||
DBUG_PRINT("info", ("Found role %s", user.user.str));
|
||||
ACL_ROLE *entry= new (&mem) ACL_ROLE(&user, &mem);
|
||||
entry->role_grants = user.role_grants;
|
||||
(void) my_init_dynamic_array(&entry->parent_grantee,
|
||||
sizeof(ACL_USER_BASE *), 50, 100, MYF(0));
|
||||
sizeof(ACL_USER_BASE *), 8, 8, MYF(0));
|
||||
my_hash_insert(&acl_roles, (uchar *)entry);
|
||||
|
||||
continue;
|
||||
@ -1830,17 +1843,17 @@ bool acl_getroot(Security_context *sctx, char *user, char *host,
|
||||
|
||||
int acl_check_setrole(THD *thd, char *rolename, ulonglong *access)
|
||||
{
|
||||
ACL_ROLE *role;
|
||||
ACL_USER_BASE *acl_user_base;
|
||||
ACL_USER *UNINIT_VAR(acl_user);
|
||||
bool is_granted= FALSE;
|
||||
int result= 0;
|
||||
|
||||
/* clear role privileges */
|
||||
mysql_mutex_lock(&acl_cache->lock);
|
||||
|
||||
ACL_ROLE *role= find_acl_role(rolename);
|
||||
ACL_USER_BASE *acl_user_base;
|
||||
ACL_USER *UNINIT_VAR(acl_user);
|
||||
|
||||
if (!strcasecmp(rolename, "NONE")) {
|
||||
if (!strcasecmp(rolename, "NONE"))
|
||||
{
|
||||
/* have to clear the privileges */
|
||||
/* get the current user */
|
||||
acl_user= find_user(thd->security_ctx->host, thd->security_ctx->user,
|
||||
@ -1856,6 +1869,8 @@ int acl_check_setrole(THD *thd, char *rolename, ulonglong *access)
|
||||
goto end;
|
||||
}
|
||||
|
||||
role= find_acl_role(rolename);
|
||||
|
||||
/* According to SQL standard, the same error message must be presented */
|
||||
if (role == NULL) {
|
||||
my_error(ER_INVALID_ROLE, MYF(0), rolename);
|
||||
@ -1907,20 +1922,18 @@ int acl_setrole(THD *thd, char *rolename, ulonglong access)
|
||||
Security_context *sctx= thd->security_ctx;
|
||||
sctx->master_access= access;
|
||||
if (thd->db)
|
||||
{
|
||||
sctx->db_access= acl_get(sctx->host,
|
||||
sctx->ip, sctx->user, thd->db, FALSE);
|
||||
sctx->db_access= acl_get("", "", rolename, thd->db, FALSE);
|
||||
}
|
||||
sctx->db_access= acl_get(sctx->host, sctx->ip, sctx->user, thd->db, FALSE);
|
||||
|
||||
if (!strcasecmp(rolename, "NONE"))
|
||||
{
|
||||
thd->security_ctx->priv_role[0]= 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (thd->db)
|
||||
sctx->db_access|= acl_get("", "", rolename, thd->db, FALSE);
|
||||
/* mark the current role */
|
||||
strmake(thd->security_ctx->priv_role, rolename,
|
||||
sizeof(thd->security_ctx->priv_role)-1);
|
||||
strmake_buf(thd->security_ctx->priv_role, rolename);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -2016,9 +2029,9 @@ static void acl_insert_role(const char *rolename, ulong privileges)
|
||||
mysql_mutex_assert_owner(&acl_cache->lock);
|
||||
entry= new (&mem) ACL_ROLE(rolename, privileges, &mem);
|
||||
(void) my_init_dynamic_array(&entry->parent_grantee,
|
||||
sizeof(ACL_USER_BASE *), 50, 100, MYF(0));
|
||||
sizeof(ACL_USER_BASE *), 8, 8, MYF(0));
|
||||
(void) my_init_dynamic_array(&entry->role_grants,sizeof(ACL_ROLE *),
|
||||
50, 100, MYF(0));
|
||||
8, 8, MYF(0));
|
||||
|
||||
my_hash_insert(&acl_roles, (uchar *)entry);
|
||||
}
|
||||
@ -2070,7 +2083,7 @@ static void acl_insert_user(const char *user, const char *host,
|
||||
acl_user.x509_issuer= x509_issuer ? strdup_root(&mem,x509_issuer) : 0;
|
||||
acl_user.x509_subject=x509_subject ? strdup_root(&mem,x509_subject) : 0;
|
||||
(void) my_init_dynamic_array(&acl_user.role_grants, sizeof(ACL_USER *),
|
||||
50, 100, MYF(0));
|
||||
8, 8, MYF(0));
|
||||
|
||||
(void) push_dynamic(&acl_users,(uchar*) &acl_user);
|
||||
if (!acl_user.host.hostname ||
|
||||
@ -5800,20 +5813,11 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke)
|
||||
|
||||
List_iterator <LEX_USER> user_list(list);
|
||||
granted_role= user_list++;
|
||||
if (granted_role->user.str == current_role.str)
|
||||
{
|
||||
rolename.str= thd->security_ctx->priv_role;
|
||||
if (!rolename.str[0])
|
||||
{
|
||||
my_error(ER_RESERVED_ROLE, MYF(0), "NONE");
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
rolename.length= strlen(rolename.str);
|
||||
}
|
||||
else
|
||||
{
|
||||
rolename= granted_role->user;
|
||||
}
|
||||
if (!(granted_role= get_current_user(thd, granted_role)))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
DBUG_ASSERT(granted_role->is_role());
|
||||
rolename= granted_role->user;
|
||||
|
||||
TABLE_LIST tables;
|
||||
tables.init_one_table(C_STRING_WITH_LEN("mysql"),
|
||||
@ -5856,6 +5860,7 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke)
|
||||
/* current_role is NONE */
|
||||
if (!thd->security_ctx->priv_role[0])
|
||||
{
|
||||
my_error(ER_INVALID_ROLE, MYF(0), "NONE");
|
||||
append_user(&wrong_users, "NONE", "");
|
||||
result= 1;
|
||||
continue;
|
||||
@ -5894,7 +5899,15 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke)
|
||||
if ((role_as_user= find_acl_role(user->user.str)))
|
||||
hostname= empty_lex_str;
|
||||
else
|
||||
{
|
||||
if (is_invalid_role_name(username.str))
|
||||
{
|
||||
append_user(&wrong_users, username.str, "");
|
||||
result= 1;
|
||||
continue;
|
||||
}
|
||||
hostname= host_not_specified;
|
||||
}
|
||||
}
|
||||
|
||||
ROLE_GRANT_PAIR *hash_entry= find_role_grant_pair(&username, &hostname,
|
||||
@ -7453,6 +7466,13 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user)
|
||||
else
|
||||
{
|
||||
lex_user= get_current_user(thd, lex_user, false);
|
||||
if (!lex_user)
|
||||
{
|
||||
mysql_mutex_unlock(&acl_cache->lock);
|
||||
mysql_rwlock_unlock(&LOCK_grant);
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
if (lex_user->is_role())
|
||||
{
|
||||
rolename= lex_user->user.str;
|
||||
@ -9111,6 +9131,13 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list, bool handle_as_role)
|
||||
|
||||
while ((user_name= user_list++))
|
||||
{
|
||||
if (handle_as_role && is_invalid_role_name(user_name->user.str))
|
||||
{
|
||||
append_user(&wrong_users, user_name);
|
||||
result= TRUE;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!user_name->host.str)
|
||||
user_name->host= host_not_specified;
|
||||
|
||||
@ -10511,6 +10538,9 @@ LEX_USER *get_current_user(THD *thd, LEX_USER *user, bool lock)
|
||||
if (!dup)
|
||||
return 0;
|
||||
|
||||
if (is_invalid_role_name(user->user.str))
|
||||
return 0;
|
||||
|
||||
if (lock)
|
||||
mysql_mutex_lock(&acl_cache->lock);
|
||||
if (find_acl_role(dup->user.str))
|
||||
|
@ -174,7 +174,6 @@ extern const TABLE_FIELD_DEF mysql_db_table_def;
|
||||
extern bool mysql_user_table_is_in_short_password_format;
|
||||
|
||||
extern LEX_STRING host_not_specified;
|
||||
extern LEX_STRING none_role;
|
||||
extern LEX_STRING current_user;
|
||||
extern LEX_STRING current_role;
|
||||
extern LEX_STRING current_user_and_current_role;
|
||||
|
@ -14221,13 +14221,13 @@ revoke:
|
||||
;
|
||||
|
||||
revoke_command:
|
||||
grant_privileges ON opt_table grant_ident FROM user_list
|
||||
grant_privileges ON opt_table grant_ident FROM user_and_role_list
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
lex->sql_command= SQLCOM_REVOKE;
|
||||
lex->type= 0;
|
||||
}
|
||||
| grant_privileges ON FUNCTION_SYM grant_ident FROM user_list
|
||||
| grant_privileges ON FUNCTION_SYM grant_ident FROM user_and_role_list
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
if (lex->columns.elements)
|
||||
@ -14238,7 +14238,7 @@ revoke_command:
|
||||
lex->sql_command= SQLCOM_REVOKE;
|
||||
lex->type= TYPE_ENUM_FUNCTION;
|
||||
}
|
||||
| grant_privileges ON PROCEDURE_SYM grant_ident FROM user_list
|
||||
| grant_privileges ON PROCEDURE_SYM grant_ident FROM user_and_role_list
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
if (lex->columns.elements)
|
||||
@ -14249,7 +14249,7 @@ revoke_command:
|
||||
lex->sql_command= SQLCOM_REVOKE;
|
||||
lex->type= TYPE_ENUM_PROCEDURE;
|
||||
}
|
||||
| ALL opt_privileges ',' GRANT OPTION FROM user_list
|
||||
| ALL opt_privileges ',' GRANT OPTION FROM user_and_role_list
|
||||
{
|
||||
Lex->sql_command = SQLCOM_REVOKE_ALL;
|
||||
}
|
||||
@ -14319,7 +14319,7 @@ grant_command:
|
||||
lex->sql_command= SQLCOM_GRANT;
|
||||
lex->type= TYPE_ENUM_PROXY;
|
||||
}
|
||||
| grant_role TO_SYM user_and_role_list opt_with_admin_option
|
||||
| grant_role TO_SYM grant_list opt_with_admin_option
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
lex->sql_command= SQLCOM_GRANT_ROLE;
|
||||
@ -14627,7 +14627,7 @@ grant_user:
|
||||
$1->plugin= $4;
|
||||
$1->auth= $6;
|
||||
}
|
||||
| user
|
||||
| user_or_role
|
||||
{ $$= $1; $1->password= null_lex_str; }
|
||||
;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user