Commit f74b9eca authored by Sergei Golubchik's avatar Sergei Golubchik

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
parent 4ec26a7c
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
......
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."
......
......@@ -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; }
;
......
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