summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVicențiu Ciorbaru <cvicentiu@gmail.com>2022-06-10 18:52:33 +0300
committerVicențiu Ciorbaru <cvicentiu@gmail.com>2022-06-12 17:26:28 +0300
commit58f547ca230f7f9ce900023e3ea9a10b176a03de (patch)
treeeb7416995f758e69e6178a47e752eb7549817aa4
parent13cdf2dde29e1916099ef0f900c23004bfd5711d (diff)
downloadmariadb-git-58f547ca230f7f9ce900023e3ea9a10b176a03de.tar.gz
Fixup routine grants impacting check_grant_db
-rw-r--r--mysql-test/suite/deny/show_databases.test1
-rw-r--r--sql/sql_acl.cc82
-rw-r--r--sql/sql_acl.h2
-rw-r--r--sql/sql_db.cc2
-rw-r--r--sql/sql_show.cc6
5 files changed, 70 insertions, 23 deletions
diff --git a/mysql-test/suite/deny/show_databases.test b/mysql-test/suite/deny/show_databases.test
index 5d7d696d30c..1254a863fcd 100644
--- a/mysql-test/suite/deny/show_databases.test
+++ b/mysql-test/suite/deny/show_databases.test
@@ -528,7 +528,6 @@ show tables from some_db;
disconnect con1;
-
connection default;
drop user foo;
drop database some_db;
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 586378eb562..9611bc00eae 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -3889,7 +3889,7 @@ static bool check_show_access(THD *thd, TABLE_LIST *table)
privilege_t deny_mask= acl_get_effective_deny_mask(thd->security_ctx,
dst_db_name);
- if (!cur_access && check_grant_db(thd->security_ctx, dst_db_name.str,
+ if (!cur_access && check_grant_db(thd->security_ctx, dst_db_name,
deny_mask))
{
status_var_increment(thd->status_var.access_denied_errors);
@@ -5071,10 +5071,10 @@ static enum object_type get_corresponding_object_type(const Sp_handler &sph)
{
switch (sph.type())
{
+ case SP_TYPE_PROCEDURE: return PROCEDURE_TYPE;
case SP_TYPE_FUNCTION: return FUNCTION_TYPE;
- case SP_TYPE_PACKAGE_BODY: return PACKAGE_BODY_TYPE;
case SP_TYPE_PACKAGE: return PACKAGE_SPEC_TYPE;
- case SP_TYPE_PROCEDURE: return PROCEDURE_TYPE;
+ case SP_TYPE_PACKAGE_BODY: return PACKAGE_BODY_TYPE;
default:
DBUG_ASSERT(0);
}
@@ -5082,6 +5082,36 @@ static enum object_type get_corresponding_object_type(const Sp_handler &sph)
return TABLE_TYPE;
}
+static HASH *get_corresponding_routine_hash(enum object_type type)
+{
+ switch (type)
+ {
+ case FUNCTION_TYPE: return &func_priv_hash;
+ case PROCEDURE_TYPE: return &proc_priv_hash;
+ case PACKAGE_SPEC_TYPE: return &package_spec_priv_hash;
+ case PACKAGE_BODY_TYPE: return &package_body_priv_hash;
+ default:
+ DBUG_ASSERT(0);
+ }
+ /* We should never reach here. */
+ return nullptr;
+}
+
+static enum PRIV_TYPE get_corresponding_priv_spec_type(enum object_type type)
+{
+ switch (type)
+ {
+ case FUNCTION_TYPE: return FUNCTION_PRIV;
+ case PROCEDURE_TYPE: return PROCEDURE_PRIV;
+ case PACKAGE_SPEC_TYPE: return PACKAGE_SPEC_PRIV;
+ case PACKAGE_BODY_TYPE: return PACKAGE_BODY_PRIV;
+ default:
+ DBUG_ASSERT(0);
+ }
+ /* We should never reach here. */
+ return NO_PRIV;
+}
+
static enum PRIV_TYPE get_corresponding_priv_spec_type(const Sp_handler &sph)
{
switch (sph.type())
@@ -10290,22 +10320,37 @@ err:
}
-static bool check_grant_db_routine(Security_context *sctx, const char *db,
- HASH *hash, privilege_t db_deny_mask)
+static bool check_grant_db_routine(Security_context *sctx,
+ const LEX_CSTRING &db,
+ enum object_type routine_type,
+ privilege_t db_deny_mask)
{
+ HASH *hash= get_corresponding_routine_hash(routine_type);
for (uint idx= 0; idx < hash->records; ++idx)
{
GRANT_NAME *item= (GRANT_NAME*) my_hash_element(hash, idx);
if (strcmp(item->user, sctx->priv_user) == 0 &&
- strcmp(item->db, db) == 0 &&
+ strcmp(item->db, db.str) == 0 &&
compare_hostname(&item->host, sctx->host, sctx->ip))
{
- if (item->privs & ~db_deny_mask)
+ privilege_t usable_mask= db_deny_mask;
+ /*
+ Only re-compute the deny mask if there are specific denies active
+ that might impact it.
+ */
+ if (sctx->denies_active & get_corresponding_priv_spec_type(routine_type))
+ {
+ LEX_CSTRING routine_name= {item->tname, strlen(item->tname)};
+ usable_mask= acl_get_effective_deny_mask_impl(sctx, db, routine_name,
+ routine_type);
+ }
+ if (item->privs & ~usable_mask)
return FALSE;
}
+ /* TODO(cvicentiu) make this work for role denies too. */
if (sctx->priv_role[0] && strcmp(item->user, sctx->priv_role) == 0 &&
- strcmp(item->db, db) == 0 &&
+ strcmp(item->db, db.str) == 0 &&
(!item->host.hostname || !item->host.hostname[0]))
{
if (item->privs & ~db_deny_mask)
@@ -10323,7 +10368,8 @@ static bool check_grant_db_routine(Security_context *sctx, const char *db,
Return 1 if access is denied
*/
-bool check_grant_db(Security_context *sctx, const char *db,
+bool check_grant_db(Security_context *sctx,
+ const LEX_CSTRING &db,
privilege_t db_deny_mask)
{
char helping [SAFE_NAME_LEN + USERNAME_LENGTH+2], *end;
@@ -10331,16 +10377,18 @@ bool check_grant_db(Security_context *sctx, const char *db,
uint len, UNINIT_VAR(len2);
bool error= TRUE;
+ LEX_CSTRING lower_case_db= db;
+
tmp_db= strmov(helping, sctx->priv_user) + 1;
- end= strnmov(tmp_db, db, helping + sizeof(helping) - tmp_db);
+ end= strnmov(tmp_db, db.str, helping + sizeof(helping) - tmp_db);
if (end >= helping + sizeof(helping)) // db name was truncated
return 1; // no privileges for an invalid db name
if (lower_case_table_names)
{
- end = tmp_db + my_casedn_str(files_charset_info, tmp_db);
- db=tmp_db;
+ end= tmp_db + my_casedn_str(files_charset_info, tmp_db);
+ lower_case_db.str= tmp_db;
}
len= (uint) (end - helping) + 1;
@@ -10351,7 +10399,7 @@ bool check_grant_db(Security_context *sctx, const char *db,
if (sctx->priv_role[0])
{
end= strmov(helping2, sctx->priv_role) + 1;
- end= strnmov(end, db, helping2 + sizeof(helping2) - end);
+ end= strnmov(end, lower_case_db.str, helping2 + sizeof(helping2) - end);
len2= (uint) (end - helping2) + 1;
}
@@ -10444,10 +10492,10 @@ bool check_grant_db(Security_context *sctx, const char *db,
//TODO(cvicentiu) implement deny_mask for check_grant_db_routine
if (error)
- error= check_grant_db_routine(sctx, db, &proc_priv_hash, deny_mask) &&
- check_grant_db_routine(sctx, db, &func_priv_hash, deny_mask) &&
- check_grant_db_routine(sctx, db, &package_spec_priv_hash, deny_mask) &&
- check_grant_db_routine(sctx, db, &package_body_priv_hash, deny_mask);
+ error= check_grant_db_routine(sctx, lower_case_db, PROCEDURE_TYPE, deny_mask) &&
+ check_grant_db_routine(sctx, lower_case_db, FUNCTION_TYPE, deny_mask) &&
+ check_grant_db_routine(sctx, lower_case_db, PACKAGE_SPEC_TYPE, deny_mask) &&
+ check_grant_db_routine(sctx, lower_case_db, PACKAGE_BODY_TYPE, deny_mask);
error:
mysql_rwlock_unlock(&LOCK_grant);
diff --git a/sql/sql_acl.h b/sql/sql_acl.h
index d8dfdd1d825..c6a8372ce74 100644
--- a/sql/sql_acl.h
+++ b/sql/sql_acl.h
@@ -102,7 +102,7 @@ bool check_column_grant_in_table_ref(THD *thd, TABLE_LIST * table_ref,
const char *name, size_t length, Field *fld);
bool check_grant_all_columns(THD *thd, privilege_t want_access,
Field_iterator_table_ref *fields);
-bool check_grant_db(Security_context *sctx, const char *db, privilege_t db_deny_mask);
+bool check_grant_db(Security_context *sctx, const LEX_CSTRING &db, privilege_t db_deny_mask);
bool check_global_access(THD *thd, const privilege_t want_access, bool no_errors= false);
bool check_access(THD *thd, privilege_t want_access,
const char *db, privilege_t *save_priv,
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 7f420360543..a043b518c4c 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -1789,7 +1789,7 @@ uint mysql_change_db(THD *thd, const LEX_CSTRING *new_db_name,
// TODO(cvicentiu) check how force_switch impacts denies.
if (!force_switch &&
!(db_access & DB_ACLS) &&
- check_grant_db(thd->security_ctx, new_db_file_name.str, deny_mask))
+ check_grant_db(thd->security_ctx, new_db_file_name, deny_mask))
{
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
sctx->priv_user,
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 582e1e9a57f..01fb7813d7a 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1408,7 +1408,7 @@ bool mysqld_show_create_db(THD *thd, LEX_CSTRING *dbname,
acl_get_current_auth(sctx, dbname->str, false);
db_access&= ~deny_mask;
- if (!(db_access & DB_ACLS) && check_grant_db(sctx, dbname->str, deny_mask))
+ if (!(db_access & DB_ACLS) && check_grant_db(sctx, *dbname, deny_mask))
{
status_var_increment(thd->status_var.access_denied_errors);
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
@@ -5303,7 +5303,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
//TODO(cvicentiu) denies -> write tests
if (!(check_access(thd, SELECT_ACL, db_name->str,
&thd->col_access, NULL, 0, 1) ||
- (!thd->col_access && check_grant_db(sctx, db_name->str, NO_ACL))) ||
+ (!thd->col_access && check_grant_db(sctx, *db_name, NO_ACL))) ||
(sctx->master_access & ~deny_mask) & (DB_ACLS | SHOW_DB_ACL) ||
(acl_get_current_auth(sctx, db_name->str, false) & ~deny_mask))
#endif
@@ -5510,7 +5510,7 @@ int fill_schema_schemata(THD *thd, TABLE_LIST *tables, COND *cond)
if ((sctx->master_access & ~deny_mask) & (DB_ACLS | SHOW_DB_ACL) ||
(acl_get_current_auth(sctx, db_name->str, false) & ~deny_mask)||
- !check_grant_db(sctx, db_name->str, deny_mask))
+ !check_grant_db(sctx, *db_name, deny_mask))
#endif
{
load_db_opt_by_name(thd, db_name->str, &create);