summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2013-10-18 15:52:26 -0700
committerSergei Golubchik <sergii@pisem.net>2013-10-18 15:52:26 -0700
commitf74b9eca6ebe83367fd742f6f537814dcdd6cc2f (patch)
tree0f411f14c6e73ca4720966e73e94e9d22a460d70
parent4ec26a7c2dbb2a49fbedf14f0ca7d126703916ae (diff)
downloadmariadb-git-f74b9eca6ebe83367fd742f6f537814dcdd6cc2f.tar.gz
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
-rw-r--r--mysql-test/r/acl_roles_none_public.result56
-rw-r--r--mysql-test/r/acl_roles_set_role-recursive.result2
-rw-r--r--mysql-test/t/acl_roles_none_public.test55
-rw-r--r--sql/share/errmsg-utf8.txt9
-rw-r--r--sql/sql_acl.cc102
-rw-r--r--sql/sql_acl.h1
-rw-r--r--sql/sql_yacc.yy12
7 files changed, 187 insertions, 50 deletions
diff --git a/mysql-test/r/acl_roles_none_public.result b/mysql-test/r/acl_roles_none_public.result
new file mode 100644
index 00000000000..a0c7a0db707
--- /dev/null
+++ b/mysql-test/r/acl_roles_none_public.result
@@ -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';
diff --git a/mysql-test/r/acl_roles_set_role-recursive.result b/mysql-test/r/acl_roles_set_role-recursive.result
index 54965157612..a4442d8caa3 100644
--- a/mysql-test/r/acl_roles_set_role-recursive.result
+++ b/mysql-test/r/acl_roles_set_role-recursive.result
@@ -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
diff --git a/mysql-test/t/acl_roles_none_public.test b/mysql-test/t/acl_roles_none_public.test
new file mode 100644
index 00000000000..af3d6bf3f68
--- /dev/null
+++ b/mysql-test/t/acl_roles_none_public.test
@@ -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';
+
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 6135f8f1b96..cf2aa33f96e 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -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."
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index b188b909600..a57f2d9f115 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -191,10 +191,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
as pointers to these string constants.
@@ -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))
diff --git a/sql/sql_acl.h b/sql/sql_acl.h
index 8766f78ecee..1b09b4bbdd4 100644
--- a/sql/sql_acl.h
+++ b/sql/sql_acl.h
@@ -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;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 5f68d79a763..38b6d990aa5 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -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; }
;