3314 lines
130 KiB
C++
3314 lines
130 KiB
C++
/**
|
|
* Copyright (c) 2021 OceanBase
|
|
* OceanBase CE is licensed under Mulan PubL v2.
|
|
* You can use this software according to the terms and conditions of the Mulan PubL v2.
|
|
* You may obtain a copy of Mulan PubL v2 at:
|
|
* http://license.coscl.org.cn/MulanPubL-2.0
|
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
* See the Mulan PubL v2 for more details.
|
|
*/
|
|
|
|
#define USING_LOG_PREFIX SQL_SESSION
|
|
#include "sql/privilege_check/ob_privilege_check.h"
|
|
|
|
#include "share/schema/ob_schema_struct.h"
|
|
#include "share/schema/ob_schema_getter_guard.h"
|
|
#include "sql/ob_sql_context.h"
|
|
#include "sql/resolver/ddl/ob_explain_stmt.h"
|
|
#include "sql/resolver/ddl/ob_create_table_stmt.h"
|
|
#include "sql/resolver/ddl/ob_create_index_stmt.h"
|
|
#include "sql/resolver/ddl/ob_create_mlog_stmt.h"
|
|
#include "sql/resolver/ddl/ob_drop_mlog_stmt.h"
|
|
#include "sql/resolver/ddl/ob_create_database_stmt.h"
|
|
#include "sql/resolver/ddl/ob_alter_table_stmt.h"
|
|
#include "sql/resolver/ddl/ob_drop_database_stmt.h"
|
|
#include "sql/resolver/ddl/ob_drop_index_stmt.h"
|
|
#include "sql/resolver/ddl/ob_lock_tenant_stmt.h"
|
|
#include "sql/resolver/ddl/ob_drop_tenant_stmt.h"
|
|
#include "sql/resolver/dcl/ob_create_user_stmt.h"
|
|
#include "sql/resolver/ddl/ob_drop_table_stmt.h"
|
|
#include "sql/resolver/dcl/ob_drop_user_stmt.h"
|
|
#include "sql/resolver/dcl/ob_lock_user_stmt.h"
|
|
#include "sql/resolver/dcl/ob_rename_user_stmt.h"
|
|
#include "sql/resolver/dcl/ob_revoke_stmt.h"
|
|
#include "sql/resolver/dcl/ob_set_password_stmt.h"
|
|
#include "sql/resolver/dml/ob_delete_stmt.h"
|
|
#include "sql/resolver/dml/ob_select_stmt.h"
|
|
#include "sql/resolver/dml/ob_update_stmt.h"
|
|
#include "sql/resolver/dml/ob_merge_stmt.h"
|
|
#include "sql/resolver/dml/ob_insert_stmt.h"
|
|
#include "sql/resolver/dcl/ob_grant_stmt.h"
|
|
#include "sql/resolver/dcl/ob_revoke_stmt.h"
|
|
#include "sql/session/ob_sql_session_info.h"
|
|
#include "sql/resolver/cmd/ob_variable_set_stmt.h"
|
|
#include "sql/resolver/ddl/ob_modify_tenant_stmt.h"
|
|
#include "sql/resolver/ddl/ob_alter_database_stmt.h"
|
|
#include "sql/resolver/ddl/ob_truncate_table_stmt.h"
|
|
#include "sql/resolver/ddl/ob_rename_table_stmt.h"
|
|
#include "sql/resolver/ddl/ob_create_table_like_stmt.h"
|
|
#include "sql/resolver/cmd/ob_set_names_stmt.h"
|
|
#include "sql/resolver/ddl/ob_create_tablegroup_stmt.h"
|
|
#include "sql/resolver/ddl/ob_drop_tablegroup_stmt.h"
|
|
#include "sql/resolver/ddl/ob_alter_tablegroup_stmt.h"
|
|
#include "sql/resolver/ddl/ob_flashback_stmt.h"
|
|
#include "sql/resolver/ddl/ob_purge_stmt.h"
|
|
#include "sql/resolver/ddl/ob_create_synonym_stmt.h"
|
|
#include "sql/resolver/ddl/ob_drop_synonym_stmt.h"
|
|
#include "sql/resolver/cmd/ob_call_procedure_stmt.h"
|
|
#include "sql/resolver/cmd/ob_load_data_stmt.h"
|
|
#include "rootserver/ob_ddl_service.h"
|
|
#include "sql/resolver/dml/ob_merge_stmt.h"
|
|
#include "sql/privilege_check/ob_ora_priv_check.h"
|
|
#include "pl/ob_pl_stmt.h"
|
|
|
|
namespace oceanbase {
|
|
using namespace share;
|
|
using namespace share::schema;
|
|
using namespace common;
|
|
namespace sql {
|
|
#define ADD_NEED_PRIV(need_priv) \
|
|
if (OB_SUCC(ret) && OB_FAIL(need_privs.push_back(need_priv))) { \
|
|
LOG_WARN("Fail to add need_priv", K(need_priv), K(ret)); \
|
|
}
|
|
|
|
int err_stmt_type_priv(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
UNUSED(session_priv);
|
|
UNUSED(need_privs);
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should not be NULL", K(ret));
|
|
} else {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_ERROR("Stmt type should not be here", K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
///@brief if you sure no priv needed for the stmt
|
|
int no_priv_needed(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
UNUSED(session_priv);
|
|
UNUSED(basic_stmt);
|
|
UNUSED(need_privs);
|
|
return OB_SUCCESS;
|
|
}
|
|
|
|
/* 判断expr是否含指定表的列,表的表级由expr level 和rel ids标记 */
|
|
int expr_has_col_in_tab(
|
|
const ObRawExpr *expr,
|
|
const ObRelIds &rel_ids,
|
|
bool& exists)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool is_stack_overflow = false;
|
|
if (OB_ISNULL(expr)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("expr is null", K(ret));
|
|
} else if (OB_FAIL(check_stack_overflow(is_stack_overflow))) {
|
|
LOG_WARN("failed to check stack overflow", K(ret));
|
|
} else if (is_stack_overflow) {
|
|
ret = OB_SIZE_OVERFLOW;
|
|
LOG_WARN("too deep recursive", K(ret), K(is_stack_overflow));
|
|
} else if (expr->is_column_ref_expr()) {
|
|
if (rel_ids.is_superset(expr->get_relation_ids())) {
|
|
exists = true;
|
|
}
|
|
} else if (expr->has_flag(CNT_COLUMN)) {
|
|
for (int64_t i = 0; OB_SUCC(ret) && !exists && i < expr->get_param_count(); ++i) {
|
|
OZ (expr_has_col_in_tab(expr->get_param_expr(i), rel_ids, exists));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/* 对update,delete语句增加必要的select权限 */
|
|
int add_nec_sel_priv_in_dml(
|
|
const ObDMLStmt* dml_stmt,
|
|
ObPackedObjPriv& packed_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool exists = false;
|
|
if (OB_ISNULL(dml_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Dml stmt should not be NULL", K(ret));
|
|
} else if (stmt::T_UPDATE == dml_stmt->get_stmt_type() ||
|
|
stmt::T_DELETE == dml_stmt->get_stmt_type()) {
|
|
/* 基表的table id*/
|
|
ObRelIds table_ids;
|
|
for (int i = 0; i < dml_stmt->get_table_size() && OB_SUCC(ret); i++) {
|
|
const TableItem *table_item = dml_stmt->get_table_item(i);
|
|
if (OB_ISNULL(table_item)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("table item is null");
|
|
} else {
|
|
OZ (table_ids.add_member(dml_stmt->get_table_bit_index(table_item->table_id_)));
|
|
}
|
|
}
|
|
for (int i = 0; OB_SUCC(ret) && (!exists) && i < dml_stmt->get_condition_size(); i++) {
|
|
const ObRawExpr *raw_expr = dml_stmt->get_condition_expr(i);
|
|
OZ (expr_has_col_in_tab(raw_expr, table_ids, exists));
|
|
}
|
|
if (OB_SUCC(ret) && exists) {
|
|
OZ (ObPrivPacker::append_raw_obj_priv(NO_OPTION, OBJ_PRIV_ID_SELECT, packed_privs));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int add_need_priv(
|
|
ObIArray<ObOraNeedPriv> &need_privs,
|
|
ObOraNeedPriv& need_priv)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool found = false;
|
|
for (int i = 0; OB_SUCC(ret) && !found && i < need_privs.count(); i++) {
|
|
ObOraNeedPriv &tmp_priv = need_privs.at(i);
|
|
if (need_priv.same_obj(tmp_priv)) {
|
|
found = true;
|
|
tmp_priv.obj_privs_ |= need_priv.obj_privs_;
|
|
}
|
|
}
|
|
if (OB_SUCC(ret) && !found) {
|
|
OZ (need_privs.push_back(need_priv));
|
|
if (need_priv.owner_id_ == OB_INVALID_ID) {
|
|
LOG_INFO("obj owner id -1", K(need_priv), K(lbt()));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/* 根据dbname,找到同名的用户信息,返回用户id */
|
|
int get_owner_id_by_db_name(
|
|
const ObSqlCtx &ctx,
|
|
const ObString &db_name,
|
|
uint64_t& owner_id)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObString host_name(OB_DEFAULT_HOST_NAME);
|
|
const ObUserInfo* user_info = NULL;
|
|
|
|
CK (ctx.session_info_ != NULL);
|
|
if (db_name == OB_SYS_DATABASE_NAME) {
|
|
owner_id = OB_ORA_SYS_USER_ID;
|
|
} else {
|
|
CK (ctx.schema_guard_ != NULL);
|
|
OZ (ctx.schema_guard_->get_user_info(ctx.session_info_->get_login_tenant_id(),
|
|
db_name,
|
|
host_name,
|
|
user_info));
|
|
CK (user_info != NULL);
|
|
OX (owner_id = user_info->get_user_id());
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int set_need_priv_owner_id(
|
|
const ObSqlCtx &ctx,
|
|
ObOraNeedPriv &need_priv)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
uint64_t owner_id = OB_INVALID_ID;
|
|
|
|
if (!need_priv.db_name_.empty()) {
|
|
OZ (get_owner_id_by_db_name(ctx, need_priv.db_name_, owner_id), need_priv.db_name_);
|
|
OX (need_priv.owner_id_ = owner_id);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
int get_view_owner_id(
|
|
const ObSqlCtx &ctx,
|
|
const TableItem* table_item,
|
|
uint64_t& user_id)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObString host_name(OB_DEFAULT_HOST_NAME);
|
|
const ObUserInfo* user_info = NULL;
|
|
|
|
CK (table_item != NULL);
|
|
CK (table_item->is_view_table_ == true);
|
|
CK( table_item->ref_query_ != NULL);
|
|
CK (ctx.schema_guard_ != NULL);
|
|
CK (ctx.session_info_ != NULL);
|
|
OZ (ctx.schema_guard_->get_user_info(ctx.session_info_->get_login_tenant_id(),
|
|
table_item->database_name_,
|
|
host_name,
|
|
user_info));
|
|
CK (user_info != NULL);
|
|
OX (user_id = user_info->get_user_id());
|
|
return ret;
|
|
}
|
|
|
|
int mock_table_item(
|
|
const ObSqlCtx &ctx,
|
|
const TableItem* table_item,
|
|
TableItem &new_table_item)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
uint64_t view_id;
|
|
CK (table_item != NULL);
|
|
CK (ctx.schema_guard_ != NULL);
|
|
CK (ctx.session_info_ != NULL);
|
|
|
|
new_table_item = *table_item;
|
|
new_table_item.alias_name_ = ObString("");
|
|
OZ (ctx.schema_guard_->get_table_id(ctx.session_info_->get_login_tenant_id(),
|
|
table_item->database_name_,
|
|
table_item->table_name_,
|
|
false,
|
|
share::schema::ObSchemaGetterGuard::ALL_NON_HIDDEN_TYPES,
|
|
view_id));
|
|
OX (new_table_item.table_id_ = view_id);
|
|
return ret;
|
|
}
|
|
/** add_col_id_array_to_need_priv
|
|
* 从 basic_stmt 中解析出sql语句作用的列,并加入到 need_priv 中
|
|
* 修改col_id_并不会影响到obj权限的检查,因为进行表级权限检查时,无需使用col_id_
|
|
* @param {const ObStmt*} basic_stmt : basic_stmt
|
|
* @param {const uint64_t} table_id : 当前处理的 table_id
|
|
* @param {ObOraNeedPriv &} need_priv : 视情况将need_priv由表级改为列级
|
|
* @return {int} : ret
|
|
*/
|
|
int add_col_id_array_to_need_priv(
|
|
const ObStmt *basic_stmt,
|
|
const uint64_t table_id,
|
|
ObOraNeedPriv &need_priv)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("basic_stmt is NULL", K(ret));
|
|
} else {
|
|
stmt::StmtType stmt_type = basic_stmt->get_stmt_type();
|
|
switch (stmt_type) {
|
|
case stmt::T_INSERT: {
|
|
need_priv.col_id_array_.reset();
|
|
const ObInsertStmt *insert_stmt = NULL;
|
|
insert_stmt = dynamic_cast<const ObInsertStmt*>(basic_stmt);
|
|
if (OB_ISNULL(insert_stmt)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("insert_stmt is NULL", K(ret));
|
|
} else {
|
|
ObColumnRefRawExpr *value_desc = NULL;
|
|
for (int i = 0; OB_SUCC(ret) && i < insert_stmt->get_values_desc().count(); ++i) {
|
|
if (OB_ISNULL(value_desc = insert_stmt->get_values_desc().at(i))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("value_desc is null", K(ret));
|
|
} else if (table_id == value_desc->get_table_id()) {
|
|
OZ (need_priv.col_id_array_.push_back(value_desc->get_column_id()));
|
|
}
|
|
}
|
|
}
|
|
if (need_priv.col_id_array_.count() > 0) {
|
|
need_priv.obj_level_ = OBJ_LEVEL_FOR_COL_PRIV;
|
|
}
|
|
break;
|
|
}
|
|
case stmt::T_UPDATE:{
|
|
need_priv.col_id_array_.reset();
|
|
const ObUpdateStmt *update_stmt = NULL;
|
|
update_stmt = dynamic_cast<const ObUpdateStmt*>(basic_stmt);
|
|
if (OB_ISNULL(update_stmt)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("update_stmt is null", K(ret));
|
|
} else {
|
|
for (int i = 0; OB_SUCC(ret) && i < update_stmt->get_update_table_info().count(); ++i) {
|
|
ObUpdateTableInfo* table_info = update_stmt->get_update_table_info().at(i);
|
|
if (OB_ISNULL(table_info)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("get null table info", K(ret));
|
|
} else if (table_info->table_id_ == table_id) {
|
|
const ObAssignments &assigns = table_info->assignments_;
|
|
for (int j = 0; OB_SUCC(ret) && j < assigns.count(); ++j) {
|
|
const ObColumnRefRawExpr *col_expr = assigns.at(i).column_expr_;
|
|
if (OB_ISNULL(col_expr)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("(col_expr is null");
|
|
} else if (col_expr->get_table_id() == table_id){
|
|
OZ (need_priv.col_id_array_.push_back(col_expr->get_column_id()));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (need_priv.col_id_array_.count() > 0) {
|
|
need_priv.obj_level_ = OBJ_LEVEL_FOR_COL_PRIV;
|
|
}
|
|
break;
|
|
}
|
|
default : {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int set_privs_by_table_item_recursively(
|
|
uint64_t user_id,
|
|
const ObSqlCtx &ctx,
|
|
const TableItem* table_item,
|
|
ObPackedObjPriv &packed_privs,
|
|
ObIArray<ObOraNeedPriv> &need_privs,
|
|
uint64_t check_flag,
|
|
const ObStmt *basic_stmt)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool is_stack_overflow = false;
|
|
ObOraNeedPriv need_priv;
|
|
if (OB_FAIL(check_stack_overflow(is_stack_overflow))) {
|
|
LOG_WARN("failed to check stack overflow", K(ret));
|
|
} else if (is_stack_overflow) {
|
|
ret = OB_SIZE_OVERFLOW;
|
|
LOG_WARN("too deep recursive", K(ret), K(is_stack_overflow));
|
|
}
|
|
CK (table_item != NULL);
|
|
CK (ctx.schema_guard_ != NULL);
|
|
if (OB_SUCC(ret)) {
|
|
if (TableItem::BASE_TABLE == table_item->type_
|
|
|| TableItem::ALIAS_TABLE == table_item->type_) {
|
|
if (!is_ora_virtual_table(table_item->ref_id_)) {
|
|
need_priv.db_name_ = table_item->database_name_;
|
|
need_priv.grantee_id_ = user_id;
|
|
need_priv.obj_id_ = table_item->ref_id_;
|
|
need_priv.obj_level_ = OBJ_LEVEL_FOR_TAB_PRIV;
|
|
need_priv.obj_type_ = static_cast<uint64_t>(ObObjectType::TABLE);
|
|
need_priv.obj_privs_ = packed_privs;
|
|
need_priv.check_flag_ = check_flag;
|
|
// Add inserted column id
|
|
OZ (add_col_id_array_to_need_priv(basic_stmt, table_item->table_id_, need_priv));
|
|
OZ (set_need_priv_owner_id(ctx, need_priv));
|
|
OZ (add_need_priv(need_privs, need_priv));
|
|
}
|
|
} else if (table_item->is_view_table_) {
|
|
if (!table_item->alias_name_.empty()) {
|
|
TableItem new_table_item;
|
|
OZ (mock_table_item(ctx, table_item, new_table_item));
|
|
OZ (set_privs_by_table_item_recursively(user_id, ctx, &new_table_item,
|
|
packed_privs, need_privs, check_flag, basic_stmt));
|
|
} else {
|
|
bool need_check = true;
|
|
if (is_sys_view(table_item->ref_id_)) {
|
|
/* oracle的字典视图(dba_*)需要做检查,其他系统视图(all_*, user_*, 性能视图(v$)不做权限检查 */
|
|
need_check = table_item->is_oracle_dba_sys_view();
|
|
} else {
|
|
need_check = true;
|
|
}
|
|
if (OB_SUCC(ret) && need_check) {
|
|
uint64_t view_owner_id;
|
|
|
|
/* 1. 对于视图,先记录视图id */
|
|
need_priv.db_name_ = table_item->database_name_;
|
|
need_priv.grantee_id_ = user_id;
|
|
need_priv.obj_id_ = table_item->ref_id_;
|
|
need_priv.obj_level_ = OBJ_LEVEL_FOR_TAB_PRIV;
|
|
need_priv.obj_type_ = static_cast<uint64_t>(ObObjectType::VIEW);
|
|
need_priv.obj_privs_ = packed_privs;
|
|
need_priv.check_flag_ = check_flag;
|
|
|
|
OZ (get_view_owner_id(ctx, table_item, view_owner_id));
|
|
OX (need_priv.owner_id_ = view_owner_id);
|
|
OZ (add_need_priv(need_privs, need_priv));
|
|
|
|
/* 2.1 对于insert,update,delete视图,
|
|
需要记录view的owner对基表的权限 */
|
|
if (table_item->view_base_item_ != NULL) {
|
|
OZ (set_privs_by_table_item_recursively(view_owner_id,
|
|
ctx,
|
|
table_item->view_base_item_,
|
|
packed_privs,
|
|
need_privs,
|
|
check_flag,
|
|
basic_stmt));
|
|
}
|
|
/* 2.2 对于select语句,
|
|
需要记录view的owner对视图定义里面的所有表,视图的权限 */
|
|
if (table_item->ref_query_ != NULL && basic_stmt != NULL
|
|
&& stmt::T_SELECT == basic_stmt->get_stmt_type()) {
|
|
OZ (ObPrivilegeCheck::get_stmt_ora_need_privs(view_owner_id,
|
|
ctx,
|
|
table_item->ref_query_,
|
|
need_privs,
|
|
check_flag));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_proc_db_name(
|
|
const ObSqlCtx &ctx,
|
|
ObOraNeedPriv &need_priv)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(ctx.session_info_) || OB_ISNULL(ctx.schema_guard_)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected null", K(ret));
|
|
} else {
|
|
uint64_t tenant_id = ctx.session_info_->get_login_tenant_id();
|
|
ObSchemaGetterGuard &schema_guard = *ctx.schema_guard_;
|
|
uint64_t db_id = OB_INVALID_ID;
|
|
const ObDatabaseSchema *db_schema = NULL;
|
|
if (static_cast<uint64_t>(ObObjectType::FUNCTION) == need_priv.obj_type_) {
|
|
const ObRoutineInfo *routine_schema = NULL;
|
|
OZ (schema_guard.get_routine_info(tenant_id, need_priv.obj_id_, routine_schema));
|
|
CK (routine_schema != NULL);
|
|
OX (db_id = routine_schema->get_database_id());
|
|
} else if (static_cast<uint64_t>(ObObjectType::PACKAGE) == need_priv.obj_type_) {
|
|
const ObSimplePackageSchema *pkg_schema = NULL;
|
|
OZ (schema_guard.get_simple_package_info(tenant_id, need_priv.obj_id_, pkg_schema));
|
|
CK (pkg_schema != NULL);
|
|
OX (db_id = pkg_schema->get_database_id());
|
|
} else if (static_cast<uint64_t>(ObObjectType::TYPE) == need_priv.obj_type_) {
|
|
const ObUDTTypeInfo *type_schema = NULL;
|
|
OZ (schema_guard.get_udt_info(tenant_id, need_priv.obj_id_, type_schema));
|
|
CK (OB_NOT_NULL(type_schema));
|
|
OX (db_id = type_schema->get_database_id());
|
|
}
|
|
OZ (schema_guard.get_database_schema(tenant_id,
|
|
db_id,
|
|
db_schema));
|
|
CK (db_schema != NULL);
|
|
OX (need_priv.db_name_ = db_schema->get_database_name());
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_seq_db_name(
|
|
uint64_t tenant_id,
|
|
const ObSqlCtx &ctx,
|
|
uint64_t obj_id,
|
|
ObString &db_name)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
uint64_t db_id = OB_INVALID_ID;
|
|
const ObSequenceSchema *seq_schema = NULL;
|
|
const ObDatabaseSchema *db_schema = NULL;
|
|
CK(ctx.schema_guard_);
|
|
CK(ctx.session_info_);
|
|
OZ(ctx.session_info_->get_dblink_sequence_schema(obj_id, seq_schema));
|
|
if (OB_SUCC(ret) && NULL == seq_schema) {
|
|
OZ (ctx.schema_guard_->get_sequence_schema(tenant_id, obj_id, seq_schema));
|
|
CK (seq_schema != NULL);
|
|
}
|
|
OX (db_id = seq_schema->get_database_id());
|
|
OZ (ctx.schema_guard_->get_database_schema(tenant_id,
|
|
db_id,
|
|
db_schema));
|
|
CK (db_schema != NULL);
|
|
OX (db_name = db_schema->get_database_name());
|
|
return ret;
|
|
}
|
|
|
|
int add_udf_expr_priv(
|
|
const ObSqlCtx &ctx,
|
|
ObRawExpr *expr,
|
|
uint64_t user_id,
|
|
ObIArray<ObOraNeedPriv> &need_privs,
|
|
uint64_t check_flag)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool is_sys_udf = false;
|
|
ObOraNeedPriv need_priv;
|
|
ObString db_name;
|
|
ObPackedObjPriv packed_privs = 0;
|
|
ObUDFRawExpr *udf_expr = NULL;
|
|
if (OB_ISNULL(expr) || OB_ISNULL(udf_expr = static_cast<ObUDFRawExpr *>(expr))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected null", KPC(expr), K(ret));
|
|
} else if (0 == udf_expr->get_database_name().case_compare(OB_SYS_DATABASE_NAME)) {
|
|
is_sys_udf = true;
|
|
} else if (common::OB_INVALID_ID != udf_expr->get_type_id()) {
|
|
need_priv.obj_id_ = udf_expr->get_type_id();
|
|
need_priv.obj_type_ = static_cast<uint64_t>(ObObjectType::TYPE);
|
|
} else if (common::OB_INVALID_ID != udf_expr->get_pkg_id()) {
|
|
need_priv.obj_id_ = udf_expr->get_pkg_id();
|
|
need_priv.obj_type_ = static_cast<uint64_t>(ObObjectType::PACKAGE);
|
|
} else if (common::OB_INVALID_ID != udf_expr->get_udf_id()) {
|
|
need_priv.obj_id_ = udf_expr->get_udf_id();
|
|
need_priv.obj_type_ = static_cast<uint64_t>(ObObjectType::FUNCTION);
|
|
} else {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("invalid udf expr", KPC(udf_expr), K(ret));
|
|
}
|
|
if (OB_SUCC(ret) && !is_sys_udf) {
|
|
// todo: check sys udf privilege after grant privs to public role
|
|
need_priv.grantee_id_ = user_id;
|
|
need_priv.obj_level_ = OBJ_LEVEL_FOR_TAB_PRIV;
|
|
need_priv.check_flag_ = check_flag;
|
|
need_priv.db_name_ = udf_expr->get_database_name();
|
|
OZ (set_need_priv_owner_id(ctx, need_priv));
|
|
OZ (ObPrivPacker::pack_raw_obj_priv(NO_OPTION, OBJ_PRIV_ID_EXECUTE, packed_privs));
|
|
OX (need_priv.obj_privs_ = packed_privs);
|
|
OZ (add_need_priv(need_privs, need_priv));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int add_proc_priv_in_expr(
|
|
const ObSqlCtx &ctx,
|
|
ObRawExpr *expr,
|
|
uint64_t user_id,
|
|
ObIArray<ObOraNeedPriv> &need_privs,
|
|
uint64_t check_flag)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(expr)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected null expr", K(ret));
|
|
} else if (!expr->has_flag(CNT_PL_UDF)) {
|
|
// do nothing
|
|
} else if (expr->has_flag(IS_PL_UDF)) {
|
|
if (OB_FAIL(add_udf_expr_priv(ctx, expr, user_id, need_privs, check_flag))) {
|
|
LOG_WARN("failed to add udf expr priv", K(ret));
|
|
}
|
|
} else {
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < expr->get_param_count(); ++i) {
|
|
ObRawExpr *param_expr = expr->get_param_expr(i);
|
|
if (OB_FAIL(add_proc_priv_in_expr(ctx, param_expr, user_id, need_privs, check_flag))) {
|
|
LOG_WARN("failed to add proc priv in expr", K(ret));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int add_procs_priv_in_dml(
|
|
uint64_t user_id,
|
|
const ObSqlCtx &ctx,
|
|
const ObDMLStmt *dml_stmt,
|
|
ObIArray<ObOraNeedPriv> &need_privs,
|
|
uint64_t check_flag)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObOraNeedPriv need_priv;
|
|
ObString db_name;
|
|
ObPackedObjPriv packed_privs = 0;
|
|
CK (ctx.schema_guard_ != NULL);
|
|
CK (ctx.session_info_ != NULL);
|
|
CK (dml_stmt != NULL);
|
|
ObSEArray<ObRawExpr *, 8> relation_exprs;
|
|
if (OB_ISNULL(dml_stmt) || OB_ISNULL(dml_stmt->get_query_ctx())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected null", K(ret));
|
|
} else if (dml_stmt->get_relation_exprs(relation_exprs)) {
|
|
LOG_WARN("failed to get relation exprs", K(ret));
|
|
}
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < relation_exprs.count(); ++i) {
|
|
ObRawExpr *expr = relation_exprs.at(i);
|
|
if (OB_FAIL(add_proc_priv_in_expr(ctx, expr, user_id, need_privs, check_flag))) {
|
|
LOG_WARN("failed to add udf priv", K(ret));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int add_seqs_priv_in_dml_inner(
|
|
uint64_t user_id,
|
|
const ObSqlCtx &ctx,
|
|
const ObIArray<uint64_t> &seq_ids,
|
|
uint64_t priv,
|
|
ObIArray<ObOraNeedPriv> &need_privs,
|
|
uint64_t check_flag)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObOraNeedPriv need_priv;
|
|
ObString db_name;
|
|
ObPackedObjPriv packed_privs = 0;
|
|
for (int i = 0; OB_SUCC(ret) && i < seq_ids.count(); i++) {
|
|
const uint64_t obj_id = seq_ids.at(i);
|
|
need_priv.grantee_id_ = user_id;
|
|
need_priv.obj_id_ = obj_id;
|
|
need_priv.obj_level_ = OBJ_LEVEL_FOR_TAB_PRIV;
|
|
need_priv.obj_type_ = static_cast<uint64_t>(ObObjectType::SEQUENCE);
|
|
need_priv.check_flag_ = check_flag;
|
|
OZ (get_seq_db_name(ctx.session_info_->get_login_tenant_id(),
|
|
ctx,
|
|
obj_id, db_name));
|
|
OX (need_priv.db_name_ = db_name);
|
|
OZ (set_need_priv_owner_id(ctx, need_priv));
|
|
OZ (ObPrivPacker::pack_raw_obj_priv(NO_OPTION, priv, packed_privs));
|
|
OX (need_priv.obj_privs_ = packed_privs);
|
|
OZ (add_need_priv(need_privs, need_priv));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int add_seqs_priv_in_dml(
|
|
uint64_t user_id,
|
|
const ObSqlCtx &ctx,
|
|
const ObDMLStmt *dml_stmt,
|
|
ObIArray<ObOraNeedPriv> &need_privs,
|
|
uint64_t check_flag)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
CK (ctx.schema_guard_ != NULL);
|
|
CK (ctx.session_info_ != NULL);
|
|
CK (dml_stmt != NULL);
|
|
const common::ObIArray<uint64_t> &nextval_sequence_ids = dml_stmt->get_nextval_sequence_ids();
|
|
const common::ObIArray<uint64_t> &currval_sequence_ids = dml_stmt->get_currval_sequence_ids();
|
|
if (OB_SUCC(ret)) {
|
|
OZ (add_seqs_priv_in_dml_inner(user_id, ctx, nextval_sequence_ids, OBJ_PRIV_ID_SELECT,
|
|
need_privs, check_flag));
|
|
OZ (add_seqs_priv_in_dml_inner(user_id, ctx, currval_sequence_ids, OBJ_PRIV_ID_SELECT,
|
|
need_privs, check_flag));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/* You must have the INSERT and UPDATE object privileges on the
|
|
target table and the SELECT object privilege on the source table.
|
|
To specify the DELETE clause of the merge_update_clause,
|
|
you must also have the DELETE object privilege on the target table
|
|
**************************************************************
|
|
* Oracle的文档有误,目标表的select权限是无条件需要的。(12c上验证过) *
|
|
**************************************************************
|
|
target table: INSERT + UPDATE + SELECT
|
|
DELETE if has delete clause (note: 这里,oracle也没有
|
|
按照delete语句仔细处理,当where 1 > 0,也粗糙的增加了select权限。
|
|
目前,我们兼容oracle的做法。 )
|
|
source table: SELECT */
|
|
int get_merge_stmt_ora_need_privs(
|
|
uint64_t user_id,
|
|
const ObSqlCtx &ctx,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObOraNeedPriv> &need_privs,
|
|
uint64_t check_flag)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObPackedObjPriv packed_privs = 0;
|
|
const TableItem *target_table = NULL;
|
|
const TableItem *source_table = NULL;
|
|
|
|
const ObMergeStmt *merge_stmt = static_cast<const ObMergeStmt*>(basic_stmt);
|
|
OZ (ObPrivPacker::pack_raw_obj_priv(NO_OPTION, OBJ_PRIV_ID_UPDATE, packed_privs));
|
|
OZ (ObPrivPacker::append_raw_obj_priv(NO_OPTION, OBJ_PRIV_ID_INSERT, packed_privs));
|
|
OZ (ObPrivPacker::append_raw_obj_priv(NO_OPTION, OBJ_PRIV_ID_SELECT, packed_privs));
|
|
CK (merge_stmt != NULL);
|
|
/* add delete+select priv if has 'delete where clause' */
|
|
if (!merge_stmt->get_delete_condition_exprs().empty()) {
|
|
OZ (ObPrivPacker::append_raw_obj_priv(NO_OPTION, OBJ_PRIV_ID_DELETE, packed_privs));
|
|
}
|
|
|
|
OX (target_table = merge_stmt->get_table_item_by_id(merge_stmt->get_target_table_id()));
|
|
OX (source_table = merge_stmt->get_table_item_by_id(merge_stmt->get_source_table_id()));
|
|
CK (target_table != NULL && source_table != NULL);
|
|
/* first add target table */
|
|
if (OB_SUCC(ret) && (TableItem::BASE_TABLE == target_table->type_
|
|
|| TableItem::ALIAS_TABLE == target_table->type_
|
|
|| target_table->is_view_table_)) {
|
|
OZ (set_privs_by_table_item_recursively(user_id,
|
|
ctx, target_table, packed_privs, need_privs, check_flag, basic_stmt));
|
|
}
|
|
/* then add source table */
|
|
OZ (ObPrivPacker::pack_raw_obj_priv(NO_OPTION, OBJ_PRIV_ID_SELECT, packed_privs));
|
|
if (OB_SUCC(ret) && (TableItem::BASE_TABLE == source_table->type_
|
|
|| TableItem::ALIAS_TABLE == source_table->type_
|
|
|| source_table->is_view_table_)) {
|
|
OZ (set_privs_by_table_item_recursively(user_id,
|
|
ctx, source_table, packed_privs, need_privs, check_flag, basic_stmt));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_dml_stmt_ora_need_privs(
|
|
uint64_t user_id,
|
|
const ObSqlCtx &ctx,
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObOraNeedPriv> &need_privs,
|
|
uint64_t check_flag)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should not be NULL", K(ret));
|
|
} else {
|
|
ObOraNeedPriv need_priv;
|
|
stmt::StmtType stmt_type = basic_stmt->get_stmt_type();
|
|
switch (stmt_type) {
|
|
case stmt::T_SELECT : {
|
|
const ObSelectStmt *select_stmt = static_cast<const ObSelectStmt*>(basic_stmt);
|
|
if (select_stmt->is_from_show_stmt()) {
|
|
//do not check priv for show stmt.
|
|
//现在大部分show 语句都是在执行时过滤掉无权限看到的信息
|
|
break;
|
|
}
|
|
}//fall through for non-show select
|
|
case stmt::T_INSERT :
|
|
case stmt::T_REPLACE :
|
|
case stmt::T_DELETE :
|
|
case stmt::T_UPDATE :
|
|
case stmt::T_MERGE : {
|
|
ObPackedObjPriv packed_privs = 0;
|
|
ObString op_literal;
|
|
if (stmt::T_SELECT == stmt_type) {
|
|
OZ (ObPrivPacker::pack_raw_obj_priv(NO_OPTION, OBJ_PRIV_ID_SELECT, packed_privs));
|
|
if (check_flag == CHECK_FLAG_DIRECT) {
|
|
OZ (ObPrivPacker::append_raw_obj_priv(NO_OPTION, OBJ_PRIV_ID_UPDATE, packed_privs));
|
|
OZ (ObPrivPacker::append_raw_obj_priv(NO_OPTION, OBJ_PRIV_ID_INSERT, packed_privs));
|
|
OZ (ObPrivPacker::append_raw_obj_priv(NO_OPTION, OBJ_PRIV_ID_DELETE, packed_privs));
|
|
}
|
|
op_literal = ObString::make_string("SELECT");
|
|
} else if (stmt::T_INSERT == stmt_type) {
|
|
OZ (ObPrivPacker::pack_raw_obj_priv(NO_OPTION, OBJ_PRIV_ID_INSERT, packed_privs));
|
|
op_literal = ObString::make_string("INSERT");
|
|
if (static_cast<const ObInsertStmt*>(basic_stmt)->is_insert_up()) {
|
|
OZ (ObPrivPacker::append_raw_obj_priv(NO_OPTION, OBJ_PRIV_ID_UPDATE, packed_privs));
|
|
OZ (ObPrivPacker::append_raw_obj_priv(NO_OPTION, OBJ_PRIV_ID_SELECT, packed_privs));
|
|
op_literal = ObString::make_string("INSERT, UPDATE");
|
|
}
|
|
op_literal = ObString::make_string("INSERT");
|
|
} else if (stmt::T_REPLACE == stmt_type) {
|
|
OZ (ObPrivPacker::pack_raw_obj_priv(NO_OPTION, OBJ_PRIV_ID_DELETE, packed_privs));
|
|
op_literal = ObString::make_string("INSERT, DELETE");
|
|
} else if (stmt::T_DELETE == stmt_type) {
|
|
OZ (ObPrivPacker::pack_raw_obj_priv(NO_OPTION, OBJ_PRIV_ID_DELETE, packed_privs));
|
|
op_literal = ObString::make_string("DELETE");
|
|
} else if (stmt::T_UPDATE == stmt_type) {
|
|
OZ (ObPrivPacker::pack_raw_obj_priv(NO_OPTION, OBJ_PRIV_ID_UPDATE, packed_privs));
|
|
op_literal = ObString::make_string("UPDATE");
|
|
} else if (stmt::T_MERGE == stmt_type) {
|
|
OZ (get_merge_stmt_ora_need_privs(user_id, ctx, basic_stmt, need_privs, check_flag));
|
|
OX (op_literal = ObString::make_string("MERGE"));
|
|
} else { } //do nothing
|
|
const ObDMLStmt *dml_stmt = static_cast<const ObDMLStmt*>(basic_stmt);
|
|
OZ (add_nec_sel_priv_in_dml(dml_stmt, packed_privs));
|
|
OZ (add_procs_priv_in_dml(user_id, ctx, dml_stmt, need_privs, check_flag));
|
|
OZ (add_seqs_priv_in_dml(user_id, ctx, dml_stmt, need_privs, check_flag));
|
|
int64_t table_size = dml_stmt->get_table_size();
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < table_size; i++) {
|
|
const TableItem *table_item = dml_stmt->get_table_item(i);
|
|
if (OB_ISNULL(table_item)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("table item is null");
|
|
} else if (stmt::T_MERGE != stmt_type
|
|
&& (TableItem::BASE_TABLE == table_item->type_
|
|
|| TableItem::ALIAS_TABLE == table_item->type_
|
|
|| table_item->is_view_table_)) {
|
|
OZ (set_privs_by_table_item_recursively(user_id,
|
|
ctx, table_item, packed_privs, need_privs, check_flag, basic_stmt));
|
|
//need_priv.is_sys_table_ = table_item->is_system_table_;
|
|
//need_priv.priv_level_ = OB_PRIV_TABLE_LEVEL;
|
|
//no check for information_schema select
|
|
if (stmt::T_SELECT != dml_stmt->get_stmt_type()) {
|
|
if (OB_FAIL(ObPrivilegeCheck::can_do_operation_on_db(session_priv,
|
|
table_item->database_name_))) {
|
|
LOG_WARN("Can not do this operation on the database", K(session_priv),
|
|
K(ret), "stmt_type", dml_stmt->get_stmt_type());
|
|
} else if (ObPrivilegeCheck::is_mysql_org_table(table_item->database_name_,
|
|
table_item->table_name_)) {
|
|
ret = OB_ERR_NO_TABLE_PRIVILEGE;
|
|
LOG_USER_ERROR(OB_ERR_NO_TABLE_PRIVILEGE, op_literal.length(), op_literal.ptr(),
|
|
session_priv.user_name_.length(), session_priv.user_name_.ptr(),
|
|
session_priv.host_name_.length(),session_priv.host_name_.ptr(),
|
|
table_item->table_name_.length(), table_item->table_name_.ptr());
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (session_priv.is_tenant_changed()
|
|
&& 0 != table_item->database_name_.case_compare(OB_SYS_DATABASE_NAME)) {
|
|
ret = OB_ERR_NO_DB_PRIVILEGE;
|
|
LOG_USER_ERROR(OB_ERR_NO_DB_PRIVILEGE, session_priv.user_name_.length(),
|
|
session_priv.user_name_.ptr(),
|
|
session_priv.host_name_.length(),session_priv.host_name_.ptr(),
|
|
table_item->database_name_.length(),
|
|
table_item->database_name_.ptr());
|
|
}
|
|
}
|
|
/*if (OB_SUCC(ret)) {
|
|
if (table_item->is_oracle_all_or_user_sys_view()) {
|
|
need_priv.priv_set_ &= ~OB_PRIV_SELECT;
|
|
}
|
|
}*/
|
|
//OZ (add_need_priv(need_privs, need_priv));
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default: {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Stmt type error, should be DML stmt", K(ret), K(stmt_type));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_dml_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should not be NULL", K(ret));
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
stmt::StmtType stmt_type = basic_stmt->get_stmt_type();
|
|
switch (stmt_type) {
|
|
case stmt::T_SELECT : {
|
|
const ObSelectStmt *select_stmt = static_cast<const ObSelectStmt*>(basic_stmt);
|
|
if (select_stmt->is_from_show_stmt()) {
|
|
//do not check priv for show stmt.
|
|
//现在大部分show 语句都是在执行时过滤掉无权限看到的信息
|
|
break;
|
|
}
|
|
}//fall through for non-show select
|
|
case stmt::T_INSERT_ALL :
|
|
case stmt::T_INSERT :
|
|
case stmt::T_REPLACE :
|
|
case stmt::T_DELETE :
|
|
case stmt::T_UPDATE :
|
|
case stmt::T_MERGE : {
|
|
ObPrivSet priv_set = 0;
|
|
ObString op_literal;
|
|
if (stmt::T_SELECT == stmt_type) {
|
|
priv_set = OB_PRIV_SELECT;
|
|
op_literal = ObString::make_string("SELECT");
|
|
if (static_cast<const ObSelectStmt*>(basic_stmt)->is_select_into_outfile()) {
|
|
ObNeedPriv need_priv;
|
|
need_priv.priv_set_ = OB_PRIV_FILE;
|
|
need_priv.priv_level_ = OB_PRIV_USER_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
} else if (stmt::T_INSERT_ALL == stmt_type) {
|
|
priv_set = OB_PRIV_INSERT;
|
|
op_literal = ObString::make_string("INSERT ALL");
|
|
} else if (stmt::T_INSERT == stmt_type) {
|
|
priv_set = OB_PRIV_INSERT;
|
|
op_literal = ObString::make_string("INSERT");
|
|
if (static_cast<const ObInsertStmt*>(basic_stmt)->is_insert_up()) {
|
|
priv_set |= (OB_PRIV_UPDATE | OB_PRIV_SELECT);
|
|
op_literal = ObString::make_string("INSERT, UPDATE");
|
|
}
|
|
op_literal = ObString::make_string("INSERT");
|
|
} else if (stmt::T_REPLACE == stmt_type) {
|
|
priv_set = OB_PRIV_INSERT | OB_PRIV_DELETE;
|
|
op_literal = ObString::make_string("INSERT, DELETE");
|
|
} else if (stmt::T_DELETE == stmt_type) {
|
|
priv_set = OB_PRIV_DELETE | OB_PRIV_SELECT;
|
|
op_literal = ObString::make_string("DELETE");
|
|
} else if (stmt::T_UPDATE == stmt_type) {
|
|
priv_set = OB_PRIV_UPDATE | OB_PRIV_SELECT;
|
|
op_literal = ObString::make_string("UPDATE");
|
|
} else if (stmt::T_MERGE == stmt_type) {
|
|
priv_set = OB_PRIV_INSERT | OB_PRIV_DELETE | OB_PRIV_UPDATE | OB_PRIV_SELECT;
|
|
op_literal = ObString::make_string("MERGE");
|
|
} else { } //do nothing
|
|
const ObDMLStmt *dml_stmt = static_cast<const ObDMLStmt*>(basic_stmt);
|
|
int64_t table_size = dml_stmt->get_table_size();
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < table_size; i++) {
|
|
const TableItem *table_item = dml_stmt->get_table_item(i);
|
|
if (OB_ISNULL(table_item)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("table item is null");
|
|
} else if (table_item->is_link_table()) {
|
|
// skip link table
|
|
} else if (TableItem::BASE_TABLE == table_item->type_
|
|
|| TableItem::ALIAS_TABLE == table_item->type_
|
|
|| table_item->is_view_table_) {
|
|
need_priv.db_ = table_item->database_name_;
|
|
need_priv.table_ = table_item->table_name_;
|
|
need_priv.priv_set_ = priv_set;
|
|
need_priv.is_sys_table_ = table_item->is_system_table_;
|
|
need_priv.is_for_update_ = table_item->for_update_;
|
|
need_priv.priv_level_ = OB_PRIV_TABLE_LEVEL;
|
|
//no check for information_schema select
|
|
if (stmt::T_SELECT != dml_stmt->get_stmt_type()) {
|
|
if (OB_FAIL(ObPrivilegeCheck::can_do_operation_on_db(session_priv, table_item->database_name_))) {
|
|
LOG_WARN("Can not do this operation on the database", K(session_priv),
|
|
K(ret), "stmt_type", dml_stmt->get_stmt_type());
|
|
} else if (ObPrivilegeCheck::is_mysql_org_table(table_item->database_name_, table_item->table_name_)) {
|
|
ret = OB_ERR_NO_TABLE_PRIVILEGE;
|
|
LOG_USER_ERROR(OB_ERR_NO_TABLE_PRIVILEGE, op_literal.length(), op_literal.ptr(),
|
|
session_priv.user_name_.length(), session_priv.user_name_.ptr(),
|
|
session_priv.host_name_.length(),session_priv.host_name_.ptr(),
|
|
table_item->table_name_.length(), table_item->table_name_.ptr());
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (session_priv.is_tenant_changed()
|
|
&& 0 != table_item->database_name_.case_compare(OB_SYS_DATABASE_NAME)) {
|
|
ret = OB_ERR_NO_DB_PRIVILEGE;
|
|
LOG_USER_ERROR(OB_ERR_NO_DB_PRIVILEGE, session_priv.user_name_.length(), session_priv.user_name_.ptr(),
|
|
session_priv.host_name_.length(),session_priv.host_name_.ptr(),
|
|
table_item->database_name_.length(), table_item->database_name_.ptr());
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (table_item->is_view_table_ && !table_item->alias_name_.empty()) {
|
|
if (table_item->is_oracle_all_or_user_sys_view_for_alias()) {
|
|
need_priv.priv_set_ &= ~OB_PRIV_SELECT;
|
|
}
|
|
} else if (table_item->is_oracle_all_or_user_sys_view()) {
|
|
need_priv.priv_set_ &= ~OB_PRIV_SELECT;
|
|
}
|
|
}
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default: {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Stmt type error, should be DML stmt", K(ret), K(stmt_type));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_alter_table_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_ALTER_TABLE != basic_stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_ALTER_TABLE",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
const ObAlterTableStmt *stmt = static_cast<const ObAlterTableStmt*>(basic_stmt);
|
|
if (OB_FAIL(ObPrivilegeCheck::can_do_operation_on_db(session_priv, stmt->get_org_database_name()))) {
|
|
LOG_WARN("Can not alter table in the database", K(session_priv), K(ret),
|
|
"database_name", stmt->get_org_database_name());
|
|
} else if (ObPrivilegeCheck::is_mysql_org_table(stmt->get_org_database_name(),
|
|
stmt->get_org_table_name())
|
|
&& session_priv.tenant_id_ != OB_SYS_TENANT_ID) {
|
|
ret = OB_ERR_NO_TABLE_PRIVILEGE;
|
|
LOG_USER_ERROR(OB_ERR_NO_TABLE_PRIVILEGE, (int)strlen("ALTER"), "ALTER",
|
|
session_priv.user_name_.length(),session_priv.user_name_.ptr(),
|
|
session_priv.host_name_.length(),session_priv.host_name_.ptr(),
|
|
stmt->get_org_table_name().length(), stmt->get_org_table_name().ptr());
|
|
} else if (stmt->has_rename_action()) {
|
|
if (OB_FAIL(ObPrivilegeCheck::can_do_operation_on_db(session_priv, stmt->get_database_name()))) {
|
|
LOG_WARN("Can not alter table in the database", K(session_priv), K(ret),
|
|
"database_name", stmt->get_database_name());
|
|
} else {
|
|
need_priv.db_ = stmt->get_org_database_name();
|
|
need_priv.table_ = stmt->get_org_table_name();
|
|
need_priv.priv_set_ = OB_PRIV_ALTER | OB_PRIV_DROP;
|
|
need_priv.priv_level_ = OB_PRIV_TABLE_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
need_priv.db_ = stmt->get_database_name();
|
|
need_priv.table_ = stmt->get_table_name();
|
|
need_priv.priv_set_ = OB_PRIV_CREATE | OB_PRIV_INSERT;
|
|
need_priv.priv_level_ = OB_PRIV_TABLE_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
} else {
|
|
need_priv.db_ = stmt->get_org_database_name();
|
|
need_priv.table_ = stmt->get_org_table_name();
|
|
need_priv.priv_set_ = OB_PRIV_ALTER;
|
|
need_priv.priv_level_ = OB_PRIV_TABLE_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
|
|
const AlterTableSchema &alter_schema = const_cast<ObAlterTableStmt*>(stmt)->get_alter_table_arg().alter_table_schema_;
|
|
if (alter_schema.alter_option_bitset_.has_member(obrpc::ObAlterTableArg::SESSION_ACTIVE_TIME)
|
|
&& session_priv.tenant_id_ != OB_SYS_TENANT_ID) {
|
|
ret = OB_ERR_NO_PRIVILEGE;
|
|
LOG_USER_ERROR(OB_ERR_NO_PRIVILEGE, "SUPER");
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_create_database_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_CREATE_DATABASE != basic_stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_CREATE_DATABASE",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
const ObCreateDatabaseStmt *stmt = static_cast<const ObCreateDatabaseStmt*>(basic_stmt);
|
|
if (OB_FAIL(ret)) {
|
|
} else if (OB_FAIL(ObPrivilegeCheck::can_do_operation_on_db(session_priv, stmt->get_database_name()))) {
|
|
LOG_WARN("Can not create in the database", K(session_priv), "database_name", stmt->get_database_name(), K(ret));
|
|
} else {
|
|
need_priv.db_ = stmt->get_database_name();
|
|
need_priv.priv_set_ = OB_PRIV_CREATE;
|
|
need_priv.priv_level_ = OB_PRIV_DB_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_alter_database_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_ALTER_DATABASE != basic_stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_ALTER_DATABASE",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
const ObAlterDatabaseStmt *stmt = static_cast<const ObAlterDatabaseStmt*>(basic_stmt);
|
|
const ObString &db_name = stmt->get_database_name();
|
|
if (0 == db_name.case_compare(OB_INFORMATION_SCHEMA_NAME)
|
|
|| (0 == db_name.case_compare(OB_SYS_DATABASE_NAME)
|
|
&& !stmt->only_alter_primary_zone())) {
|
|
ret = OB_ERR_NO_DB_PRIVILEGE;
|
|
LOG_USER_ERROR(OB_ERR_NO_DB_PRIVILEGE, session_priv.user_name_.length(), session_priv.user_name_.ptr(),
|
|
session_priv.host_name_.length(), session_priv.host_name_.ptr(),
|
|
db_name.length(), db_name.ptr());
|
|
} else {
|
|
need_priv.db_ = stmt->get_database_name();
|
|
need_priv.priv_set_ = OB_PRIV_ALTER;
|
|
need_priv.priv_level_ = OB_PRIV_DB_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_drop_database_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_DROP_DATABASE != basic_stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_DROP_DATABASE",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
const ObDropDatabaseStmt *stmt = static_cast<const ObDropDatabaseStmt*>(basic_stmt);
|
|
if (OB_FAIL(ObPrivilegeCheck::can_do_drop_operation_on_db(session_priv, stmt->get_database_name()))) {
|
|
LOG_WARN("Can not drop information_schema database", K(ret));
|
|
} else {
|
|
need_priv.db_ = stmt->get_database_name();
|
|
need_priv.priv_set_ = OB_PRIV_DROP;
|
|
need_priv.priv_level_ = OB_PRIV_DB_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_create_table_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_CREATE_TABLE != basic_stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_CREATE_TABLE", K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
const ObCreateTableStmt *stmt = static_cast<const ObCreateTableStmt*>(basic_stmt);
|
|
if (OB_FAIL(ret)) {
|
|
} else if (OB_FAIL(ObPrivilegeCheck::can_do_operation_on_db(session_priv, stmt->get_database_name()))) {
|
|
LOG_WARN("Can not create table in information_schema database", K(session_priv), K(ret));
|
|
} else if (stmt->is_view_table()){
|
|
for (int64_t i = 0; i < stmt->get_view_need_privs().count(); i++) {
|
|
LOG_INFO("output need privs", K(stmt->get_view_need_privs().at(i)), K(i));
|
|
}
|
|
if (OB_FAIL(need_privs.assign(stmt->get_view_need_privs()))) {
|
|
LOG_WARN("fail to assign need_privs", K(ret));
|
|
}
|
|
} else {
|
|
const ObSelectStmt *select_stmt = stmt->get_sub_select();
|
|
if (NULL != select_stmt) {
|
|
need_priv.priv_set_ = OB_PRIV_CREATE | OB_PRIV_INSERT;
|
|
} else {
|
|
need_priv.priv_set_ = OB_PRIV_CREATE;
|
|
}
|
|
need_priv.db_ = stmt->get_database_name();
|
|
need_priv.table_ = stmt->get_table_name();
|
|
need_priv.priv_level_ = OB_PRIV_TABLE_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
if (OB_SUCC(ret) && NULL != select_stmt) {
|
|
OZ (ObPrivilegeCheck::get_stmt_need_privs(session_priv, select_stmt, need_privs));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_drop_table_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_DROP_TABLE != basic_stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_DROP_TABLE",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
const ObDropTableStmt *stmt = static_cast<const ObDropTableStmt*>(basic_stmt);
|
|
const ObIArray<obrpc::ObTableItem> &tables = stmt->get_drop_table_arg().tables_;
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < tables.count(); i++) {
|
|
const obrpc::ObTableItem &table_item = tables.at(i);
|
|
if (OB_FAIL(ObPrivilegeCheck::can_do_operation_on_db(session_priv, table_item.database_name_))) {
|
|
LOG_WARN("Can not drop table in information_schema database", K(session_priv), K(ret));
|
|
} else if (ObPrivilegeCheck::is_mysql_org_table(table_item.database_name_, table_item.table_name_)
|
|
&& session_priv.tenant_id_ != OB_SYS_TENANT_ID) {
|
|
ret = OB_ERR_NO_TABLE_PRIVILEGE;
|
|
LOG_USER_ERROR(OB_ERR_NO_TABLE_PRIVILEGE, (int)strlen("DROP"), "DROP",
|
|
session_priv.user_name_.length(), session_priv.user_name_.ptr(),
|
|
session_priv.host_name_.length(),session_priv.host_name_.ptr(),
|
|
table_item.table_name_.length(), table_item.table_name_.ptr());
|
|
} else {
|
|
need_priv.db_ = table_item.database_name_;
|
|
need_priv.table_ = table_item.table_name_;
|
|
need_priv.priv_set_ = OB_PRIV_DROP;
|
|
need_priv.priv_level_ = OB_PRIV_TABLE_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
}
|
|
if ((share::schema::TMP_TABLE == stmt->get_drop_table_arg().table_type_
|
|
|| share::schema::TMP_TABLE_ALL == stmt->get_drop_table_arg().table_type_)
|
|
&& common::OB_INVALID_ID != stmt->get_drop_table_arg().session_id_
|
|
&& session_priv.tenant_id_ != OB_SYS_TENANT_ID) {
|
|
ret = OB_ERR_NO_PRIVILEGE;
|
|
LOG_USER_ERROR(OB_ERR_NO_PRIVILEGE, "SUPER");
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
int get_create_synonym_priv(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
UNUSED(session_priv);
|
|
ObNeedPriv need_priv;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (stmt::T_CREATE_SYNONYM != basic_stmt->get_stmt_type()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected stmt type", K(basic_stmt->get_stmt_type()), K(ret));
|
|
} else if (OB_FAIL(ObPrivilegeCheck::can_do_operation_on_db(
|
|
session_priv, static_cast<const ObCreateSynonymStmt *>(basic_stmt)->get_database_name()))) {
|
|
LOG_WARN("Can not do this operation on the database", KPC(basic_stmt), K(ret));
|
|
} else {
|
|
need_priv.priv_set_ = OB_PRIV_CREATE_SYNONYM;
|
|
need_priv.priv_level_ = OB_PRIV_USER_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_create_dblink_priv(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
UNUSED(session_priv);
|
|
ObNeedPriv need_priv;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (stmt::T_CREATE_DBLINK != basic_stmt->get_stmt_type()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected stmt type", K(basic_stmt->get_stmt_type()), K(ret));
|
|
} else {
|
|
need_priv.priv_set_ = OB_PRIV_CREATE_DATABASE_LINK;
|
|
need_priv.priv_level_ = OB_PRIV_USER_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_drop_dblink_priv(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
UNUSED(session_priv);
|
|
ObNeedPriv need_priv;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (stmt::T_DROP_DBLINK != basic_stmt->get_stmt_type()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected stmt type", K(basic_stmt->get_stmt_type()), K(ret));
|
|
} else {
|
|
need_priv.priv_set_ = OB_PRIV_DROP_DATABASE_LINK;
|
|
need_priv.priv_level_ = OB_PRIV_USER_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_drop_synonym_priv(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
UNUSED(session_priv);
|
|
ObNeedPriv need_priv;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (stmt::T_DROP_SYNONYM != basic_stmt->get_stmt_type()) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected stmt type", K(basic_stmt->get_stmt_type()), K(ret));
|
|
} else if (OB_FAIL(ObPrivilegeCheck::can_do_operation_on_db(
|
|
session_priv, static_cast<const ObDropSynonymStmt *>(basic_stmt)->get_database_name()))) {
|
|
LOG_WARN("Can not do this operation on the database", KPC(basic_stmt), K(ret));
|
|
} else {
|
|
need_priv.priv_set_ = OB_PRIV_DROP;
|
|
need_priv.priv_level_ = OB_PRIV_USER_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_create_index_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_CREATE_INDEX != basic_stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_CREATE_INDEX",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
const ObCreateIndexStmt *stmt = static_cast<const ObCreateIndexStmt*>(basic_stmt);
|
|
if (OB_FAIL(ObPrivilegeCheck::can_do_operation_on_db(session_priv, stmt->get_database_name()))) {
|
|
LOG_WARN("Can not create index in information_schema database", K(session_priv), K(ret));
|
|
} else {
|
|
need_priv.db_ = stmt->get_database_name();
|
|
need_priv.table_ = stmt->get_table_name();
|
|
need_priv.priv_set_ = OB_PRIV_INDEX;
|
|
need_priv.priv_level_ = OB_PRIV_TABLE_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_drop_index_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_DROP_INDEX != basic_stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_DROP_INDEX",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
const ObDropIndexStmt *stmt = static_cast<const ObDropIndexStmt*>(basic_stmt);
|
|
if (OB_FAIL(ObPrivilegeCheck::can_do_operation_on_db(session_priv, stmt->get_database_name()))) {
|
|
LOG_WARN("Can not drop index in information_schema database", K(session_priv), K(ret));
|
|
} else {
|
|
need_priv.db_ = stmt->get_database_name();
|
|
need_priv.table_ = stmt->get_table_name();
|
|
need_priv.priv_set_ = OB_PRIV_INDEX;
|
|
need_priv.priv_level_ = OB_PRIV_TABLE_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_create_mlog_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", KR(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_CREATE_MLOG != basic_stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_CREATE_MLOG",
|
|
KR(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
const ObCreateMLogStmt *stmt = static_cast<const ObCreateMLogStmt*>(basic_stmt);
|
|
if (OB_FAIL(ObPrivilegeCheck::can_do_operation_on_db(session_priv, stmt->get_database_name()))) {
|
|
LOG_WARN("Can not create materialized view log in information_schema database",
|
|
KR(ret), K(session_priv));
|
|
} else {
|
|
// create mlog requires select privilege on base table
|
|
need_priv.db_ = stmt->get_database_name();
|
|
need_priv.table_ = stmt->get_table_name();
|
|
need_priv.priv_set_ = OB_PRIV_SELECT;
|
|
need_priv.priv_level_ = OB_PRIV_TABLE_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
|
|
need_priv.db_ = stmt->get_database_name();
|
|
need_priv.table_ = stmt->get_mlog_name();
|
|
need_priv.priv_set_ = OB_PRIV_CREATE;
|
|
need_priv.priv_level_ = OB_PRIV_TABLE_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_drop_mlog_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", KR(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_DROP_MLOG != basic_stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_DROP_MLOG",
|
|
KR(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
const ObDropMLogStmt *stmt = static_cast<const ObDropMLogStmt*>(basic_stmt);
|
|
if (OB_FAIL(ObPrivilegeCheck::can_do_operation_on_db(session_priv, stmt->get_database_name()))) {
|
|
LOG_WARN("Can not drop materialized view log in information_schema database",
|
|
KR(ret), K(session_priv));
|
|
} else {
|
|
need_priv.db_ = stmt->get_database_name();
|
|
need_priv.table_ = stmt->get_mlog_name();
|
|
need_priv.priv_set_ = OB_PRIV_DROP;
|
|
need_priv.priv_level_ = OB_PRIV_TABLE_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_grant_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_GRANT != basic_stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_GRANT",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
const ObGrantStmt *stmt = static_cast<const ObGrantStmt *>(basic_stmt);
|
|
if (OB_FAIL(ObPrivilegeCheck::can_do_grant_on_db_table(session_priv, stmt->get_priv_set(),
|
|
stmt->get_database_name(),
|
|
stmt->get_table_name()))) {
|
|
LOG_WARN("Can not grant information_schema database", K(ret));
|
|
} else if (stmt->need_create_user_priv() &&
|
|
!(session_priv.user_priv_set_ & OB_PRIV_CREATE_USER)) {
|
|
ret = OB_ERR_CREATE_USER_WITH_GRANT;
|
|
LOG_WARN("Need create user priv", K(ret), "user priv", ObPrintPrivSet(session_priv.user_priv_set_));
|
|
} else {
|
|
need_priv.db_ = stmt->get_database_name();
|
|
need_priv.table_ = stmt->get_table_name();
|
|
need_priv.priv_set_ = stmt->get_priv_set() | OB_PRIV_GRANT;
|
|
need_priv.priv_level_ = stmt->get_grant_level();
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_revoke_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_REVOKE != basic_stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_REVOKE",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
const ObRevokeStmt *stmt = static_cast<const ObRevokeStmt *>(basic_stmt);
|
|
if (OB_FAIL(ObPrivilegeCheck::can_do_grant_on_db_table(session_priv, stmt->get_priv_set(),
|
|
stmt->get_database_name(),
|
|
stmt->get_table_name()))) {
|
|
LOG_WARN("Can not grant information_schema database", K(ret));
|
|
} else if (lib::is_mysql_mode() && stmt->get_revoke_all()) {
|
|
//check privs at resolver
|
|
} else {
|
|
need_priv.db_ = stmt->get_database_name();
|
|
need_priv.table_ = stmt->get_table_name();
|
|
need_priv.priv_set_ = stmt->get_priv_set() | OB_PRIV_GRANT;
|
|
need_priv.priv_level_ = stmt->get_grant_level();
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_create_user_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
UNUSED(session_priv);
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
stmt::StmtType stmt_type = basic_stmt->get_stmt_type();
|
|
switch (stmt_type) {//TODO deleted switch
|
|
case stmt::T_LOCK_USER :
|
|
case stmt::T_ALTER_USER_PROFILE :
|
|
case stmt::T_ALTER_USER_PRIMARY_ZONE:
|
|
case stmt::T_ALTER_USER:
|
|
case stmt::T_SET_PASSWORD :
|
|
case stmt::T_RENAME_USER :
|
|
case stmt::T_DROP_USER :
|
|
case stmt::T_CREATE_USER : {
|
|
if (stmt::T_SET_PASSWORD == stmt_type
|
|
&& static_cast<const ObSetPasswordStmt*>(basic_stmt)->get_for_current_user()) {
|
|
} else {
|
|
need_priv.priv_set_ = OB_PRIV_CREATE_USER;
|
|
need_priv.priv_level_ = OB_PRIV_USER_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
break;
|
|
}
|
|
default: {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type not in types dealt in this function", K(ret), K(stmt_type));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_variable_set_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
UNUSED(session_priv);
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_VARIABLE_SET != basic_stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_VARIABLE_SET",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
const ObVariableSetStmt *stmt = static_cast<const ObVariableSetStmt *>(basic_stmt);
|
|
if (stmt->has_global_variable()) {
|
|
// Return alter system instead of super.
|
|
need_priv.priv_set_ = OB_PRIV_ALTER_SYSTEM;
|
|
need_priv.priv_level_ = OB_PRIV_USER_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_modify_tenant_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_MODIFY_TENANT != basic_stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_MODIFY_TENANT",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
const ObModifyTenantStmt *stmt = static_cast<const ObModifyTenantStmt *>(basic_stmt);
|
|
if (OB_SYS_TENANT_ID != session_priv.tenant_id_) {
|
|
if (!stmt->is_for_current_tenant()) {
|
|
ret = OB_ERR_NO_PRIVILEGE;
|
|
LOG_WARN("Only sys tenant can do this operation for other tenant", K(ret));
|
|
} else {
|
|
bool normal_tenant_can_do = false;
|
|
if (OB_FAIL(stmt->check_normal_tenant_can_do(normal_tenant_can_do))) {
|
|
LOG_WARN("Failed to check normal tenant can do the job", K(ret));
|
|
} else if (!normal_tenant_can_do) {
|
|
ret = OB_ERR_NO_PRIVILEGE;
|
|
LOG_WARN("Include operation normal tenant can not do", K(ret));
|
|
} else { }
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
need_priv.priv_set_ = OB_PRIV_ALTER_TENANT;
|
|
need_priv.priv_level_ = OB_PRIV_USER_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_lock_tenant_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_LOCK_TENANT != basic_stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_LOCK_TENANT",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
const ObLockTenantStmt *stmt = static_cast<const ObLockTenantStmt *>(basic_stmt);
|
|
if (OB_SYS_TENANT_ID != session_priv.tenant_id_) {
|
|
ret = OB_ERR_NO_PRIVILEGE;
|
|
LOG_WARN("Only sys tenant can do this operation", K(ret));
|
|
} else if (stmt->get_tenant_name() == OB_SYS_TENANT_NAME) {
|
|
ret = OB_ERR_NO_PRIVILEGE;
|
|
LOG_WARN("Can not lock sys tenant", K(ret));
|
|
} else {
|
|
need_priv.priv_set_ = OB_PRIV_SUPER;
|
|
need_priv.priv_level_ = OB_PRIV_USER_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_drop_tenant_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_DROP_TENANT != basic_stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_DROP_TENANT",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
const ObDropTenantStmt *stmt = static_cast<const ObDropTenantStmt *>(basic_stmt);
|
|
if (OB_SYS_TENANT_ID != session_priv.tenant_id_) {
|
|
ret = OB_ERR_NO_PRIVILEGE;
|
|
LOG_WARN("Only sys tenant can do this operation", K(ret));
|
|
} else if (stmt->get_tenant_name() == OB_SYS_TENANT_NAME
|
|
|| stmt->get_tenant_name() == OB_GTS_TENANT_NAME) {
|
|
ret = OB_ERR_NO_PRIVILEGE;
|
|
LOG_WARN("Can not drop sys or gts tenant", K(ret));
|
|
} else {
|
|
need_priv.priv_set_ = OB_PRIV_SUPER;
|
|
need_priv.priv_level_ = OB_PRIV_USER_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_truncate_table_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_TRUNCATE_TABLE != basic_stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_TRUNCATE_TABLE",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
const ObTruncateTableStmt *stmt = static_cast<const ObTruncateTableStmt *>(basic_stmt);
|
|
//as there is tenant id is truncate_table_arg, so I check this.
|
|
//And not allow truncate other tenant's table. Even sys tenant.
|
|
if (session_priv.tenant_id_ != stmt->get_tenant_id()) {
|
|
ret = OB_ERR_NO_PRIVILEGE;
|
|
LOG_WARN("Can not truncate other tenant's table. Should not be here except change"
|
|
"tenant which not suggested", K(ret));
|
|
} else if (OB_FAIL(ObPrivilegeCheck::can_do_operation_on_db(session_priv, stmt->get_database_name()))) {
|
|
LOG_WARN("Can not do this operation on the database", K(session_priv), K(ret));
|
|
} else {
|
|
need_priv.db_ = stmt->get_database_name();
|
|
need_priv.table_ = stmt->get_table_name();
|
|
need_priv.priv_set_ = OB_PRIV_DROP;
|
|
need_priv.priv_level_ = OB_PRIV_TABLE_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_rename_table_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_RENAME_TABLE != basic_stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_RENAME_TABLE",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
const ObRenameTableStmt *stmt = static_cast<const ObRenameTableStmt *>(basic_stmt);
|
|
if (session_priv.tenant_id_ != stmt->get_tenant_id()) {
|
|
ret = OB_ERR_NO_PRIVILEGE;
|
|
LOG_WARN("Can not rename other tenant's table. Should not be here except change"
|
|
"tenant which not suggested", K(ret));
|
|
} else {
|
|
const obrpc::ObRenameTableArg &arg = stmt->get_rename_table_arg();
|
|
for (int64_t idx = 0; OB_SUCC(ret) && idx < arg.rename_table_items_.count(); ++idx) {
|
|
const obrpc::ObRenameTableItem &table_item = arg.rename_table_items_.at(idx);
|
|
if (OB_FAIL(ObPrivilegeCheck::can_do_operation_on_db(session_priv, table_item.origin_db_name_))) {
|
|
LOG_WARN("Can not do this operation on the database", K(session_priv), K(ret));
|
|
} else if (OB_FAIL(ObPrivilegeCheck::can_do_operation_on_db(session_priv, table_item.new_db_name_))) {
|
|
LOG_WARN("Can not do this operation on the database", K(session_priv), K(ret));
|
|
} else {
|
|
need_priv.db_ = table_item.origin_db_name_;
|
|
need_priv.table_ = table_item.origin_table_name_;
|
|
need_priv.priv_set_ = OB_PRIV_DROP | OB_PRIV_ALTER;
|
|
need_priv.priv_level_ = OB_PRIV_TABLE_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
need_priv.db_ = table_item.new_db_name_;
|
|
need_priv.table_ = table_item.new_table_name_;
|
|
need_priv.priv_set_ = OB_PRIV_CREATE | OB_PRIV_INSERT;
|
|
need_priv.priv_level_ = OB_PRIV_TABLE_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_create_table_like_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_CREATE_TABLE_LIKE != basic_stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_CREATE_TABLE_LIKE",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
const ObCreateTableLikeStmt *stmt = static_cast<const ObCreateTableLikeStmt *>(basic_stmt);
|
|
if (OB_FAIL(ret)) {
|
|
} else if (session_priv.tenant_id_ != stmt->get_tenant_id()) {
|
|
ret = OB_ERR_NO_PRIVILEGE;
|
|
LOG_WARN("Can not create other tenant's table. Should not be here except change"
|
|
"tenant which not suggested", K(ret));
|
|
} else if (OB_FAIL(ObPrivilegeCheck::can_do_operation_on_db(session_priv, stmt->get_new_db_name()))) {
|
|
LOG_WARN("Can not do this operation on the database", K(session_priv), K(ret));
|
|
} else {
|
|
need_priv.db_ = stmt->get_origin_db_name();
|
|
need_priv.table_ = stmt->get_origin_table_name();
|
|
need_priv.priv_set_ = OB_PRIV_SELECT;
|
|
need_priv.priv_level_ = OB_PRIV_TABLE_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
need_priv.db_ = stmt->get_new_db_name();
|
|
need_priv.table_ = stmt->get_new_table_name();
|
|
need_priv.priv_set_ = OB_PRIV_CREATE;
|
|
need_priv.priv_level_ = OB_PRIV_TABLE_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_sys_tenant_super_priv(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_SYS_TENANT_ID != session_priv.tenant_id_ &&
|
|
stmt::T_ALTER_SYSTEM_SET_PARAMETER != basic_stmt->get_stmt_type() &&
|
|
stmt::T_REFRESH_TIME_ZONE_INFO != basic_stmt->get_stmt_type() &&
|
|
stmt::T_SWITCHOVER != basic_stmt->get_stmt_type()) {
|
|
ret = OB_ERR_NO_PRIVILEGE;
|
|
LOG_WARN("Only sys tenant can do this operation",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
need_priv.priv_set_ = OB_PRIV_SUPER;
|
|
need_priv.priv_level_ = OB_PRIV_USER_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_sys_tenant_alter_system_priv(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_SYS_TENANT_ID != session_priv.tenant_id_ &&
|
|
stmt::T_FLUSH_CACHE != basic_stmt->get_stmt_type() &&
|
|
stmt::T_ALTER_SYSTEM_SET_PARAMETER != basic_stmt->get_stmt_type() &&
|
|
stmt::T_FREEZE != basic_stmt->get_stmt_type() &&
|
|
stmt::T_CLEAR_MERGE_ERROR != basic_stmt->get_stmt_type() &&
|
|
stmt::T_ADMIN_MERGE != basic_stmt->get_stmt_type() &&
|
|
stmt::T_ARCHIVE_LOG != basic_stmt->get_stmt_type() &&
|
|
stmt::T_BACKUP_DATABASE != basic_stmt->get_stmt_type() &&
|
|
stmt::T_BACKUP_MANAGE != basic_stmt->get_stmt_type() &&
|
|
stmt::T_BACKUP_CLEAN != basic_stmt->get_stmt_type() &&
|
|
stmt::T_DELETE_POLICY != basic_stmt->get_stmt_type() &&
|
|
stmt::T_BACKUP_KEY != basic_stmt->get_stmt_type() &&
|
|
stmt::T_RECOVER != basic_stmt->get_stmt_type() &&
|
|
stmt::T_TABLE_TTL != basic_stmt->get_stmt_type() &&
|
|
stmt::T_ALTER_SYSTEM_RESET_PARAMETER != basic_stmt->get_stmt_type()) {
|
|
ret = OB_ERR_NO_PRIVILEGE;
|
|
LOG_WARN("Only sys tenant can do this operation",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
need_priv.priv_set_ = OB_PRIV_ALTER_SYSTEM;
|
|
need_priv.priv_level_ = OB_PRIV_USER_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_sys_tenant_create_resource_pool_priv(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_SYS_TENANT_ID != session_priv.tenant_id_) {
|
|
ret = OB_ERR_NO_PRIVILEGE;
|
|
LOG_WARN("Only sys tenant can do this operation",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else if (stmt::T_CREATE_RESOURCE_POOL != basic_stmt->get_stmt_type()
|
|
&& stmt::T_DROP_RESOURCE_POOL != basic_stmt->get_stmt_type()
|
|
&& stmt::T_ALTER_RESOURCE_POOL != basic_stmt->get_stmt_type()
|
|
&& stmt::T_SPLIT_RESOURCE_POOL != basic_stmt->get_stmt_type()
|
|
&& stmt::T_ALTER_RESOURCE_TENANT != basic_stmt->get_stmt_type()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be create/alter/drop/split resource pool",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
need_priv.priv_set_ = OB_PRIV_CREATE_RESOURCE_POOL;
|
|
need_priv.priv_level_ = OB_PRIV_USER_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_sys_tenant_create_resource_unit_priv(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_SYS_TENANT_ID != session_priv.tenant_id_) {
|
|
ret = OB_ERR_NO_PRIVILEGE;
|
|
LOG_WARN("Only sys tenant can do this operation",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else if (stmt::T_CREATE_RESOURCE_UNIT != basic_stmt->get_stmt_type()
|
|
&& stmt::T_ALTER_RESOURCE_UNIT != basic_stmt->get_stmt_type()
|
|
&& stmt::T_DROP_RESOURCE_UNIT != basic_stmt->get_stmt_type()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be create/alter/drop resource",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
need_priv.priv_set_ = OB_PRIV_CREATE_RESOURCE_UNIT;
|
|
need_priv.priv_level_ = OB_PRIV_USER_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_change_tenant_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
UNUSED(need_privs);
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_CHANGE_TENANT != basic_stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_CHANGE_TENANT",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else if (OB_SYS_TENANT_ID != session_priv.tenant_id_) {
|
|
ret = OB_ERR_NO_PRIVILEGE;
|
|
LOG_WARN("Only sys tenant can do this operation",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_boot_strap_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_BOOTSTRAP != basic_stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_BOOTSTRAP",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else if (OB_SYS_TENANT_ID != session_priv.tenant_id_) {
|
|
ret = OB_ERR_NO_PRIVILEGE;
|
|
LOG_WARN("Only sys tenant can do this operation", K(ret));
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
need_priv.priv_set_ = OB_PRIV_BOOTSTRAP;
|
|
need_priv.priv_level_ = OB_PRIV_USER_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_load_data_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
UNUSED(session_priv);
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_LOAD_DATA != basic_stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_LOAD_DATA",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
const ObLoadDataStmt *load_data_stmt = static_cast<const ObLoadDataStmt *>(basic_stmt);
|
|
if (OB_SUCC(ret)) {
|
|
ObNeedPriv need_priv;
|
|
need_priv.db_ = load_data_stmt->get_load_arguments().database_name_;
|
|
need_priv.table_ = load_data_stmt->get_load_arguments().table_name_;
|
|
need_priv.priv_set_ = OB_PRIV_INSERT;
|
|
need_priv.is_sys_table_ = false;
|
|
need_priv.is_for_update_ = false;
|
|
need_priv.priv_level_ = OB_PRIV_TABLE_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
ObNeedPriv need_priv;
|
|
need_priv.priv_set_ = OB_PRIV_FILE;
|
|
need_priv.priv_level_ = OB_PRIV_USER_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int get_create_tablegroup_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
UNUSED(session_priv);
|
|
int ret = OB_SUCCESS;
|
|
UNUSED(session_priv);
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_CREATE_TABLEGROUP != basic_stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_CREATE_TABLEGROUP",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
if (OB_SUCC(ret)) {
|
|
ObNeedPriv need_priv;
|
|
need_priv.priv_set_ = OB_PRIV_CREATE;
|
|
need_priv.priv_level_ = OB_PRIV_USER_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_drop_tablegroup_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_DROP_TABLEGROUP != basic_stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_DROP_TABLEGROUP",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
const ObDropTablegroupStmt *stmt = static_cast<const ObDropTablegroupStmt *>(basic_stmt);
|
|
if (OB_SYS_TENANT_ID != session_priv.tenant_id_
|
|
&& 0 == stmt->get_tablegroup_name().compare(OB_SYS_TABLEGROUP_NAME)) { //tablegroup case sensetitive
|
|
ret = OB_ERR_NO_PRIVILEGE;
|
|
LOG_WARN("Only sys tenant can do drop sys tablegroup",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
need_priv.priv_set_ = OB_PRIV_DROP;
|
|
need_priv.priv_level_ = OB_PRIV_USER_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_alter_tablegroup_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
UNUSED(session_priv);
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_ALTER_TABLEGROUP != basic_stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_ALTER_TABLEGROUP",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
need_priv.priv_set_ = OB_PRIV_ALTER;
|
|
need_priv.priv_level_ = OB_PRIV_USER_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_flashback_table_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
UNUSED(session_priv);
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (stmt::T_FLASHBACK_TABLE_FROM_RECYCLEBIN != basic_stmt->get_stmt_type()
|
|
&& stmt::T_FLASHBACK_TABLE_TO_SCN != basic_stmt->get_stmt_type()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_FLASHBACK_TABLE",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
need_priv.priv_set_ = OB_PRIV_SUPER;
|
|
need_priv.priv_level_ = OB_PRIV_USER_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_purge_recyclebin_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
UNUSED(session_priv);
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (stmt::T_PURGE_RECYCLEBIN != basic_stmt->get_stmt_type()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_PURGE_RECYCLEBIN",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
need_priv.priv_set_ = OB_PRIV_DROP;
|
|
need_priv.priv_level_ = OB_PRIV_USER_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_flashback_index_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
UNUSED(session_priv);
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_FLASHBACK_INDEX != basic_stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_FLASHBACK_TABLE",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
need_priv.priv_set_ = OB_PRIV_SUPER;
|
|
need_priv.priv_level_ = OB_PRIV_USER_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int get_flashback_database_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
UNUSED(session_priv);
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_FLASHBACK_DATABASE != basic_stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_FLASHBACK_DATABASE",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
need_priv.priv_set_ = OB_PRIV_SUPER;
|
|
need_priv.priv_level_ = OB_PRIV_USER_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_purge_table_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
UNUSED(session_priv);
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_PURGE_TABLE != stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_PURGE_TABLE",
|
|
K(ret), "stmt type", stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
need_priv.priv_set_ = OB_PRIV_SUPER;
|
|
need_priv.priv_level_ = OB_PRIV_USER_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_purge_index_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
UNUSED(session_priv);
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_PURGE_INDEX != stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_PURGE_INDEX",
|
|
K(ret), "stmt type", stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
need_priv.priv_set_ = OB_PRIV_SUPER;
|
|
need_priv.priv_level_ = OB_PRIV_USER_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_purge_database_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
UNUSED(session_priv);
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_PURGE_DATABASE != stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be PURGE_DATABASE",
|
|
K(ret), "stmt type", stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
need_priv.priv_set_ = OB_PRIV_SUPER;
|
|
need_priv.priv_level_ = OB_PRIV_USER_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
return ret;
|
|
|
|
}
|
|
|
|
int get_flashback_tenant_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
UNUSED(session_priv);
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_FLASHBACK_TENANT != basic_stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be T_FLASHBACK_TENANT",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
if (OB_SYS_TENANT_ID != session_priv.tenant_id_) {
|
|
ret = OB_ERR_NO_PRIVILEGE;
|
|
LOG_WARN("Only sys tenant can do this operation", K(ret));
|
|
} else {
|
|
need_priv.priv_set_ = OB_PRIV_SUPER;
|
|
need_priv.priv_level_ = OB_PRIV_USER_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
int get_purge_tenant_stmt_need_privs(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
UNUSED(session_priv);
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_UNLIKELY(stmt::T_PURGE_TENANT != stmt->get_stmt_type())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt type should be PURGE_TENANT",
|
|
K(ret), "stmt type", stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
if (OB_SYS_TENANT_ID != session_priv.tenant_id_) {
|
|
ret = OB_ERR_NO_PRIVILEGE;
|
|
LOG_WARN("Only sys tenant can do this operation", K(ret));
|
|
} else {
|
|
need_priv.priv_set_ = OB_PRIV_SUPER;
|
|
need_priv.priv_level_ = OB_PRIV_USER_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_restore_point_priv(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Basic stmt should be not be NULL", K(ret));
|
|
} else if (OB_SYS_TENANT_ID == session_priv.tenant_id_) {
|
|
ret = OB_ERR_NO_PRIVILEGE;
|
|
LOG_WARN("Only non sys tenant can do this operation",
|
|
K(ret), "stmt type", basic_stmt->get_stmt_type());
|
|
} else {
|
|
ObNeedPriv need_priv;
|
|
need_priv.priv_set_ = OB_PRIV_SELECT;
|
|
need_priv.priv_level_ = OB_PRIV_USER_LEVEL;
|
|
ADD_NEED_PRIV(need_priv);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
const ObGetStmtNeedPrivsFunc ObPrivilegeCheck::priv_check_funcs_[] =
|
|
{
|
|
#define OB_STMT_TYPE_DEF(stmt_type, priv_check_func, id, action_type) priv_check_func,
|
|
#include "sql/resolver/ob_stmt_type.h"
|
|
#undef OB_STMT_TYPE_DEF
|
|
};
|
|
|
|
|
|
/* 新的检查权限总入口。
|
|
mysql mode, 或者 oracle mode的_enable_priv_check = false,沿用老的权限check逻辑,
|
|
oracle mode并且_enable_priv_check = true,用新的权限check逻辑 */
|
|
int ObPrivilegeCheck::check_privilege_new(
|
|
const ObSqlCtx &ctx,
|
|
const ObStmt *basic_stmt,
|
|
ObStmtNeedPrivs &stmt_need_privs,
|
|
ObStmtOraNeedPrivs &stmt_ora_need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!ObSchemaChecker::is_ora_priv_check()) {
|
|
OZ (check_privilege(ctx, basic_stmt, stmt_need_privs));
|
|
} else {
|
|
if (ctx.disable_privilege_check_ == PRIV_CHECK_FLAG_DISABLE || ctx.is_remote_sql_) {
|
|
//do not check privilege
|
|
} else {
|
|
if (OB_ISNULL(basic_stmt)
|
|
|| OB_ISNULL(ctx.session_info_)
|
|
|| OB_ISNULL(ctx.schema_guard_)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("basic_stmt, ctx.session_info or ctx.schema_manager is NULL",
|
|
K(ret), K(basic_stmt), "session_info", ctx.session_info_,
|
|
"schema manager", ctx.schema_guard_);
|
|
} else if (basic_stmt->is_explain_stmt()) {
|
|
basic_stmt = static_cast<const ObExplainStmt*>(basic_stmt)->get_explain_query_stmt();
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Explain query stmt is NULL", K(ret));
|
|
}
|
|
} else {
|
|
//do nothing
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
common::ObSEArray<ObNeedPriv, 4> tmp_need_privs;
|
|
common::ObSEArray<ObOraNeedPriv, 4> tmp_ora_need_privs;
|
|
ObSessionPrivInfo session_priv;
|
|
ctx.session_info_->get_session_priv_info(session_priv);
|
|
session_priv.set_effective_tenant_id(ctx.session_info_->get_effective_tenant_id());
|
|
OZ (get_stmt_need_privs(session_priv, basic_stmt, tmp_need_privs));
|
|
OZ (stmt_need_privs.need_privs_.assign(tmp_need_privs));
|
|
/* set user id=-1, means: use current user executing sql and can change
|
|
user to be checked should be -1.
|
|
reason: normal sql stmt and inner sql stmt in pl can share plan cache
|
|
how to change user to be checked:
|
|
1. when execute pl, change priv_user_id in session
|
|
2. when check priv, use priv_user_id in session */
|
|
OZ (get_stmt_ora_need_privs(common::OB_INVALID_ID,
|
|
ctx,
|
|
basic_stmt,
|
|
tmp_ora_need_privs,
|
|
CHECK_FLAG_NORMAL));
|
|
OZ (stmt_ora_need_privs.need_privs_.assign(tmp_ora_need_privs));
|
|
if (OB_SUCC(ret) && !ctx.session_info_->has_user_super_privilege()) {
|
|
bool has_global_variable = false;
|
|
if (basic_stmt->get_stmt_type() == stmt::T_VARIABLE_SET) {
|
|
has_global_variable =
|
|
static_cast<const ObVariableSetStmt*>(basic_stmt)->has_global_variable();
|
|
}
|
|
if (ObStmt::is_write_stmt(basic_stmt->get_stmt_type(), has_global_variable)
|
|
&& OB_FAIL(ctx.schema_guard_->verify_read_only(
|
|
ctx.session_info_->get_effective_tenant_id(),
|
|
stmt_need_privs))) {
|
|
LOG_WARN("database or table is read only, cannot execute this stmt", K(ret));
|
|
}
|
|
} else {
|
|
//do nothing
|
|
}
|
|
//OZ (check_privilege(ctx, stmt_need_privs));
|
|
OZ (check_ora_privilege(ctx, stmt_ora_need_privs));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPrivilegeCheck::check_ora_privilege(
|
|
const ObSqlCtx &ctx,
|
|
const ObStmtOraNeedPrivs &stmt_ora_need_priv)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (ctx.disable_privilege_check_ == PRIV_CHECK_FLAG_DISABLE) {
|
|
//do not check privilege
|
|
} else if (OB_ISNULL(ctx.session_info_)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Session is NULL");
|
|
} else {
|
|
ObIArray<uint64_t> &role_id_array = ctx.session_info_->get_enable_role_array();
|
|
OZ (const_cast<ObSchemaGetterGuard *>(ctx.schema_guard_)->check_ora_priv(
|
|
ctx.session_info_->get_login_tenant_id(),
|
|
ctx.session_info_->get_priv_user_id(), stmt_ora_need_priv,
|
|
role_id_array),
|
|
K(ctx.session_info_->get_in_definer_named_proc()),
|
|
K(ctx.session_info_->get_user_id()),
|
|
ctx.session_info_->get_priv_user_id());
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPrivilegeCheck::check_privilege(
|
|
const ObSqlCtx &ctx,
|
|
const ObStmt *basic_stmt,
|
|
ObStmtNeedPrivs &stmt_need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (ctx.disable_privilege_check_ == PRIV_CHECK_FLAG_DISABLE || ctx.is_remote_sql_) {
|
|
//do not check privilege
|
|
//远端SQL生成执行计划不需要check权限,权限检查都在控制端完成,统一流程
|
|
} else {
|
|
if (OB_ISNULL(basic_stmt)
|
|
|| OB_ISNULL(ctx.session_info_)
|
|
|| OB_ISNULL(ctx.schema_guard_)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("basic_stmt, ctx.session_info or ctx.schema_manager is NULL",
|
|
K(ret), K(basic_stmt), "session_info", ctx.session_info_,
|
|
"schema manager", ctx.schema_guard_);
|
|
} else if (basic_stmt->is_explain_stmt()) {
|
|
basic_stmt = static_cast<const ObExplainStmt*>(basic_stmt)->get_explain_query_stmt();
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Explain query stmt is NULL", K(ret));
|
|
}
|
|
} else {
|
|
//do nothing
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
common::ObSEArray<ObNeedPriv, 4> tmp_need_privs;
|
|
ObSessionPrivInfo session_priv;
|
|
ctx.session_info_->get_session_priv_info(session_priv);
|
|
session_priv.set_effective_tenant_id(ctx.session_info_->get_effective_tenant_id());
|
|
if (OB_FAIL(get_stmt_need_privs(session_priv, basic_stmt, tmp_need_privs))) {
|
|
LOG_WARN("Get stmt need privs error", K(ret));
|
|
} else if (OB_FAIL(stmt_need_privs.need_privs_.assign(tmp_need_privs))) {
|
|
LOG_WARN("fail to assign need_privs", K(ret));
|
|
} else if (!ctx.session_info_->has_user_super_privilege()) {
|
|
bool has_global_variable = false;
|
|
if (basic_stmt->get_stmt_type() == stmt::T_VARIABLE_SET) {
|
|
has_global_variable = static_cast<const ObVariableSetStmt*>(basic_stmt)->has_global_variable();
|
|
}
|
|
if (ObStmt::is_write_stmt(basic_stmt->get_stmt_type(), has_global_variable)
|
|
&& OB_FAIL(ctx.schema_guard_->verify_read_only(
|
|
ctx.session_info_->get_effective_tenant_id(),
|
|
stmt_need_privs))) {
|
|
LOG_WARN("database or table is read only, cannot execute this stmt", K(ret));
|
|
}
|
|
} else {
|
|
//do nothing
|
|
}
|
|
if (OB_SUCC(ret) && OB_FAIL(check_privilege(ctx, stmt_need_privs))) {
|
|
LOG_WARN("privilege check not passed", K(ret));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPrivilegeCheck::check_privilege(
|
|
const ObSqlCtx &ctx,
|
|
const ObStmtNeedPrivs &stmt_need_priv)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (ctx.disable_privilege_check_ == PRIV_CHECK_FLAG_DISABLE) {
|
|
//do not check privilege
|
|
} else {
|
|
ObSessionPrivInfo session_priv;
|
|
if (OB_ISNULL(ctx.session_info_)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Session is NULL");
|
|
} else {
|
|
if (ctx.session_info_->get_user_id() == ctx.session_info_->get_priv_user_id()) {
|
|
ctx.session_info_->get_session_priv_info(session_priv);
|
|
} else if (OB_FAIL(const_cast<ObSchemaGetterGuard *>(ctx.schema_guard_)->get_session_priv_info(
|
|
ctx.session_info_->get_priv_tenant_id(),
|
|
ctx.session_info_->get_priv_user_id(),
|
|
ctx.session_info_->get_database_name(),
|
|
session_priv))) {
|
|
LOG_WARN("fail to get_session_priv_info", K(ret));
|
|
}
|
|
if (OB_FAIL(ret)) {
|
|
} else if (OB_UNLIKELY(!session_priv.is_valid())) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Session priv is invalid", "tenant_id", session_priv.tenant_id_,
|
|
"user_id", session_priv.user_id_, K(ret));
|
|
} else if (OB_FAIL(const_cast<ObSchemaGetterGuard *>(ctx.schema_guard_)->check_priv(
|
|
session_priv, stmt_need_priv))) {
|
|
LOG_WARN("No privilege", K(session_priv),
|
|
"disable check", ctx.disable_privilege_check_, K(ret));
|
|
} else {
|
|
//do nothing
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/* xinqi to do: 获取每个stmt需要的权限 */
|
|
int ObPrivilegeCheck::get_stmt_ora_need_privs(
|
|
uint64_t user_id,
|
|
const ObSqlCtx &ctx,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObOraNeedPriv> &need_privs,
|
|
uint64_t check_flag)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
const ObDMLStmt *dml_stmt = NULL;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt is NULL", K(ret));
|
|
} else if (OB_FAIL(one_level_stmt_ora_need_priv(user_id, ctx, basic_stmt,
|
|
need_privs, check_flag))) {
|
|
LOG_WARN("Failed to get one level stmt need priv", K(ret));
|
|
} else if (basic_stmt->is_show_stmt()
|
|
|| (stmt::T_SELECT == basic_stmt->get_stmt_type()
|
|
&& static_cast<const ObSelectStmt*>(basic_stmt)->is_from_show_stmt())) {
|
|
//do not check sub-stmt of show_stmt
|
|
} else if ((dml_stmt = dynamic_cast<const ObDMLStmt*>(basic_stmt))) {
|
|
ObArray<ObSelectStmt*> child_stmts;
|
|
if (OB_FAIL(dml_stmt->get_child_stmts(child_stmts))) {
|
|
LOG_WARN("get child stmt failed", K(ret));
|
|
}
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < child_stmts.count(); ++i) {
|
|
const ObSelectStmt *sub_stmt = child_stmts.at(i);
|
|
if (OB_ISNULL(sub_stmt)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Sub-stmt is NULL", K(ret));
|
|
} else if (sub_stmt->is_view_stmt()
|
|
&& (stmt::T_SELECT == basic_stmt->get_stmt_type()
|
|
|| stmt::T_INSERT == basic_stmt->get_stmt_type()
|
|
|| stmt::T_UPDATE == basic_stmt->get_stmt_type()
|
|
|| stmt::T_DELETE == basic_stmt->get_stmt_type())) {
|
|
//do not check privilege of view stmt, one level 已经递归处理了视图的情况
|
|
} else if (OB_FAIL(get_stmt_ora_need_privs(user_id,
|
|
ctx,
|
|
sub_stmt,
|
|
need_privs,
|
|
check_flag))) {
|
|
LOG_WARN("Failed to extract priv info of shild stmts", K(i), K(dml_stmt), K(ret));
|
|
} else {
|
|
//do nothing
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPrivilegeCheck::get_stmt_need_privs(const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const ObDMLStmt *dml_stmt = NULL;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt is NULL", K(ret));
|
|
} else if (OB_FAIL(one_level_stmt_need_priv(session_priv, basic_stmt, need_privs))) {
|
|
LOG_WARN("Failed to get one level stmt need priv", K(ret));
|
|
} else if (basic_stmt->is_show_stmt()
|
|
|| (stmt::T_SELECT == basic_stmt->get_stmt_type()
|
|
&& static_cast<const ObSelectStmt*>(basic_stmt)->is_from_show_stmt())) {
|
|
//do not check sub-stmt of show_stmt
|
|
} else if ((dml_stmt = dynamic_cast<const ObDMLStmt*>(basic_stmt))) {
|
|
ObArray<ObSelectStmt*> child_stmts;
|
|
if (OB_FAIL(dml_stmt->get_child_stmts(child_stmts))) {
|
|
LOG_WARN("get child stmt failed", K(ret));
|
|
}
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < child_stmts.count(); ++i) {
|
|
const ObSelectStmt *sub_stmt = child_stmts.at(i);
|
|
if (OB_ISNULL(sub_stmt)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Sub-stmt is NULL", K(ret));
|
|
} else if (sub_stmt->is_view_stmt() && ObStmt::is_dml_stmt(basic_stmt->get_stmt_type())) {
|
|
//do not check privilege of view stmt
|
|
} else if (OB_FAIL(get_stmt_need_privs(session_priv, sub_stmt, need_privs))) {
|
|
LOG_WARN("Failed to extract priv info of shild stmts", K(i), K(dml_stmt), K(ret));
|
|
} else {
|
|
//do nothing
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int adjust_objpriv_for_grant_obj(
|
|
const ObGrantStmt * grant_stmt,
|
|
int org_n_need_privs,
|
|
ObIArray<ObOraNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool need_adjust = true;
|
|
CK (grant_stmt != NULL);
|
|
const ObRawObjPrivArray &raw_obj_privs = grant_stmt->get_obj_priv_array();
|
|
if (OB_UNLIKELY(raw_obj_privs.count() == 0)) {
|
|
need_adjust = false;
|
|
} else if (raw_obj_privs.count() == 1 && raw_obj_privs.at(0) == OBJ_PRIV_ID_SELECT) {
|
|
need_adjust = false;
|
|
} else {
|
|
need_adjust = true;
|
|
}
|
|
if (need_adjust) {
|
|
ObPackedObjPriv packed_obj_privs;
|
|
OZ (ObPrivPacker::pack_raw_obj_priv_list(GRANT_OPTION,
|
|
raw_obj_privs, packed_obj_privs));
|
|
for (int i = org_n_need_privs; i < need_privs.count(); i ++) {
|
|
OX (need_privs.at(i).obj_privs_ = packed_obj_privs);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/* 检查references权限时,检查的是create table的owner。
|
|
例如: z1用户:
|
|
create table z3.t2(c1 int, c2 int, foreign key (c2) references z1.t1(c1));
|
|
如果z3没有z1.t1的引用权限,是无法建立表的。
|
|
*/
|
|
int get_reference_ora_need_privs(
|
|
const ObSqlCtx &ctx,
|
|
const ObString &user_name,
|
|
const common::ObSArray<obrpc::ObCreateForeignKeyArg> fk_array,
|
|
ObIArray<ObOraNeedPriv> &need_privs,
|
|
uint64_t check_flag)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
uint64_t user_id = OB_INVALID_ID;
|
|
ObOraNeedPriv need_priv;
|
|
ObPackedObjPriv packed_privs = 0;
|
|
uint64_t tenant_id = ctx.session_info_->get_login_tenant_id();
|
|
uint64_t table_id = OB_INVALID_ID;
|
|
|
|
for (int i = 0; OB_SUCC(ret) && i < fk_array.count(); i++) {
|
|
const obrpc::ObCreateForeignKeyArg &fk_arg = fk_array.at(i);
|
|
if (!fk_arg.parent_database_.empty() && !fk_arg.parent_table_.empty()) {
|
|
OZ (ObPrivPacker::pack_raw_obj_priv(NO_OPTION, OBJ_PRIV_ID_REFERENCES, packed_privs));
|
|
OX (need_priv.db_name_ = fk_arg.parent_database_);
|
|
OZ (ctx.schema_guard_->get_user_id(tenant_id, user_name, ObString(""), user_id));
|
|
OX (need_priv.grantee_id_ = user_id);
|
|
OZ (ctx.schema_guard_->get_table_id(tenant_id,
|
|
fk_arg.parent_database_,
|
|
fk_arg.parent_table_,
|
|
false /* is_index */,
|
|
share::schema::ObSchemaGetterGuard::NON_TEMP_WITH_NON_HIDDEN_TABLE_TYPE,
|
|
table_id));
|
|
OX (need_priv.obj_id_ = table_id);
|
|
OX (need_priv.obj_level_ = OBJ_LEVEL_FOR_TAB_PRIV);
|
|
OX (need_priv.obj_type_ = static_cast<uint64_t>(ObObjectType::TABLE));
|
|
OX (need_priv.obj_privs_ = packed_privs);
|
|
OX (need_priv.check_flag_ = check_flag);
|
|
OZ (add_need_priv(need_privs, need_priv));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_create_table_ora_need_privs(
|
|
uint64_t user_id,
|
|
const ObSqlCtx &ctx,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObOraNeedPriv> &need_privs,
|
|
uint64_t check_flag)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const ObCreateTableStmt * ddl_stmt = dynamic_cast<const ObCreateTableStmt*>(basic_stmt);
|
|
const ObAlterTableStmt * alter_stmt = dynamic_cast<const ObAlterTableStmt*>(basic_stmt);
|
|
if (ddl_stmt != NULL) {
|
|
if (ddl_stmt->get_sub_select() != NULL) {
|
|
OZ (ObPrivilegeCheck::get_stmt_ora_need_privs(user_id,
|
|
ctx,
|
|
ddl_stmt->get_sub_select(),
|
|
need_privs,
|
|
check_flag));
|
|
}
|
|
/* 对于create view语句,还需要check view的owner是否有依赖的table, view等的任何直接权限*/
|
|
if (ddl_stmt->is_view_stmt() && ddl_stmt->get_view_define() != NULL) {
|
|
ObString host_name(OB_DEFAULT_HOST_NAME);
|
|
const ObUserInfo* user_info = NULL;
|
|
|
|
CK (ctx.session_info_ != NULL);
|
|
OZ (ctx.schema_guard_->get_user_info(ctx.session_info_->get_login_tenant_id(),
|
|
ddl_stmt->get_database_name(),
|
|
host_name,
|
|
user_info));
|
|
CK (user_info != NULL);
|
|
OZ (ObPrivilegeCheck::get_stmt_ora_need_privs(user_info->get_user_id(),
|
|
ctx,
|
|
ddl_stmt->get_view_define(),
|
|
need_privs,
|
|
CHECK_FLAG_DIRECT));
|
|
|
|
}
|
|
/* add reference obj priv if necessary */
|
|
OZ (get_reference_ora_need_privs(ctx,
|
|
ddl_stmt->get_database_name(),
|
|
ddl_stmt->get_read_only_foreign_key_arg_list(),
|
|
need_privs,
|
|
check_flag));
|
|
} else if (alter_stmt != NULL) {
|
|
/* add reference obj priv if necessary */
|
|
OZ (get_reference_ora_need_privs(ctx,
|
|
alter_stmt->get_database_name(),
|
|
alter_stmt->get_read_only_foreign_key_arg_list(),
|
|
need_privs,
|
|
check_flag));
|
|
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_grant_ora_need_privs(
|
|
const ObSqlCtx &ctx,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObOraNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const ObGrantStmt * grant_stmt = dynamic_cast<const ObGrantStmt*>(basic_stmt);
|
|
if (grant_stmt != NULL && grant_stmt->get_ref_query() != NULL) {
|
|
ObString host_name(OB_DEFAULT_HOST_NAME);
|
|
const ObUserInfo* user_info = NULL;
|
|
int org_n_need_privs = 0;
|
|
|
|
/* ref query是视图定义的展开,视图的owner记录在grant stmt的database_name中*/
|
|
CK (ctx.schema_guard_ != NULL);
|
|
CK (ctx.session_info_ != NULL);
|
|
OZ (ctx.schema_guard_->get_user_info(ctx.session_info_->get_login_tenant_id(),
|
|
grant_stmt->get_database_name(),
|
|
host_name,
|
|
user_info));
|
|
CK (user_info != NULL);
|
|
OX (org_n_need_privs = need_privs.count());
|
|
OZ (ObPrivilegeCheck::get_stmt_ora_need_privs(user_info->get_user_id(),
|
|
ctx,
|
|
grant_stmt->get_ref_query(),
|
|
need_privs,
|
|
CHECK_FLAG_WITH_GRANT_OPTION));
|
|
OZ (adjust_objpriv_for_grant_obj(grant_stmt, org_n_need_privs, need_privs));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int sys_pkg_need_priv_check(uint64_t pkg_id, ObSchemaGetterGuard *schema_guard,
|
|
bool &need_check, uint64_t &pkg_spec_id,
|
|
bool &need_only_obj_check)
|
|
{
|
|
static const char *pkg_name_need_priv[] = {
|
|
/* add package's name here, who need to be check priv, for example */
|
|
"dbms_plan_cache",
|
|
"dbms_resource_manager",
|
|
};
|
|
static const char *pkg_name_only_need_obj_priv[] = {
|
|
/* add package's name here, who need to be check priv, for example */
|
|
"dbms_plan_cache",
|
|
};
|
|
int ret = OB_SUCCESS;
|
|
int64_t compatible_mode = lib::is_oracle_mode() ? COMPATIBLE_ORACLE_MODE
|
|
: COMPATIBLE_MYSQL_MODE;
|
|
need_check = false;
|
|
need_only_obj_check = false;
|
|
pkg_spec_id = OB_INVALID_ID;
|
|
const uint64_t tenant_id = pl::get_tenant_id_by_object_id(pkg_id);
|
|
if (OB_NOT_NULL(schema_guard) && OB_INVALID_ID != pkg_id) {
|
|
const ObSimplePackageSchema *pkg_schema = NULL;
|
|
if (OB_FAIL(schema_guard->get_simple_package_info(tenant_id, pkg_id, pkg_schema))) {
|
|
LOG_WARN("failed to get pkg schema", K(ret), K(tenant_id), K(pkg_id));
|
|
} else if (OB_ISNULL(pkg_schema)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("null pkg schema, unexpected", K(ret), K(pkg_id));
|
|
} else {
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < sizeof(pkg_name_need_priv)/ sizeof(const char *); ++i) {
|
|
if (0 == pkg_schema->get_package_name().case_compare(pkg_name_need_priv[i])) {
|
|
need_check = true;
|
|
for (int64_t j = 0; OB_SUCC(ret) && j < sizeof(pkg_name_need_priv)/ sizeof(const char *); ++j) {
|
|
if (0 == pkg_schema->get_package_name().case_compare(pkg_name_only_need_obj_priv[j])) {
|
|
need_only_obj_check = true;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (OB_SUCC(ret) && need_check) {
|
|
OZ (schema_guard->get_package_id(pkg_schema->get_tenant_id(),
|
|
pkg_schema->get_database_id(),
|
|
pkg_schema->get_package_name(),
|
|
PACKAGE_TYPE,
|
|
compatible_mode,
|
|
pkg_spec_id));
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_call_ora_need_privs(
|
|
const ObSqlCtx &ctx,
|
|
uint64_t user_id,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObOraNeedPriv> &need_privs,
|
|
uint64_t check_flag)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObOraNeedPriv need_priv;
|
|
ObPackedObjPriv packed_privs = 0;
|
|
ObCallProcedureStmt * call_stmt = const_cast<ObCallProcedureStmt *>(dynamic_cast<const ObCallProcedureStmt*>(basic_stmt));
|
|
if (call_stmt != NULL && call_stmt->get_call_proc_info() != NULL) {
|
|
need_priv.db_name_ = call_stmt->get_call_proc_info()->get_db_name();
|
|
uint64_t pkg_id = call_stmt->get_call_proc_info()->get_package_id();
|
|
/* 对于sys库的package,不需要权限 */
|
|
if (need_priv.db_name_ == OB_SYS_DATABASE_NAME
|
|
&& (OB_INVALID_ID == pkg_id
|
|
|| pl::get_tenant_id_by_object_id(pkg_id) == OB_SYS_TENANT_ID)) {
|
|
bool need_check_priv = false;
|
|
bool need_only_obj_check = false;
|
|
ObSQLSessionInfo *session_info = ctx.session_info_;
|
|
CK (OB_NOT_NULL(session_info));
|
|
uint64_t spec_id = OB_INVALID_ID;
|
|
OZ (sys_pkg_need_priv_check(pkg_id, ctx.schema_guard_, need_check_priv, spec_id,
|
|
need_only_obj_check));
|
|
LOG_DEBUG("check sys package priv", K(pkg_id), K(need_check_priv), K(ret));
|
|
if (need_check_priv) {
|
|
OX (need_priv.grantee_id_ = user_id);
|
|
/* mock user tenent schema id */
|
|
OX (need_priv.obj_id_ = pkg_id);
|
|
OX (need_priv.obj_type_ = need_only_obj_check ?
|
|
static_cast<uint64_t>(ObObjectType::SYS_PACKAGE_ONLY_OBJ_PRIV)
|
|
: static_cast<uint64_t>(ObObjectType::SYS_PACKAGE));
|
|
OX (need_priv.obj_level_ = OBJ_LEVEL_FOR_TAB_PRIV);
|
|
OX (need_priv.check_flag_ = check_flag);
|
|
OZ (set_need_priv_owner_id(ctx, need_priv));
|
|
OZ (ObPrivPacker::pack_raw_obj_priv(NO_OPTION, OBJ_PRIV_ID_EXECUTE, packed_privs));
|
|
OX (need_priv.obj_privs_ = packed_privs);
|
|
OZ (add_need_priv(need_privs, need_priv));
|
|
}
|
|
} else {
|
|
need_priv.grantee_id_ = user_id;
|
|
if (call_stmt->get_call_proc_info()->get_package_id() != OB_INVALID_ID) {
|
|
need_priv.obj_id_ = call_stmt->get_call_proc_info()->get_package_id();
|
|
need_priv.obj_type_ = static_cast<uint64_t>(ObObjectType::PACKAGE);
|
|
} else {
|
|
need_priv.obj_id_ = call_stmt->get_call_proc_info()->get_routine_id();
|
|
need_priv.obj_type_ = static_cast<uint64_t>(ObObjectType::PROCEDURE);
|
|
}
|
|
need_priv.obj_level_ = OBJ_LEVEL_FOR_TAB_PRIV;
|
|
need_priv.check_flag_ = check_flag;
|
|
OZ (set_need_priv_owner_id(ctx, need_priv));
|
|
OZ (ObPrivPacker::pack_raw_obj_priv(NO_OPTION, OBJ_PRIV_ID_EXECUTE, packed_privs));
|
|
OX (need_priv.obj_privs_ = packed_privs);
|
|
OZ (add_need_priv(need_privs, need_priv));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/* flashback table to scn
|
|
To flash back a table to an earlier SCN or timestamp,
|
|
1. you must have either the FLASHBACK object privilege on the table or the
|
|
FLASHBACK ANY TABLE system privilege.
|
|
2. In addition, you must have the READ or SELECT object privilege on the table,
|
|
and you must have the INSERT, DELETE, and ALTER object privileges on the table.
|
|
|
|
在resovle阶段,检查ddl相关的权限:flashback权限和alter 权限。
|
|
本阶段,检查dml相关权限:select,insert,delete */
|
|
int get_fb_tbl_scn_ora_need_privs(
|
|
const ObSqlCtx &ctx,
|
|
uint64_t user_id,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObOraNeedPriv> &need_privs,
|
|
uint64_t check_flag)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObOraNeedPriv need_priv;
|
|
ObPackedObjPriv packed_privs = 0;
|
|
const ObFlashBackTableToScnStmt * ddl_stmt =
|
|
dynamic_cast<const ObFlashBackTableToScnStmt*>(basic_stmt);
|
|
|
|
if (ddl_stmt != NULL) {
|
|
CK (ctx.session_info_ != NULL);
|
|
CK (ctx.schema_guard_ != NULL);
|
|
const obrpc::ObFlashBackTableToScnArg &arg = ddl_stmt->flashback_table_to_scn_arg_;
|
|
const ObSimpleTableSchemaV2 *simple_table_schema = NULL;
|
|
uint64_t db_id = OB_INVALID_ID;
|
|
uint64_t tenant_id = ctx.session_info_->get_login_tenant_id();
|
|
OZ (ObPrivPacker::pack_raw_obj_priv(NO_OPTION, OBJ_PRIV_ID_SELECT, packed_privs));
|
|
OZ (ObPrivPacker::append_raw_obj_priv(NO_OPTION, OBJ_PRIV_ID_INSERT, packed_privs));
|
|
OZ (ObPrivPacker::append_raw_obj_priv(NO_OPTION, OBJ_PRIV_ID_DELETE, packed_privs));
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < arg.tables_.count(); ++i) {
|
|
need_priv.db_name_ = arg.tables_.at(i).database_name_;
|
|
need_priv.grantee_id_ = user_id;
|
|
OZ (ctx.schema_guard_->get_database_id(tenant_id,
|
|
arg.tables_.at(i).database_name_,
|
|
db_id));
|
|
if (OB_SUCC(ret) && db_id == OB_INVALID_ID) {
|
|
ret = OB_ERR_BAD_DATABASE;
|
|
LOG_USER_ERROR(OB_ERR_BAD_DATABASE, arg.tables_.at(i).database_name_.length(),
|
|
arg.tables_.at(i).database_name_.ptr());
|
|
LOG_WARN("database not exists", K(ret), K(i), K(tenant_id),
|
|
K(arg.tables_.at(i).database_name_));
|
|
}
|
|
OZ (ctx.schema_guard_->get_simple_table_schema(tenant_id,
|
|
db_id,
|
|
arg.tables_.at(i).table_name_,
|
|
false,/*is index*/
|
|
simple_table_schema));
|
|
if (OB_SUCC(ret) && simple_table_schema == NULL) {
|
|
ret = OB_TABLE_NOT_EXIST;
|
|
LOG_WARN("table not exists", K(ret), K(i), K(tenant_id),
|
|
K(arg.tables_.at(i).table_name_), K(arg.tables_.at(i).database_name_));
|
|
}
|
|
OX (need_priv.obj_id_ = simple_table_schema->get_table_id());
|
|
OX (need_priv.obj_level_ = OBJ_LEVEL_FOR_TAB_PRIV);
|
|
OX (need_priv.obj_type_ = static_cast<uint64_t>(ObObjectType::TABLE));
|
|
OX (need_priv.obj_privs_ = packed_privs);
|
|
OX (need_priv.check_flag_ = check_flag);
|
|
OZ (set_need_priv_owner_id(ctx, need_priv));
|
|
OZ (add_need_priv(need_privs, need_priv));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int get_load_data_ora_need_privs(
|
|
const ObSqlCtx &ctx,
|
|
uint64_t user_id,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObOraNeedPriv> &need_privs,
|
|
uint64_t check_flag)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObOraNeedPriv need_priv;
|
|
ObPackedObjPriv packed_privs = 0;
|
|
const ObLoadDataStmt *cmd_stmt =
|
|
dynamic_cast<const ObLoadDataStmt*>(basic_stmt);
|
|
const ObDirectorySchema *directory_schema = NULL;
|
|
uint64_t tenant_id = ctx.session_info_->get_login_tenant_id();
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid args", K(ret), KP(basic_stmt));
|
|
} else if (OB_FAIL(ctx.schema_guard_->get_directory_schema_by_name(
|
|
tenant_id, "DEFAULT", directory_schema))) {
|
|
LOG_WARN("fail to get directory schema", K(ret), K(tenant_id));
|
|
} else if (OB_ISNULL(directory_schema)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("directory schema is null", K(ret), KP(directory_schema));
|
|
} else {
|
|
UNUSED(ctx);
|
|
OZ (ObPrivPacker::pack_raw_obj_priv(NO_OPTION, OBJ_PRIV_ID_INSERT, packed_privs));
|
|
OZ (ObPrivPacker::append_raw_obj_priv(NO_OPTION, OBJ_PRIV_ID_UPDATE, packed_privs));
|
|
need_priv.db_name_ = cmd_stmt->get_load_arguments().database_name_;
|
|
need_priv.grantee_id_ = user_id;
|
|
need_priv.obj_id_ = cmd_stmt->get_load_arguments().table_id_;
|
|
need_priv.obj_level_ = OBJ_LEVEL_FOR_TAB_PRIV;
|
|
need_priv.obj_type_ = static_cast<uint64_t>(ObObjectType::TABLE);
|
|
need_priv.obj_privs_ = packed_privs;
|
|
need_priv.check_flag_ = check_flag;
|
|
OZ (set_need_priv_owner_id(ctx, need_priv));
|
|
OZ (add_need_priv(need_privs, need_priv));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* 根据 stmt里面的数据库对象信息和stmt type,确定需要什么类型的权限 */
|
|
int ObPrivilegeCheck::one_level_stmt_ora_need_priv(
|
|
uint64_t user_id,
|
|
const ObSqlCtx &ctx,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObOraNeedPriv> &need_privs,
|
|
uint64_t check_flag)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSQLSessionInfo *session_info = ctx.session_info_;
|
|
ObSessionPrivInfo session_priv;
|
|
if (OB_ISNULL(session_info)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Session info is invalid", K(session_info), K(ret));
|
|
} else if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt is NULL", K(basic_stmt), K(ret));
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
stmt::StmtType stmt_type = basic_stmt->get_stmt_type();
|
|
if (stmt_type < 0
|
|
|| stmt::get_stmt_type_idx(stmt_type) >=
|
|
static_cast<int64_t>(sizeof(priv_check_funcs_) / sizeof(ObGetStmtNeedPrivsFunc))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Stmt type is error", K(ret), K(stmt_type));
|
|
} else if (session_info->is_tenant_changed()
|
|
&& !ObStmt::check_change_tenant_stmt(stmt_type)) {
|
|
ret = OB_NOT_SUPPORTED;
|
|
LOG_WARN("stmt invalid", K(ret), K(stmt_type));
|
|
LOG_USER_ERROR(OB_NOT_SUPPORTED, "tenant changed, statement");
|
|
} else {
|
|
switch (stmt_type) {
|
|
case stmt::T_SELECT:
|
|
case stmt::T_REPLACE:
|
|
case stmt::T_DELETE:
|
|
case stmt::T_UPDATE:
|
|
case stmt::T_MERGE:
|
|
case stmt::T_INSERT:
|
|
OZ (get_dml_stmt_ora_need_privs(user_id, ctx, session_priv,
|
|
basic_stmt, need_privs, check_flag));
|
|
break;
|
|
case stmt::T_CREATE_TABLE:
|
|
case stmt::T_ALTER_TABLE:
|
|
OZ (get_create_table_ora_need_privs(user_id, ctx, basic_stmt, need_privs, check_flag));
|
|
break;
|
|
case stmt::T_GRANT:
|
|
OZ (get_grant_ora_need_privs(ctx, basic_stmt, need_privs));
|
|
break;
|
|
case stmt::T_CALL_PROCEDURE:
|
|
OZ (get_call_ora_need_privs(ctx, user_id, basic_stmt, need_privs, check_flag));
|
|
break;
|
|
case stmt::T_FLASHBACK_TABLE_TO_SCN:
|
|
OZ (get_fb_tbl_scn_ora_need_privs(ctx, user_id, basic_stmt, need_privs, check_flag));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPrivilegeCheck::one_level_stmt_need_priv(const ObSessionPrivInfo &session_priv,
|
|
const ObStmt *basic_stmt,
|
|
ObIArray<ObNeedPriv> &need_privs)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(basic_stmt)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt is NULL", K(basic_stmt), K(ret));
|
|
} else if (OB_UNLIKELY(!session_priv.is_valid())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Session priv is invalid", K(ret), K(session_priv));
|
|
} else {
|
|
stmt::StmtType stmt_type = basic_stmt->get_stmt_type();
|
|
if (stmt_type < 0
|
|
|| stmt::get_stmt_type_idx(stmt_type) >= static_cast<int64_t>(sizeof(priv_check_funcs_) / sizeof(ObGetStmtNeedPrivsFunc))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Stmt type is error", K(ret), K(stmt_type));
|
|
} else if (session_priv.is_tenant_changed()
|
|
&& !ObStmt::check_change_tenant_stmt(stmt_type)
|
|
&& stmt_type != stmt::T_SYSTEM_GRANT
|
|
&& stmt_type != stmt::T_REFRESH_TIME_ZONE_INFO) {
|
|
ret = OB_NOT_SUPPORTED;
|
|
LOG_WARN("stmt invalid", K(ret), K(stmt_type), K(session_priv));
|
|
LOG_USER_ERROR(OB_NOT_SUPPORTED, "tenant changed, statement");
|
|
} else if (OB_ISNULL(priv_check_funcs_[stmt::get_stmt_type_idx(stmt_type)])) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("No stmt privilege check function", K(ret), K(stmt_type));
|
|
} else if (OB_FAIL(priv_check_funcs_[stmt::get_stmt_type_idx(stmt_type)](session_priv, basic_stmt, need_privs))) {
|
|
LOG_WARN("Failed to check priv", K(ret), K(stmt_type));
|
|
} else { }//do nothing
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPrivilegeCheck::can_do_operation_on_db(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObString &db_name)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (session_priv.is_tenant_changed()
|
|
&& 0 != db_name.case_compare(OB_SYS_DATABASE_NAME)) {
|
|
ret = OB_ERR_NO_DB_PRIVILEGE;
|
|
LOG_USER_ERROR(OB_ERR_NO_DB_PRIVILEGE, session_priv.user_name_.length(), session_priv.user_name_.ptr(),
|
|
session_priv.host_name_.length(),session_priv.host_name_.ptr(),
|
|
db_name.length(), db_name.ptr());
|
|
} else if (0 == db_name.case_compare(OB_INFORMATION_SCHEMA_NAME)
|
|
|| 0 == db_name.case_compare(OB_RECYCLEBIN_SCHEMA_NAME)
|
|
//|| 0 == db_name.case_compare(OB_MYSQL_SCHEMA_NAME)
|
|
|| 0 == db_name.case_compare(OB_SYS_DATABASE_NAME)) {
|
|
if (session_priv.tenant_id_ != OB_SYS_TENANT_ID) {
|
|
if ((0 == db_name.case_compare(OB_RECYCLEBIN_SCHEMA_NAME))
|
|
&& ((0 == session_priv.user_name_.compare(OB_RESTORE_USER_NAME))
|
|
|| (0 == session_priv.user_name_.compare(OB_DRC_USER_NAME)))) {
|
|
// do nothing,仅仅允许sync ddl user用户来operate recyclebin
|
|
} else {
|
|
ret = OB_ERR_NO_DB_PRIVILEGE;
|
|
LOG_USER_ERROR(OB_ERR_NO_DB_PRIVILEGE, session_priv.user_name_.length(), session_priv.user_name_.ptr(),
|
|
session_priv.host_name_.length(),session_priv.host_name_.ptr(),
|
|
db_name.length(), db_name.ptr());
|
|
}
|
|
} else {
|
|
//do nothing
|
|
}
|
|
} else {
|
|
//do nothing
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPrivilegeCheck::can_do_grant_on_db_table(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObPrivSet priv_set,
|
|
const ObString &db_name,
|
|
const ObString &table_name)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (session_priv.is_tenant_changed()) {
|
|
ret = OB_ERR_NO_DB_PRIVILEGE;
|
|
LOG_USER_ERROR(OB_ERR_NO_DB_PRIVILEGE, session_priv.user_name_.length(), session_priv.user_name_.ptr(),
|
|
session_priv.host_name_.length(),session_priv.host_name_.ptr(),
|
|
db_name.length(), db_name.ptr());
|
|
} else if (session_priv.tenant_id_ != OB_SYS_TENANT_ID) {
|
|
if (0 == db_name.case_compare(OB_INFORMATION_SCHEMA_NAME)
|
|
|| 0 == db_name.case_compare(OB_RECYCLEBIN_SCHEMA_NAME)
|
|
|| 0 == db_name.case_compare(OB_PUBLIC_SCHEMA_NAME)
|
|
|| 0 == db_name.case_compare(OB_SYS_DATABASE_NAME)) {
|
|
if (0 == db_name.case_compare(OB_INFORMATION_SCHEMA_NAME)
|
|
|| OB_PRIV_HAS_OTHER(priv_set, OB_PRIV_SELECT)) {
|
|
ret = OB_ERR_NO_DB_PRIVILEGE;
|
|
LOG_USER_ERROR(OB_ERR_NO_DB_PRIVILEGE, session_priv.user_name_.length(), session_priv.user_name_.ptr(),
|
|
session_priv.host_name_.length(),session_priv.host_name_.ptr(),
|
|
db_name.length(), db_name.ptr());
|
|
}
|
|
} else if (ObPrivilegeCheck::is_mysql_org_table(db_name, table_name)) {
|
|
if (OB_PRIV_HAS_OTHER(priv_set, OB_PRIV_SELECT)) {
|
|
ret = OB_ERR_NO_TABLE_PRIVILEGE;
|
|
const char *command = "NOT-SELECT";
|
|
LOG_USER_ERROR(OB_ERR_NO_TABLE_PRIVILEGE, (int)strlen(command), command,
|
|
session_priv.user_name_.length(), session_priv.user_name_.ptr(),
|
|
session_priv.host_name_.length(),session_priv.host_name_.ptr(),
|
|
table_name.length(), table_name.ptr());
|
|
}
|
|
} else { }//do nothing
|
|
} else {
|
|
if (0 == db_name.case_compare(OB_INFORMATION_SCHEMA_NAME)) {
|
|
ret = OB_ERR_NO_DB_PRIVILEGE;
|
|
LOG_USER_ERROR(OB_ERR_NO_DB_PRIVILEGE, session_priv.user_name_.length(), session_priv.user_name_.ptr(),
|
|
session_priv.host_name_.length(),session_priv.host_name_.ptr(),
|
|
db_name.length(), db_name.ptr());
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPrivilegeCheck::can_do_drop_operation_on_db(
|
|
const ObSessionPrivInfo &session_priv,
|
|
const ObString &db_name)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (session_priv.is_tenant_changed()) {
|
|
ret = OB_ERR_NO_DB_PRIVILEGE;
|
|
LOG_USER_ERROR(OB_ERR_NO_DB_PRIVILEGE, session_priv.user_name_.length(), session_priv.user_name_.ptr(),
|
|
session_priv.host_name_.length(),session_priv.host_name_.ptr(),
|
|
db_name.length(), db_name.ptr());
|
|
} else if (0 == db_name.case_compare(OB_INFORMATION_SCHEMA_NAME)
|
|
|| 0 == db_name.case_compare(OB_SYS_DATABASE_NAME)
|
|
|| 0 == db_name.case_compare(OB_RECYCLEBIN_SCHEMA_NAME)
|
|
|| 0 == db_name.case_compare(OB_PUBLIC_SCHEMA_NAME)
|
|
|| 0 == db_name.case_compare(OB_MYSQL_SCHEMA_NAME)) {
|
|
ret = OB_ERR_NO_DB_PRIVILEGE;
|
|
LOG_USER_ERROR(OB_ERR_NO_DB_PRIVILEGE, session_priv.user_name_.length(), session_priv.user_name_.ptr(),
|
|
session_priv.host_name_.length(),session_priv.host_name_.ptr(),
|
|
db_name.length(), db_name.ptr());
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
bool ObPrivilegeCheck::is_mysql_org_table(const ObString &db_name, const ObString &table_name)
|
|
{
|
|
bool bret = false;
|
|
if (0 == db_name.case_compare(OB_MYSQL_SCHEMA_NAME)) {
|
|
if (0 == table_name.case_compare("user") || 0 == table_name.case_compare("db")){
|
|
bret = true;
|
|
}
|
|
}
|
|
return bret;
|
|
}
|
|
|
|
int ObPrivilegeCheck::check_password_expired(const ObSqlCtx &ctx, const stmt::StmtType stmt_type)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (stmt::T_SET_PASSWORD == stmt_type) {
|
|
// do nothing
|
|
} else if (OB_ISNULL(ctx.session_info_)) {
|
|
ret = OB_NOT_INIT;
|
|
LOG_WARN("params's session info is null", K(ret));
|
|
} else if (ctx.session_info_->is_password_expired()) {
|
|
ret = OB_ERR_MUST_CHANGE_PASSWORD;
|
|
LOG_WARN("the password is out of date, please change the password", K(ret));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPrivilegeCheck::check_password_expired_on_connection(
|
|
const uint64_t tenant_id,
|
|
const uint64_t user_id,
|
|
ObSchemaGetterGuard &schema_guard,
|
|
ObSQLSessionInfo &session)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (ObOraSysChecker::is_super_user(user_id)) {
|
|
//do nothing
|
|
} else if (MYSQL_MODE == session.get_compatibility_mode()
|
|
&& OB_FAIL(check_password_life_time_mysql(tenant_id, user_id, schema_guard, session))) {
|
|
LOG_WARN("The current user's password may be out of date", K(ret), K(tenant_id), K(user_id));
|
|
} else if (ORACLE_MODE == session.get_compatibility_mode()
|
|
&& OB_FAIL(check_password_life_time_oracle(tenant_id, user_id, schema_guard, session))) {
|
|
LOG_WARN("The current user's password may be out of date", K(ret), K(tenant_id), K(user_id));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObPrivilegeCheck::check_password_life_time_mysql(
|
|
const uint64_t tenant_id,
|
|
const uint64_t user_id,
|
|
ObSchemaGetterGuard &schema_guard,
|
|
ObSQLSessionInfo &session)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const share::schema::ObUserInfo *user_info = NULL;
|
|
uint64_t password_life_time = 0;
|
|
if (OB_FAIL(session.get_sys_variable(share::SYS_VAR_DEFAULT_PASSWORD_LIFETIME,
|
|
password_life_time))) {
|
|
LOG_WARN("fail to get default_password_lifetime variable", K(ret));
|
|
} else if (password_life_time != ObPasswordLifeTime::FOREVER) {
|
|
if (OB_FAIL(schema_guard.get_user_info(tenant_id, user_id, user_info))) {
|
|
LOG_WARN("fail to get user info", K(ret), K(tenant_id), K(user_id));
|
|
} else if (NULL == user_info) {
|
|
ret = OB_USER_NOT_EXIST;
|
|
LOG_WARN("user is not exist", K(user_id), K(ret));
|
|
} else if (check_password_expired_time(user_info->get_password_last_changed(),
|
|
password_life_time)) {
|
|
session.set_password_expired(true);
|
|
LOG_WARN("the password may have expired", K(ret));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
bool ObPrivilegeCheck::check_password_expired_time(int64_t password_last_changed_ts,
|
|
int64_t password_life_time)
|
|
{
|
|
bool is_expired = false;
|
|
int64_t now = ObClockGenerator::getClock();
|
|
int64_t timeline = now - password_life_time * 24 * 60 * 60 * 1000 * 1000UL;
|
|
if (OB_UNLIKELY(timeline < 0)) {
|
|
/*do nothing*/
|
|
} else if ((uint64_t)(timeline) > (uint64_t)password_last_changed_ts) {
|
|
is_expired = true;
|
|
LOG_WARN_RET(OB_SUCCESS, "the password is out of date, please change the password");
|
|
}
|
|
return is_expired;
|
|
}
|
|
|
|
int ObPrivilegeCheck::check_password_life_time_oracle(
|
|
const uint64_t tenant_id,
|
|
const uint64_t user_id,
|
|
ObSchemaGetterGuard &schema_guard,
|
|
ObSQLSessionInfo &session)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
int64_t password_last_changed = INT64_MAX;
|
|
int64_t password_life_time = INT64_MAX;
|
|
int64_t password_grace_time = INT64_MAX;
|
|
if (OB_FAIL(schema_guard.get_user_password_expire_times(tenant_id,
|
|
user_id,
|
|
password_last_changed,
|
|
password_life_time,
|
|
password_grace_time))) {
|
|
LOG_WARN("fail to get user id and profile limit", K(ret));
|
|
} else {
|
|
int64_t now = ObTimeUtility::current_time();
|
|
if (password_life_time == INT64_MAX || password_last_changed + password_life_time > now) {
|
|
//do nothing
|
|
} else if (password_grace_time == INT64_MAX ||
|
|
password_last_changed + password_life_time + password_grace_time > now) {
|
|
int64_t expire_in_days = (now - password_last_changed + password_life_time) / USECS_PER_DAY;
|
|
LOG_WARN("the password will expire", K(expire_in_days));
|
|
} else {
|
|
// setting password expired flag on session allows user login to set password theirself
|
|
session.set_password_expired(true);
|
|
LOG_WARN("the password is expired", K(password_last_changed), K(password_life_time),
|
|
K(password_grace_time), K(ret));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#undef ADD_NEED_PRIV
|
|
|
|
}
|
|
}
|