diff options
author | Vicențiu Ciorbaru <cvicentiu@gmail.com> | 2022-06-10 18:52:33 +0300 |
---|---|---|
committer | Vicențiu Ciorbaru <cvicentiu@gmail.com> | 2022-06-12 17:26:28 +0300 |
commit | 58f547ca230f7f9ce900023e3ea9a10b176a03de (patch) | |
tree | eb7416995f758e69e6178a47e752eb7549817aa4 | |
parent | 13cdf2dde29e1916099ef0f900c23004bfd5711d (diff) | |
download | mariadb-git-58f547ca230f7f9ce900023e3ea9a10b176a03de.tar.gz |
Fixup routine grants impacting check_grant_db
-rw-r--r-- | mysql-test/suite/deny/show_databases.test | 1 | ||||
-rw-r--r-- | sql/sql_acl.cc | 82 | ||||
-rw-r--r-- | sql/sql_acl.h | 2 | ||||
-rw-r--r-- | sql/sql_db.cc | 2 | ||||
-rw-r--r-- | sql/sql_show.cc | 6 |
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); |