/** * 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 "share/schema/ob_schema_getter_guard.h" #include "sql/privilege_check/ob_ora_priv_check.h" #include "share/schema/ob_sys_priv_type.h" #include "share/schema/ob_table_schema.h" #include "sql/engine/expr/ob_expr_user_can_access_obj.h" namespace oceanbase { using namespace share; using namespace schema; using namespace common; namespace sql { /* don't use grantor_id in obj_key */ int ObOraSysChecker::get_roles_obj_privs( ObSchemaGetterGuard &guard, const ObObjPrivSortKey &obj_key, ObPackedObjPriv &obj_privs, const bool fetch_public_role_flag, const ObIArray &role_id_array) { int ret = OB_SUCCESS; uint64_t tenant_id = obj_key.tenant_id_; uint64_t user_id = obj_key.grantee_id_; uint64_t role_id; const ObUserInfo *user_info = NULL; UNUSED(fetch_public_role_flag); obj_privs = 0; if (OB_FAIL(guard.get_user_info(tenant_id, user_id, user_info))) { LOG_WARN("failed 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 info is null", K(ret), K(user_id)); } else { for (int i = 0; OB_SUCC(ret) && i < role_id_array.count(); ++i) { ObObjPrivSortKey role_obj_key = obj_key; role_id = role_id_array.at(i); role_obj_key.grantee_id_ = role_id; ObPackedObjPriv tmp_privs = 0; /* merge privs of roles */ OZ (guard.get_obj_privs_in_ur_and_obj(tenant_id, role_obj_key, tmp_privs)); OX (obj_privs |= tmp_privs); } } return ret; } int ObOraSysChecker::get_user_sys_priv_in_roles( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, ObPackedPrivArray &packed_array_out, const bool fetch_public_role_flag, const ObIArray &role_id_array) { int ret = OB_SUCCESS; uint64_t role_id; const ObUserInfo *user_info = NULL; UNUSED(fetch_public_role_flag); packed_array_out.reset(); if (OB_FAIL(guard.get_user_info(tenant_id, user_id, user_info))) { LOG_WARN("failed 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 info is null", K(ret), K(user_id)); } else { for (int i = 0; OB_SUCC(ret) && i < role_id_array.count(); ++i) { ObSysPriv *tmp_sys_priv_p; ObPackedPrivArray tmp_sys_priv_array; role_id = role_id_array.at(i); OZ (guard.get_sys_priv_with_grantee_id(tenant_id, role_id, tmp_sys_priv_p)); if (OB_SUCC(ret) && tmp_sys_priv_p != NULL) { OZ (ObPrivPacker::merge_two_packed_array(packed_array_out, tmp_sys_priv_p->get_priv_array()), packed_array_out, tmp_sys_priv_p->get_priv_array()); } } } return ret; } int ObOraSysChecker::check_single_sys_priv_inner( const ObPackedPrivArray& sys_packed_array, const ObRawPriv p1) { int ret = OB_SUCCESS; bool exists = false; OZ (ObOraPrivCheck::raw_sys_priv_exists(p1, sys_packed_array, exists)); if (OB_SUCC(ret) && !exists) { ret = OB_ERR_NO_PRIVILEGE; } return ret; } int ObOraSysChecker::check_single_sys_priv_inner( const ObSysPriv *sys_priv, const ObRawPriv p1) { int ret = OB_SUCCESS; if (sys_priv == NULL) { ret = OB_ERR_NO_PRIVILEGE; } else { OZX1 (check_single_sys_priv_inner(sys_priv->get_priv_array(), p1), OB_ERR_NO_PRIVILEGE); } return ret; } int ObOraSysChecker::check_p1_in_single( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObRawPriv p1) { int ret = OB_SUCCESS; ObSysPriv *sys_priv = NULL; OZ (guard.get_sys_priv_with_grantee_id(tenant_id, user_id, sys_priv)); OZX1 (check_single_sys_priv_inner(sys_priv, p1), OB_ERR_NO_PRIVILEGE); return ret; } int ObOraSysChecker::check_p1_in_roles( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObRawPriv p1, const ObIArray &role_id_array) { int ret = OB_SUCCESS; ObPackedPrivArray sys_packed_array; OZ (get_user_sys_priv_in_roles(guard, tenant_id, user_id, sys_packed_array, true, role_id_array), tenant_id, user_id); OZX1 (check_single_sys_priv_inner(sys_packed_array, p1), OB_ERR_NO_PRIVILEGE); return ret; } /* check user 是否有多种系统权限的全部 1. 先check 自己的权限, 2. 然后check通过role间接拥有的权限 */ int ObOraSysChecker::check_plist_and( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObRawPrivArray &plist, const ObIArray &role_id_array, const uint64_t option) { int ret = OB_SUCCESS; OZX1 (check_plist_and_in_single(guard, tenant_id, user_id, plist, option), OB_ERR_NO_PRIVILEGE); if (ret == OB_ERR_NO_PRIVILEGE) { ret = OB_SUCCESS; OZX1 (check_plist_and_in_roles(guard, tenant_id, user_id, plist, role_id_array, option), OB_ERR_NO_PRIVILEGE, tenant_id, user_id, plist); } return ret; } /* check user 是否有多种系统权限的任一种 1. 先check 自己的权限, 2. 然后check通过role间接拥有的权限 */ int ObOraSysChecker::check_plist_or( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObRawPrivArray &plist, const ObIArray &role_id_array, const uint64_t option) { int ret = OB_SUCCESS; OZX1 (check_plist_or_in_single(guard, tenant_id, user_id, plist, option), OB_ERR_NO_PRIVILEGE); if (ret == OB_ERR_NO_PRIVILEGE) { ret = OB_SUCCESS; OZX1 (check_plist_or_in_roles(guard, tenant_id, user_id, plist, role_id_array, option), OB_ERR_NO_PRIVILEGE, tenant_id, user_id, plist); } return ret; } /* check user 是否有一种系统权限 1. 先check 自己的权限, 2. 然后check通过role间接拥有的权限 */ int ObOraSysChecker::check_p1( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObRawPriv p1, const ObIArray &role_id_array) { int ret = OB_SUCCESS; OZX1 (check_p1_in_single(guard, tenant_id, user_id, p1), OB_ERR_NO_PRIVILEGE); if (ret == OB_ERR_NO_PRIVILEGE) { ret = OB_SUCCESS; OZX1 (check_p1_in_roles(guard, tenant_id, user_id, p1, role_id_array), OB_ERR_NO_PRIVILEGE, tenant_id, user_id, p1); } return ret; } /* check user 是否有多一种系统权限的至少一种 */ int ObOraSysChecker::check_plist_or_in_roles( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObRawPrivArray &plist, const ObIArray &role_id_array, const uint64_t option) { int ret = OB_SUCCESS; bool exists; ObPackedPrivArray sys_packed_array; OZ (get_user_sys_priv_in_roles(guard, tenant_id, user_id, sys_packed_array, true, role_id_array), tenant_id, user_id); ObPackedPrivArray packed_privs; OZ (ObPrivPacker::pack_raw_priv_list(option, plist, packed_privs)); OZ (ObOraPrivCheck::packed_sys_priv_list_or_exists(packed_privs, sys_packed_array, exists)); if (OB_SUCC(ret) && !exists) { ret = OB_ERR_NO_PRIVILEGE; } return ret; } /* check user 是否有全部系统权限 */ int ObOraSysChecker::check_plist_and_in_roles( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObRawPrivArray &plist, const ObIArray &role_id_array, const uint64_t option) { int ret = OB_SUCCESS; bool exists; ObPackedPrivArray sys_packed_array; OZ (get_user_sys_priv_in_roles(guard, tenant_id, user_id, sys_packed_array, true, role_id_array), tenant_id, user_id); ObPackedPrivArray packed_privs; OZ (ObPrivPacker::pack_raw_priv_list(option, plist, packed_privs)); OZ (ObOraPrivCheck::packed_sys_priv_list_and_exists(packed_privs, sys_packed_array, exists)); if (OB_SUCC(ret) && !exists) { ret = OB_ERR_NO_PRIVILEGE; } return ret; } /* check user 是否有多一种系统权限的至少一种 */ int ObOraSysChecker::check_plist_and_in_single( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObRawPrivArray &plist, const uint64_t option) { int ret = OB_SUCCESS; bool exists; ObSysPriv *sys_priv = NULL; OZ (guard.get_sys_priv_with_grantee_id(tenant_id, user_id, sys_priv)); if (OB_SUCC(ret)) { if (sys_priv == NULL) { ret = OB_ERR_NO_PRIVILEGE; } else { ObPackedPrivArray packed_privs; OZ (ObPrivPacker::pack_raw_priv_list(option, plist, packed_privs)); OZ (ObOraPrivCheck::packed_sys_priv_list_and_exists(packed_privs, sys_priv->get_priv_array(), exists)); if (OB_SUCC(ret) && !exists) { ret = OB_ERR_NO_PRIVILEGE; } } } return ret; } /* check user 是否有多一种系统权限的至少一种 */ int ObOraSysChecker::check_plist_or_in_single( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObRawPrivArray &plist, const uint64_t option) { int ret = OB_SUCCESS; bool exists; ObSysPriv *sys_priv = NULL; OZ (guard.get_sys_priv_with_grantee_id(tenant_id, user_id, sys_priv)); if (OB_SUCC(ret)) { if (sys_priv == NULL) { ret = OB_ERR_NO_PRIVILEGE; } else { ObPackedPrivArray packed_privs; OZ (ObPrivPacker::pack_raw_priv_list(option, plist, packed_privs)); OZ (ObOraPrivCheck::packed_sys_priv_list_or_exists(packed_privs, sys_priv->get_priv_array(), exists)); if (OB_SUCC(ret) && !exists) { ret = OB_ERR_NO_PRIVILEGE; } } } return ret; } /* check user 的rolearray中是否有多个对象权限的至少一种 */ int ObOraSysChecker::check_obj_plist_or_in_roles( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const uint64_t obj_type, const uint64_t obj_id, const uint64_t col_id, const ObRawObjPrivArray &plist, const ObIArray &role_id_array) { int ret = OB_SUCCESS; ObObjPrivSortKey obj_key(tenant_id, obj_id, obj_type, col_id, user_id, user_id); ObPackedObjPriv tmp_privs = 0; ObPackedObjPriv packed_privs; bool exists = false; /* 1. get roles's privs --> tmp_privs */ OZ (get_roles_obj_privs(guard, obj_key, tmp_privs, true, role_id_array)); /* 2. get privs needed --> packed_privs */ OZ (ObPrivPacker::pack_raw_obj_priv_list(NO_OPTION, plist, packed_privs)); /* 3. check */ OZ (ObOraPrivCheck::packed_obj_priv_list_or_exists(packed_privs, tmp_privs, exists)); if (OB_SUCC(ret) && !exists) { ret = OB_ERR_NO_PRIVILEGE; } return ret; } /* check user 是否有多一种系统权限的至少一种 */ int ObOraSysChecker::check_obj_plist_or_in_single( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const uint64_t obj_type, const uint64_t obj_id, const uint64_t col_id, const ObRawObjPrivArray &plist) { int ret = OB_SUCCESS; bool exists; ObObjPrivSortKey obj_key(tenant_id, obj_id, obj_type, col_id, user_id, user_id); ObPackedObjPriv tmp_privs = 0; OZ (guard.get_obj_privs_in_ur_and_obj(tenant_id, obj_key, tmp_privs)); if (OB_SUCC(ret)) { if (tmp_privs == 0) { ret = OB_ERR_EMPTY_QUERY; } else { ObPackedObjPriv packed_privs; OZ (ObPrivPacker::pack_raw_obj_priv_list(NO_OPTION, plist, packed_privs)); OZ (ObOraPrivCheck::packed_obj_priv_list_or_exists(packed_privs, tmp_privs, exists)); if (OB_SUCC(ret) && !exists) { ret = OB_ERR_NO_PRIVILEGE; } } } return ret; } int ObOraSysChecker::check_obj_p1_in_single( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const uint64_t obj_type, const uint64_t obj_id, const uint64_t col_id, const ObRawObjPriv p1, const uint64_t option) { int ret = OB_SUCCESS; ObObjPrivSortKey obj_key(tenant_id, obj_id, obj_type, col_id, user_id, user_id); ObPackedObjPriv tmp_privs = 0; OZ (guard.get_obj_privs_in_ur_and_obj(tenant_id, obj_key, tmp_privs)); OZX2 (check_single_option_obj_priv_inner(tmp_privs, option, p1), OB_ERR_NO_PRIVILEGE, OB_ERR_EMPTY_QUERY); return ret; } int ObOraSysChecker::check_obj_p1_in_roles( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const uint64_t obj_type, const uint64_t obj_id, const uint64_t col_id, const ObRawObjPriv p1, const uint64_t option, const ObIArray &role_id_array) { int ret = OB_SUCCESS; ObObjPrivSortKey obj_key(tenant_id, obj_id, obj_type, col_id, user_id, user_id); ObPackedObjPriv tmp_privs = 0; OZ (get_roles_obj_privs(guard, obj_key, tmp_privs, true, role_id_array)); OZX1 (check_single_option_obj_priv_inner(tmp_privs, option, p1), OB_ERR_EMPTY_QUERY); return ret; } /* check user 是否有一种对象权限 1. 先check 自己的权限, 2. 然后递归找到通过role拥有的权限 */ int ObOraSysChecker::check_obj_plist_or( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const uint64_t obj_type, const uint64_t obj_id, const uint64_t col_id, const ObRawObjPrivArray &plist, const ObIArray &role_id_array) { int ret = OB_SUCCESS; int ret1; OZX2 (check_obj_plist_or_in_single(guard, tenant_id, user_id, obj_type, obj_id, col_id, plist), OB_ERR_NO_PRIVILEGE, OB_ERR_EMPTY_QUERY, tenant_id, user_id, obj_type, obj_id, col_id, plist); if (ret == OB_ERR_NO_PRIVILEGE || ret == OB_ERR_EMPTY_QUERY) { ret1 = ret; ret = OB_SUCCESS; OZ (check_obj_plist_or_in_roles(guard, tenant_id, user_id, obj_type, obj_id, col_id, plist, role_id_array), tenant_id, user_id, obj_type, obj_id, col_id, plist); /* 无任何间接权限,但有直接权限,需要更改错误码为 no privilege */ if (ret == OB_ERR_EMPTY_QUERY && ret1 != OB_ERR_EMPTY_QUERY) { ret = OB_ERR_NO_PRIVILEGE; } } return ret; } /* check user 是否有一种对象权限 1. 先check 自己的权限, 2. 然后递归找到通过role拥有的权限 */ int ObOraSysChecker::check_obj_p1( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const uint64_t obj_type, const uint64_t obj_id, const uint64_t col_id, const ObRawObjPriv p1, const uint64_t option, const ObIArray &role_id_array) { int ret = OB_SUCCESS; int ret1; OZX2 (check_obj_p1_in_single(guard, tenant_id, user_id, obj_type, obj_id, col_id, p1, option), OB_ERR_NO_PRIVILEGE, OB_ERR_EMPTY_QUERY, tenant_id, user_id, obj_type, obj_id, col_id, p1, option); if (ret == OB_ERR_NO_PRIVILEGE || ret == OB_ERR_EMPTY_QUERY) { ret1 = ret; ret = OB_SUCCESS; OZX1 (check_obj_p1_in_roles(guard, tenant_id, user_id, obj_type, obj_id, col_id, p1, option, role_id_array), OB_ERR_EMPTY_QUERY, tenant_id, user_id, obj_type, obj_id, col_id, p1, option); /* 无任何间接权限,但有直接权限,需要更改错误码为 no privilege */ if (ret == OB_ERR_EMPTY_QUERY && ret1 != OB_ERR_EMPTY_QUERY) { ret = OB_ERR_NO_PRIVILEGE; } } return ret; } int ObOraSysChecker::check_p1_or_plist_in_single( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObRawPriv p1, const uint64_t option, const ObRawPrivArray &plist) { int ret = OB_SUCCESS; ObSysPriv *sys_priv = NULL; OZ (guard.get_sys_priv_with_grantee_id(tenant_id, user_id, sys_priv)); if (OB_SUCC(ret)) { if (sys_priv == NULL) { ret = OB_ERR_NO_PRIVILEGE; } else { OZX1 (check_p1_or_plist_using_privs(sys_priv->get_priv_array(), p1, option, plist), OB_ERR_NO_PRIVILEGE); } } return ret; } int ObOraSysChecker::check_p1_or_plist_in_roles( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObRawPriv p1, const uint64_t option, const ObRawPrivArray &plist, const ObIArray &role_id_array) { int ret = OB_SUCCESS; ObPackedPrivArray sys_packed_array; OZ (get_user_sys_priv_in_roles(guard, tenant_id, user_id, sys_packed_array, true, role_id_array), tenant_id, user_id); OZ (check_p1_or_plist_using_privs(sys_packed_array, p1, option, plist)); return ret; } /* check user 是否有p1系统权限,如果没有,返回是否有plist里面的任意一个权限 1. 先check 自己的权限, 2. 然后递归找到通过role拥有的权限 3. 如果有p1,返回成功。 如果没有p1, 返回失败,同时,看是有plist的任意一个 这个函数用于错误码的修正。 例如: select * from user1.table1; 当没有该对对象上的查询权限时,会报错。 报错的信息为:当用户没有对该对象的任何权限时,报table not exists 当用户有该对象的其他权限时,报权限不足。这种情况,不仅仅需要判断select any table权限 还是需要判断是否有create any table/alter any table/drop any table系统权限 */ int ObOraSysChecker::check_p1_with_plist_info( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObRawPriv p1, const uint64_t option, ObRawPrivArray &plist, bool &has_other_priv, const ObIArray &role_id_array) { int ret = OB_SUCCESS; OZX1 (check_p1_with_plist_info_in_single( guard, tenant_id, user_id, p1, option, plist, has_other_priv), OB_ERR_NO_PRIVILEGE); if (ret == OB_ERR_NO_PRIVILEGE) { ret = OB_SUCCESS; if (has_other_priv) { OZX1 (check_p1_in_roles(guard, tenant_id, user_id, p1, role_id_array), OB_ERR_NO_PRIVILEGE); } else { OZX1 (check_p1_with_plist_info_in_roles( guard, tenant_id, user_id, p1, option, plist, has_other_priv, role_id_array), OB_ERR_NO_PRIVILEGE); } } return ret; } int ObOraSysChecker::check_p1_with_plist_info_in_roles( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObRawPriv p1, const uint64_t option, ObRawPrivArray &plist, bool &has_other_priv, const ObIArray &role_id_array) { int ret = OB_SUCCESS; ObPackedPrivArray sys_packed_array; OZ (get_user_sys_priv_in_roles(guard, tenant_id, user_id, sys_packed_array, true, role_id_array), tenant_id, user_id); OZX1 (check_p1_with_plist_info_using_privs(sys_packed_array, p1, option, plist, has_other_priv), OB_ERR_NO_PRIVILEGE); return ret; } int ObOraSysChecker::check_p1_with_plist_info_using_privs( const ObPackedPrivArray &priv_array, const ObRawPriv p1, const uint64_t option, ObRawPrivArray &plist, bool &has_other_priv) { int ret = OB_SUCCESS; int tmp_ret = OB_SUCCESS; bool exists = false; has_other_priv = false; // 1. check p1 OZ (ObOraPrivCheck::raw_sys_priv_exists(option, p1, priv_array, exists)); // 2. when has no p1, then fill "has_other_priv" if (OB_SUCC(ret) && !exists) { tmp_ret = OB_ERR_NO_PRIVILEGE; for (int i = 0; i < plist.count() && !exists && OB_SUCC(ret); i++) { OZ (ObOraPrivCheck::raw_sys_priv_exists(option, plist.at(i), priv_array, exists)); if (OB_SUCC(ret) && exists) { has_other_priv = true; } } OX (ret = tmp_ret); } return ret; } int ObOraSysChecker::check_p1_with_plist_info_in_single( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObRawPriv p1, const uint64_t option, ObRawPrivArray &plist, bool &has_other_priv) { int ret = OB_SUCCESS; ObSysPriv *sys_priv = NULL; has_other_priv = false; OZ (guard.get_sys_priv_with_grantee_id(tenant_id, user_id, sys_priv)); if (OB_SUCC(ret)) { if (sys_priv == NULL) { ret = OB_ERR_NO_PRIVILEGE; } else { OZX1 (check_p1_with_plist_info_using_privs( sys_priv->get_priv_array(), p1, option, plist, has_other_priv), OB_ERR_NO_PRIVILEGE); } } return ret; } /* check user 是否有p1系统权限,如果没有,check plist option 1. 先check 自己的权限, 2. 然后递归找到通过role拥有的权限 */ int ObOraSysChecker::check_p1_or_plist( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObRawPriv p1, const uint64_t option, const ObRawPrivArray &plist, const ObIArray &role_id_array) { int ret = OB_SUCCESS; OZX1 (check_p1_or_plist_in_single(guard, tenant_id, user_id, p1, option, plist), OB_ERR_NO_PRIVILEGE); if (ret == OB_ERR_NO_PRIVILEGE) { ret = OB_SUCCESS; OZ (check_p1_or_plist_in_roles(guard, tenant_id, user_id, p1, option, plist, role_id_array)); } return ret; } /* 检查是否有一组系统权限的任意一种 */ int ObOraSysChecker::check_plist_using_privs( const ObPackedPrivArray &priv_array, const uint64_t option, const ObRawPrivArray &plist) { int ret = OB_SUCCESS; bool exists = false; for (int i = 0; i < plist.count() && OB_SUCC(ret) && !exists; i++) { OZ (ObOraPrivCheck::raw_sys_priv_exists(option, plist.at(i), priv_array, exists)); } if (OB_SUCC(ret) && !exists) { ret = OB_ERR_NO_PRIVILEGE; } return ret; } int ObOraSysChecker::check_p1_or_plist_using_privs( const ObPackedPrivArray &priv_array, const ObRawPriv p1, const uint64_t option, const ObRawPrivArray &plist) { int ret = OB_SUCCESS; bool exists = false; // 1. check p1 OZ (ObOraPrivCheck::raw_sys_priv_exists(option, p1, priv_array, exists)); // 2. Or check plist if (OB_SUCC(ret) && !exists) { OZ (check_plist_using_privs(priv_array, option, plist)); } return ret; } int ObOraSysChecker::check_p1_or_cond_p2_in_single( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t ur_id, const ObRawPriv p1, bool is_owner, const ObRawPriv p2) { int ret = OB_SUCCESS; ObSysPriv *sys_priv = NULL; bool exists = false; OZ (guard.get_sys_priv_with_grantee_id(tenant_id, ur_id, sys_priv)); if (OB_SUCC(ret)) { if (sys_priv == NULL) { ret = OB_ERR_NO_PRIVILEGE; } else { OZ (ObOraPrivCheck::p1_or_cond_p2_exists(p1, is_owner, p2, sys_priv->get_priv_array(), exists)); if (OB_SUCC(ret) && !exists) { ret = OB_ERR_NO_PRIVILEGE; } } } return ret; } int ObOraSysChecker::check_p1_or_cond_p2_in_roles( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t ur_id, const ObRawPriv p1, bool is_owner, const ObRawPriv p2, const ObIArray &role_id_array) { int ret = OB_SUCCESS; ObPackedPrivArray sys_packed_array; bool exists = false; OZ (get_user_sys_priv_in_roles(guard, tenant_id, ur_id, sys_packed_array, true, role_id_array), tenant_id, ur_id); OZ (ObOraPrivCheck::p1_or_cond_p2_exists(p1, is_owner, p2, sys_packed_array, exists)); if (OB_SUCC(ret) && !exists) { ret = OB_ERR_NO_PRIVILEGE; } return ret; } /* 检查一个user是否有一种系统权限,如果没有,检查是否是owner并且有另一种系统权限 1. check sys p1 2. check owner and sys p2 一般用于create 语句, such as: create table, create view, create function, etc. */ int ObOraSysChecker::check_p1_or_owner_and_p2( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObString &database_name, const ObRawPriv p1, const ObRawPriv p2, const ObIArray &role_id_array) { int ret = OB_SUCCESS; bool is_owner; if (database_name.empty()) { is_owner = true; } else { const ObUserInfo *user_info = NULL; OZ (guard.get_user_info(tenant_id, user_id, user_info)); if (OB_SUCC(ret) && NULL == user_info) { ret = OB_USER_NOT_EXIST; LOG_USER_ERROR(OB_USER_NOT_EXIST, database_name.length(), database_name.ptr()); } OX (is_owner = ObOraPrivCheck::user_is_owner(user_info->get_user_name(), database_name)); } OZX1 (check_p1_or_cond_p2_in_single(guard, tenant_id, user_id, p1, is_owner, p2), OB_ERR_NO_PRIVILEGE, tenant_id, user_id, p1, is_owner, p2); if (ret == OB_ERR_NO_PRIVILEGE) { ret = OB_SUCCESS; OZ (check_p1_or_cond_p2_in_roles(guard, tenant_id, user_id, p1, is_owner, p2, role_id_array)); } return ret; } /* 检查一个user是否是owner,或者有一种系统权限,或者有一种对象权限 1. check owner 2. check sys p1 3. check obj p2 一般用于drop 语句, such as: drop table, drop view, drop function, etc. */ int ObOraSysChecker::check_owner_or_p1_or_objp2( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObString &database_name, const uint64_t obj_id, const uint64_t obj_type, const ObRawPriv p1, const ObRawObjPriv obj_p2, const ObIArray &role_id_array) { int ret = OB_SUCCESS; bool is_owner = false; uint64_t obj_owner_id = OB_INVALID_ID; if (database_name.empty()) { is_owner = true; obj_owner_id = user_id; } else { const ObUserInfo *user_info = NULL; OZ (guard.get_user_info(tenant_id, user_id, user_info)); if (OB_SUCC(ret) && NULL == user_info) { ret = OB_USER_NOT_EXIST; LOG_USER_ERROR(OB_USER_NOT_EXIST, database_name.length(), database_name.ptr()); } OX (is_owner = ObOraPrivCheck::user_is_owner(user_info->get_user_name(), database_name)); OZ (guard.get_user_id(tenant_id, database_name, ObString(OB_DEFAULT_HOST_NAME), obj_owner_id)); if (OB_SUCC(ret) && obj_owner_id == OB_INVALID_ID) { ret = OB_USER_NOT_EXIST; LOG_USER_ERROR(OB_USER_NOT_EXIST, database_name.length(), database_name.ptr()); } } if (!is_owner) { OZX1 (check_p1(guard, tenant_id, user_id, p1, role_id_array), OB_ERR_NO_PRIVILEGE, tenant_id, user_id, p1); if (ret == OB_ERR_NO_PRIVILEGE) { ret = OB_SUCCESS; OZ (check_ora_obj_priv(guard, tenant_id, user_id, database_name, obj_id, OBJ_LEVEL_FOR_TAB_PRIV, obj_type, obj_p2, CHECK_FLAG_NORMAL, obj_owner_id, role_id_array)); /*OZ (check_obj_p1(guard, tenant_id, user_id, obj_type, obj_id, OBJ_LEVEL_FOR_TAB_PRIV, obj_p2, NO_OPTION, role_id_array), tenant_id, user_id, obj_type, obj_id, OBJ_LEVEL_FOR_TAB_PRIV, obj_p2);*/ } } return ret; } /** 按照以下顺序进行权限检查 * 1. 检查是否是owner * 2. 检查user_id是否具有系统权限p1 * 3. 检查是否具有相关的对象权限 * 1. 如果有,那么ret = OB_ERR_NO_PRIVILEGE * 2. 如果没有,那么ret = OB_TABLE_NOT_EXIST * 用于oracle模式下的drop table, drop view 的权限检查 */ int ObOraSysChecker::check_owner_or_p1_or_access( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObString &database_name, const ObRawPriv p1, const uint64_t obj_type, const uint64_t obj_id, const ObIArray &role_id_array) { int ret = OB_SUCCESS; bool is_owner = false; if (database_name.empty()) { is_owner = true; } else { const ObUserInfo *user_info = NULL; OZ (guard.get_user_info(tenant_id, user_id, user_info)); if (OB_SUCC(ret)) { if (OB_ISNULL(user_info)) { ret = OB_USER_NOT_EXIST; LOG_USER_ERROR(OB_USER_NOT_EXIST, database_name.length(), database_name.ptr()); } } // 1. Check if is owner OX (is_owner = ObOraPrivCheck::user_is_owner(user_info->get_user_name(), database_name)); } if (OB_SUCC(ret)) { if (!is_owner) { // 2. Check sys priv OZX1 (check_p1(guard, tenant_id, user_id, p1, role_id_array), OB_ERR_NO_PRIVILEGE, tenant_id, user_id, p1); // 3. Check related priv if (OB_ERR_NO_PRIVILEGE == ret) { ret = OB_SUCCESS; bool accessible = false; OZ (check_access_to_obj(guard, tenant_id, user_id, p1, obj_type, obj_id, database_name, role_id_array, accessible)); if (OB_SUCC(ret)) { if (accessible) { ret = OB_ERR_NO_PRIVILEGE; } else { ret = OB_TABLE_NOT_EXIST; } } } } } return ret; } int ObOraSysChecker::check_access_to_mlog_base_table( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const uint64_t obj_id, const ObString &database_name, const ObIArray &role_id_array, bool &accessible) { int ret = OB_SUCCESS; uint64_t obj_owner_id = OB_INVALID_ID; accessible = false; if (OB_FAIL(guard.get_user_id(tenant_id, database_name, ObString(OB_DEFAULT_HOST_NAME), obj_owner_id))) { LOG_WARN("failed to get user id", KR(ret), K(tenant_id), K(database_name)); } else if (OB_FAIL(ObOraSysChecker::check_ora_obj_priv( guard, tenant_id, user_id, database_name, obj_id, OBJ_LEVEL_FOR_TAB_PRIV, static_cast(ObObjectType::TABLE), OBJ_PRIV_ID_SELECT, CHECK_FLAG_NORMAL, obj_owner_id, role_id_array))) { LOG_WARN("failed to check ora obj privs", KR(ret), K(tenant_id), K(user_id), K(database_name), K(obj_id), K(obj_owner_id), K(role_id_array)); } else { accessible = true; } // callers need to rewrite the error code by accessible=false if (OB_ERR_NO_SYS_PRIVILEGE == ret) { ret = OB_SUCCESS; } return ret; } /** 检查user是否具有access到obj_id的权限,按照如下顺序进行检查 * 1. 检查user_id是否具有和p1相关的系统权限 * 2. 检查user_id是否具有和p1,obj_type相关的对象权限 * 用于 drop table, drop view 的相关权限判断 */ int ObOraSysChecker::check_access_to_obj( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObRawPriv p1, const uint64_t obj_type, const uint64_t obj_id, const ObString &database_name, const ObIArray &role_id_array, bool &accessible) { int ret = OB_SUCCESS; accessible = false; ObRawPrivArray sys_priv_array; ObRawObjPrivArray obj_priv_array; bool is_owner = false; // 1. 建立和p1相关的权限列表 OZ (build_related_sys_priv_array(p1, sys_priv_array), p1); // 2. 检查user_id是否具有sys_priv_array中的系统权限一种 if (OB_SUCC(ret)) { const ObUserInfo *user_info = NULL; if (database_name.empty()) { is_owner = true; } else if (OB_FAIL(guard.get_user_info(tenant_id, user_id, user_info))) { LOG_WARN("failed to get user info", K(ret), K(tenant_id), K(user_id)); } else if (OB_ISNULL(user_info)) { ret = OB_USER_NOT_EXIST; LOG_USER_ERROR(OB_USER_NOT_EXIST, database_name.length(), database_name.ptr()); } else { is_owner = ObOraPrivCheck::user_is_owner(user_info->get_user_name(), database_name); } } if (OB_FAIL(ret)) { } else if (is_owner) { accessible = true; } else { if (sys_priv_array.count() > 0) { OZ (check_p1_or_plist(guard, tenant_id, user_id, p1, NO_OPTION, sys_priv_array, role_id_array)); } else { OZ (check_p1(guard, tenant_id, user_id, p1, role_id_array)); } if (OB_SUCC(ret)) { accessible = true; } else { ret = OB_SUCCESS; } if (OB_SUCC(ret) && !accessible) { // 3. 建立和p1,obj_type相关的对象权限列表 OZ (build_related_obj_priv_array(p1, obj_type, obj_priv_array), p1, obj_type); // 4. 检查user_id对于obj_id是否具有obj_priv_array权限中的一种 if (OB_SUCC(ret) && obj_priv_array.count() > 0) { OZ (check_obj_plist_or(guard, tenant_id, user_id, obj_type, obj_id, OBJ_LEVEL_FOR_TAB_PRIV, obj_priv_array, role_id_array)); if (OB_SUCC(ret)) { accessible = true; } else { ret = OB_SUCCESS; } } } } return ret; } // 检测用户能否感知到obj int ObOraSysChecker::check_access_to_obj( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const uint64_t obj_type, const uint64_t obj_id, const ObString &database_name, const ObIArray &role_id_array, bool &accessible) { int ret = OB_SUCCESS; accessible = false; ObRawPrivArray sys_priv_array; ObRawObjPrivArray obj_priv_array; bool is_owner = false; // 1. 建立相关的sys权限列表 OZ (build_related_sys_priv_array(obj_type, sys_priv_array)); // 2. 检查user_id是否具有 sys_priv 中的任意一个 if (OB_SUCC(ret)) { const ObUserInfo *user_info = NULL; if (database_name.empty()) { is_owner = true; } else if (OB_FAIL(guard.get_user_info(tenant_id, user_id, user_info))) { LOG_WARN("failed to get user info", K(ret), K(tenant_id), K(user_id)); } else if (OB_ISNULL(user_info)) { ret = OB_USER_NOT_EXIST; LOG_USER_ERROR(OB_USER_NOT_EXIST, database_name.length(), database_name.ptr()); } else { is_owner = ObOraPrivCheck::user_is_owner(user_info->get_user_name(), database_name); } } if (OB_FAIL(ret)) { } else if (is_owner) { accessible = true; /* is_owner = true, means user can access obj */ } else { if (sys_priv_array.count() > 0) { OZ (check_plist_or(guard, tenant_id, user_id, sys_priv_array, role_id_array)); if (OB_SUCC(ret)) { accessible = true; } else if (OB_ERR_NO_PRIVILEGE == ret || OB_ERR_EMPTY_QUERY == ret) { accessible = false; ret = OB_SUCCESS; } else { accessible = false; } } // 3. 建立相关的对象权限 OZ (build_related_obj_priv_array(obj_type, obj_priv_array)); // 4. 检查user_id 是否具有 obj_priv_array中的一种 if (OB_SUCC(ret) && obj_priv_array.count() > 0 && !accessible) { OZ (check_obj_plist_or(guard, tenant_id, user_id, obj_type, obj_id, OBJ_LEVEL_FOR_TAB_PRIV, obj_priv_array, role_id_array)); if (OB_SUCC(ret)) { accessible = true; } else if (OB_ERR_NO_PRIVILEGE == ret || OB_ERR_EMPTY_QUERY == ret) { accessible = false; ret = OB_SUCCESS; } else { accessible = false; } } } return ret; } /** * 根据p1, obj_type来判断哪些对象权限是相关的 */ int ObOraSysChecker::build_related_obj_priv_array( const ObRawPriv p1, const uint64_t obj_type, ObRawObjPrivArray &obj_priv_array) { int ret = OB_SUCCESS; obj_priv_array.reset(); switch (obj_type) { case static_cast(share::schema::ObObjectType::TABLE): if (PRIV_ID_DROP_ANY_TABLE == p1 || PRIV_ID_SELECT_ANY_TABLE == p1 || PRIV_ID_SELECT_ANY_DICTIONARY == p1) { OZ (obj_priv_array.push_back(OBJ_PRIV_ID_ALTER)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_DEBUG)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_DELETE)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_INDEX)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_INSERT)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_READ)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_REFERENCES)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_SELECT)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_UPDATE)); } else if (PRIV_ID_CREATE_ANY_VIEW == p1 || PRIV_ID_SELECT_ANY_TABLE == p1 || PRIV_ID_SELECT_ANY_DICTIONARY == p1) { OZ (obj_priv_array.push_back(OBJ_PRIV_ID_ALTER)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_DEBUG)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_DELETE)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_INSERT)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_READ)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_REFERENCES)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_SELECT)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_UPDATE)); } break; case static_cast(share::schema::ObObjectType::VIEW): if (PRIV_ID_DROP_ANY_VIEW == p1 || PRIV_ID_SELECT_ANY_TABLE == p1 || PRIV_ID_SELECT_ANY_DICTIONARY == p1) { OZ (obj_priv_array.push_back(OBJ_PRIV_ID_ALTER)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_DEBUG)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_DELETE)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_INDEX)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_INSERT)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_READ)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_REFERENCES)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_SELECT)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_UPDATE)); } break; default: ret = OB_ERR_UNEXPECTED; LOG_WARN("unexcepted obj_type", K(ret), K(obj_type)); break; } return ret; } /**根据p1来判断哪些系统权限是相关的 * */ int ObOraSysChecker::build_related_sys_priv_array( const ObRawPriv p1, ObRawPrivArray &sys_priv_array) { int ret = OB_SUCCESS; sys_priv_array.reset(); switch (p1) { case static_cast(PRIV_ID_DROP_ANY_TABLE): case static_cast(PRIV_ID_SELECT_ANY_TABLE): OZ (sys_priv_array.push_back(PRIV_ID_CREATE_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_ALTER_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_LOCK_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_COMMENT_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_SELECT_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_INSERT_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_UPDATE_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_DELETE_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_FLASHBACK_ANY_TABLE)); break; case static_cast(PRIV_ID_DROP_ANY_VIEW): OZ (sys_priv_array.push_back(PRIV_ID_ALTER_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_LOCK_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_COMMENT_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_SELECT_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_INSERT_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_UPDATE_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_DELETE_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_FLASHBACK_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_CREATE_ANY_VIEW)); break; case static_cast(PRIV_ID_CREATE_ANY_VIEW): OZ (sys_priv_array.push_back(PRIV_ID_CREATE_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_DROP_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_ALTER_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_LOCK_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_COMMENT_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_SELECT_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_INSERT_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_UPDATE_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_DELETE_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_FLASHBACK_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_DROP_ANY_VIEW)); break; case static_cast(PRIV_ID_SELECT_ANY_DICTIONARY): break; default: ret = OB_ERR_UNEXPECTED; LOG_WARN("unexcepted sys_priv type", K(ret), K(p1)); break; } return ret; } // 根据对象类型来判断哪些系统权限是相关的 int ObOraSysChecker::build_related_sys_priv_array( const uint64_t obj_type, ObRawPrivArray &sys_priv_array) { int ret = OB_SUCCESS; sys_priv_array.reset(); switch (obj_type) { case static_cast(ObObjectType::TABLE): { OZ (sys_priv_array.push_back(PRIV_ID_CREATE_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_DROP_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_ALTER_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_LOCK_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_COMMENT_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_SELECT_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_INSERT_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_UPDATE_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_DELETE_ANY_TABLE)); OZ (sys_priv_array.push_back(PRIV_ID_FLASHBACK_ANY_TABLE)); break; } default: { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexcepted sys_priv type", K(ret), K(obj_type)); break; } } return ret; } int ObOraSysChecker::build_related_obj_priv_array( const uint64_t obj_type, ObRawObjPrivArray &obj_priv_array) { int ret = OB_SUCCESS; obj_priv_array.reset(); switch (obj_type) { case static_cast(ObObjectType::TABLE): { OZ (obj_priv_array.push_back(OBJ_PRIV_ID_CREATE)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_ALTER)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_DEBUG)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_DELETE)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_INDEX)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_INSERT)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_READ)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_REFERENCES)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_SELECT)); OZ (obj_priv_array.push_back(OBJ_PRIV_ID_UPDATE)); break; } default: { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid obj_type", K(ret), K(obj_type)); break; } } return ret; } /* 检查一个user是否有一种系统权限,如果没有,检查是否是owner并且有另一种系统权限 1. check owner 2. check sys p1 一般用于drop 语句, such as: drop table, drop view, drop function, etc. */ int ObOraSysChecker::check_owner_or_p1( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObString &database_name, const ObRawPriv p1, const ObIArray &role_id_array) { int ret = OB_SUCCESS; bool is_owner = false; if (database_name.empty()) { is_owner = true; } else { const ObUserInfo *user_info = NULL; OZ (guard.get_user_info(tenant_id, user_id, user_info)); if (OB_SUCC(ret) && NULL == user_info) { ret = OB_USER_NOT_EXIST; LOG_USER_ERROR(OB_USER_NOT_EXIST, database_name.length(), database_name.ptr()); } OX (is_owner = ObOraPrivCheck::user_is_owner(user_info->get_user_name(), database_name)); } if (!is_owner) { OZ (check_p1(guard, tenant_id, user_id, p1, role_id_array), tenant_id, user_id, p1); } return ret; } /* 检查方法: 1. check is owner 2. if owner return success 3. else has sys priv p1, return success 4. else has obj priv p2, return success 5. else return no_privilege */ // int ObOraSysChecker::check_ora_alter_ddl_priv_inner( // ObSchemaGetterGuard &guard, // const uint64_t tenant_id, // const uint64_t user_id, // const ObString &database_name, // const ObDbObjType db_obj_type, // const ObString &objname, // const ObRawPriv p1, // const ObObjRawPriv p2) // { // int ret = OB_SUCCESS; // ObSysPriv *sys_priv = NULL; // bool is_owner; // lib::Worker::CompatMode compat_mode; // bool exists = false; // if (OB_FAIL(guard.get_tenant_compat_mode(tenant_id, compat_mode))) { // LOG_WARN("get_tenant_compat_mode failed", K(ret)); // } else if (compat_mode == lib::Worker::CompatMode::ORACLE) { // if (database_name.empty()) { // is_owner = true; // } else { // const ObUserInfo *user_info = NULL; // OZ (guard.get_user_info(user_id, user_info)); // OX (is_owner = ObOraPrivCheck::user_is_owner(user_info->get_user_name(), // database_name)); // } // OZ (check_cond_p1_or_op2(guard, tenant_id, user_id, db_obj_type, objname, is_owner, p1, p2), // tenant_id, user_id, is_owner, p1, p2); // if (ret == OB_ERR_NO_PRIVILEGE) { // ret = OB_SUCCESS; // ObPackedPrivArray sys_packed_array; // OZ (get_user_sys_priv_in_roles(guard, tenant_id, user_id, sys_packed_array), // tenant_id, user_id); // OZ (ObOraPrivCheck::p1_or_cond_p2_exists(p1, // is_owner, // p2, // sys_packed_array, // exists)); // if (OB_SUCC(ret) && !exists) { // ret = OB_ERR_NO_PRIVILEGE; // } // } // } // return ret; // } /* check owner, 两种sys priv。命名来自于create table需要的权限 */ #define DEFINE_CREATE_CHECK_CMD(p1, p2) \ OZ (check_p1_or_owner_and_p2(guard, \ tenant_id, \ user_id, \ database_name, \ p1, \ p2, \ role_id_array), \ tenant_id, user_id, database_name, p1, p2); /* check owner, 一种sys priv 或者一种obj priv,命名来自于alter table 需要的权限 */ #define DEFINE_ALTER_CHECK_CMD(p1, obj_p2) \ OZ (check_owner_or_p1_or_objp2(guard, \ tenant_id, \ user_id, \ database_name, \ obj_id, \ obj_type, \ p1, \ obj_p2, \ role_id_array), \ tenant_id, user_id, database_name, p1, obj_p2); /* check owner, 一种sys priv, 命名来自于drop table需要的权限 */ #define DEFINE_DROP_CHECK_CMD(p1) \ OZ (check_owner_or_p1(guard, \ tenant_id, \ user_id, \ database_name, \ p1, \ role_id_array), \ tenant_id, user_id, database_name, p1); /* check owner,一种sys priv,如果没有sys priv,则需要查看其他权限, 根据是否有其他权限,确定返回权限不足还是无效的表名*/ #define DEFINE_DROP_VIEW_CHECK_CMD(p1) \ OZ (check_owner_or_p1_or_access(guard, \ tenant_id, \ user_id, \ database_name, \ p1, \ obj_type, \ obj_id, \ role_id_array), \ tenant_id, user_id, database_name, p1); /** check owner, 一种sys priv,如果没有sys priv,则判断user_id是否 * 拥有其他相关的系统和对象权限,确定返回权限不足还是表不存在 */ #define DEFINE_DROP_TABLE_CHECK_CMD(p1) \ OZ (check_owner_or_p1_or_access(guard, \ tenant_id, \ user_id, \ database_name, \ p1, \ obj_type, \ obj_id, \ role_id_array), \ tenant_id, user_id, database_name, p1); /* check 一种sys priv,命名来自于create pub synonym */ #define DEFINE_PUB_CHECK_CMD(p1) \ OZX1 (check_p1(guard, \ tenant_id, \ user_id, \ p1, \ role_id_array), \ OB_ERR_NO_PRIVILEGE, tenant_id, user_id, p1); /* check 两种sys priv,命名来自于purge table/index/recyclebin */ #define DEFINE_PURGE_CHECK_CMD(p1, p2) \ OZX1 (check_p1(guard, \ tenant_id, \ user_id, \ p1, \ role_id_array), \ OB_ERR_NO_PRIVILEGE, tenant_id, user_id, p1); \ if (ret == OB_ERR_NO_PRIVILEGE) { \ ret = OB_SUCCESS; \ OZ (check_p1(guard, \ tenant_id, \ user_id, \ p2, \ role_id_array), \ tenant_id, user_id, p2); \ } /* sp: sys priv op: obj priv */ /* 如果有sys priv,grant语句的grantor是对象的owner,相当于代替对象owner执行。 这样设计,revoke的时候,这种情况下的授权不会被递归回收。 如果没有sys priv,grant语句的grantor是执行grant语句的用户。 */ int ObOraSysChecker::decide_grantor_id( ObSchemaGetterGuard &guard, bool has_sys_priv, const uint64_t tenant_id, const uint64_t user_id, const ObString &database_name, uint64_t &grantor_id_out) { int ret = OB_SUCCESS; if (has_sys_priv) { /* set ownerid to grantor_id */ if (database_name.empty()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("database name is null."); } else { const ObUserInfo *user_info = NULL; OZ (guard.get_user_info(tenant_id, database_name, ObString(OB_DEFAULT_HOST_NAME), user_info)); if (OB_SUCC(ret)) { if (user_info != NULL) { grantor_id_out = user_info->get_user_id(); } else { ret = OB_ERR_BAD_DATABASE; LOG_USER_ERROR(OB_ERR_BAD_DATABASE, database_name.length(), database_name.ptr()); LOG_WARN("invalid database name. ", K(database_name)); } } } } else { grantor_id_out = user_id; } return ret; } int ObOraSysChecker::check_single_option_obj_priv_inner( ObPackedObjPriv &ur_privs, uint64_t option, ObRawObjPriv raw_priv) { int ret = OB_SUCCESS; bool exists = false; /* 如果没有任何权限,暂时返回empty_query */ if (ur_privs == OBJ_PRIV_ID_NONE) { ret = OB_ERR_EMPTY_QUERY; } else { OZ (ObOraPrivCheck::raw_obj_priv_exists(raw_priv, option, ur_privs, exists)); if (OB_SUCC(ret) && !exists) { ret = OB_ERR_NO_PRIVILEGE; } } return ret; } /* 检查一个对象的一个转授权限是否存在 in: 用户在一个对象上的所有权限 in: 待check的权限 */ int ObOraSysChecker::check_single_option_obj_priv_inner( ObPackedObjPriv &ur_privs, ObRawObjPriv raw_priv) { int ret = OB_SUCCESS; bool exists = false; if (ur_privs == OBJ_PRIV_ID_NONE) { ret = OB_ERR_EMPTY_QUERY; } else { OZ (ObOraPrivCheck::raw_obj_priv_exists(raw_priv, GRANT_OPTION, ur_privs, exists)); if (OB_SUCC(ret) && !exists) { ret = OB_ERR_NO_PRIVILEGE; } } return ret; } /* 检查一个对象的一组权限是否存在 in: 用户在一个对象上的所有权限 in: 待check的权限组 */ int ObOraSysChecker::check_multi_option_obj_privs_inner( ObPackedObjPriv &ur_privs, const ObRawObjPrivArray &table_privs) { int ret = OB_SUCCESS; int i = 0; for (i = 0; i < table_privs.count() && OB_SUCC(ret); i++) { OZ (check_single_option_obj_priv_inner(ur_privs, table_privs.at(i))); } return ret; } int ObOraSysChecker::check_objplist_in_single( ObSchemaGetterGuard &guard, ObObjPrivSortKey &obj_key, const ObRawObjPrivArray &table_privs, const ObIArray &ins_col_id, const ObIArray &upd_col_id, const ObIArray &ref_col_id) { int ret = OB_SUCCESS; uint64_t tenant_id = obj_key.tenant_id_; ObPackedObjPriv obj_privs = 0; ObRawObjPriv priv; // 1. check table privs OZ (guard.get_obj_privs_in_ur_and_obj(tenant_id, obj_key, obj_privs), obj_key); OZX1 (check_multi_option_obj_privs_inner(obj_privs, table_privs), OB_ERR_NO_PRIVILEGE); //2. check ins col privs priv = OBJ_PRIV_ID_INSERT; for (int i = 0; i < ins_col_id.count() && OB_SUCC(ret); i++) { OX (obj_key.col_id_ = ins_col_id.at(i)); OZ (guard.get_obj_privs_in_ur_and_obj(tenant_id, obj_key, obj_privs), obj_key); OZX1 (check_single_option_obj_priv_inner(obj_privs, priv), OB_ERR_NO_PRIVILEGE); } //3. check upd col privs priv = OBJ_PRIV_ID_UPDATE; for (int i = 0; i < upd_col_id.count() && OB_SUCC(ret); i++) { OX (obj_key.col_id_ = upd_col_id.at(i)); OZ (guard.get_obj_privs_in_ur_and_obj(tenant_id, obj_key, obj_privs), obj_key); OZX1 (check_single_option_obj_priv_inner(obj_privs, priv), OB_ERR_NO_PRIVILEGE); } //4. check ref col privs priv = OBJ_PRIV_ID_REFERENCES; for (int i = 0; i < ref_col_id.count() && OB_SUCC(ret); i++) { OX (obj_key.col_id_ = ref_col_id.at(i)); OZ (guard.get_obj_privs_in_ur_and_obj(tenant_id, obj_key, obj_privs), obj_key); OZX1 (check_single_option_obj_priv_inner(obj_privs, priv), OB_ERR_NO_PRIVILEGE); } return ret; } int ObOraSysChecker::check_objplist_in_roles( ObSchemaGetterGuard &guard, ObObjPrivSortKey &obj_key, const ObRawObjPrivArray &table_privs, const ObIArray &ins_col_id, const ObIArray &upd_col_id, const ObIArray &ref_col_id, const ObIArray &role_id_array) { int ret = OB_SUCCESS; ObPackedObjPriv obj_privs = 0; // 1. check table privs OZ (get_roles_obj_privs(guard, obj_key, obj_privs, true, role_id_array)); OZ (check_multi_option_obj_privs_inner(obj_privs, table_privs)); //2. check ins col privs for (int i = 0; i < ins_col_id.count() && OB_SUCC(ret); i++) { OX (obj_key.col_id_ = ins_col_id.at(i)); OZ (get_roles_obj_privs(guard, obj_key, obj_privs, true, role_id_array)); OZ (check_single_option_obj_priv_inner(obj_privs, OBJ_PRIV_ID_INSERT)); } //3. check upd col privs for (int i = 0; i < upd_col_id.count() && OB_SUCC(ret); i++) { OX (obj_key.col_id_ = upd_col_id.at(i)); OZ (get_roles_obj_privs(guard, obj_key, obj_privs, true, role_id_array)); OZ (check_single_option_obj_priv_inner(obj_privs, OBJ_PRIV_ID_UPDATE)); } //4. check ref col privs for (int i = 0; i < ref_col_id.count() && OB_SUCC(ret); i++) { OX (obj_key.col_id_ = ref_col_id.at(i)); OZ (get_roles_obj_privs(guard, obj_key, obj_privs, true, role_id_array)); OZ (check_single_option_obj_priv_inner(obj_privs, OBJ_PRIV_ID_REFERENCES)); } return ret; } /* check grant objauth privs */ int ObOraSysChecker::check_objplist( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const uint64_t obj_id, const uint64_t obj_type, const ObRawObjPrivArray &table_privs, const ObIArray &ins_col_id, const ObIArray &upd_col_id, const ObIArray &ref_col_id, const ObIArray &role_id_array) { int ret = OB_SUCCESS; ObObjPrivSortKey obj_key(tenant_id, obj_id, obj_type, OBJ_LEVEL_FOR_TAB_PRIV, user_id, user_id); OZX2 (check_objplist_in_single(guard, obj_key, table_privs, ins_col_id, upd_col_id, ref_col_id), OB_ERR_NO_PRIVILEGE, OB_ERR_EMPTY_QUERY); if (ret == OB_ERR_NO_PRIVILEGE || ret == OB_ERR_EMPTY_QUERY) { ret = OB_SUCCESS; OZ (check_objplist_in_roles(guard, obj_key, table_privs, ins_col_id, upd_col_id, ref_col_id, role_id_array)); } return ret; } /* 为create view定制的check, check 在对象上是否有直接的select, insert, update, delete权限 */ int ObOraSysChecker::check_ora_obj_priv_for_create_view( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObString &database_name, const uint64_t obj_id, const uint64_t col_id, const uint64_t obj_type, const uint64_t obj_owner_id) { int ret = OB_SUCCESS; UNUSED(database_name); bool is_owner = is_owner_user(user_id, obj_owner_id); if (OB_SUCC(ret)) { if (obj_type == static_cast(ObObjectType::TABLE)) { /* 1. check owner*/ if (!is_owner) { /* 2. check sys priv */ ObRawPrivArray priv_list; if (!is_ora_sys_view_table(obj_id)) { OZ (priv_list.push_back(PRIV_ID_SELECT_ANY_TABLE)); OZ (priv_list.push_back(PRIV_ID_INSERT_ANY_TABLE)); OZ (priv_list.push_back(PRIV_ID_UPDATE_ANY_TABLE)); OZ (priv_list.push_back(PRIV_ID_DELETE_ANY_TABLE)); OZ (priv_list.push_back(PRIV_ID_CREATE_ANY_TABLE)); OZ (priv_list.push_back(PRIV_ID_DROP_ANY_TABLE)); OZ (priv_list.push_back(PRIV_ID_ALTER_ANY_TABLE)); OZ (priv_list.push_back(PRIV_ID_LOCK_ANY_TABLE)); OZ (priv_list.push_back(PRIV_ID_COMMENT_ANY_TABLE)); OZ (priv_list.push_back(PRIV_ID_FLASHBACK_ANY_TABLE)); } else { OZ (priv_list.push_back(PRIV_ID_SELECT_ANY_DICTIONARY)); } OZX1 (check_plist_or_in_single(guard, tenant_id, user_id, priv_list), OB_ERR_NO_PRIVILEGE); if (ret == OB_ERR_NO_PRIVILEGE) { /* 3. check obj priv */ ret = OB_SUCCESS; ObRawObjPrivArray obj_p_list; OZ (obj_p_list.push_back(OBJ_PRIV_ID_SELECT)); OZ (obj_p_list.push_back(OBJ_PRIV_ID_INSERT)); OZ (obj_p_list.push_back(OBJ_PRIV_ID_UPDATE)); OZ (obj_p_list.push_back(OBJ_PRIV_ID_DELETE)); OZ (obj_p_list.push_back(OBJ_PRIV_ID_CREATE)); OZ (obj_p_list.push_back(OBJ_PRIV_ID_ALTER)); OZ (obj_p_list.push_back(OBJ_PRIV_ID_DEBUG)); OZ (obj_p_list.push_back(OBJ_PRIV_ID_INDEX)); OZ (obj_p_list.push_back(OBJ_PRIV_ID_READ)); OZ (obj_p_list.push_back(OBJ_PRIV_ID_REFERENCES)); OZ (check_obj_plist_or_in_single(guard, tenant_id, user_id, obj_type, obj_id, col_id, obj_p_list), tenant_id, user_id, obj_type, obj_id, col_id, obj_p_list); } /* 调整错误码 to table or view not exists */ if (ret == OB_ERR_EMPTY_QUERY) { ret = OB_TABLE_NOT_EXIST; } } } else if (obj_type == static_cast(ObObjectType::SEQUENCE)) { if (!is_owner) { ObRawPrivArray priv_list; OZ (priv_list.push_back(PRIV_ID_SELECT_ANY_SEQ)); OZX1 (check_plist_or_in_single(guard, tenant_id, user_id, priv_list), OB_ERR_NO_PRIVILEGE); if (ret == OB_ERR_NO_PRIVILEGE) { /* 3. check obj priv */ ret = OB_SUCCESS; OZ (check_obj_p1_in_single(guard, tenant_id, user_id, obj_type, obj_id, col_id, OBJ_PRIV_ID_SELECT, NO_OPTION), tenant_id, user_id, obj_type, obj_id, col_id, OBJ_PRIV_ID_SELECT, NO_OPTION); } } } /* xinqi to do: else if */ } return ret; } /* 根据sys_priv,输出相关的other sys privs . 用途:确定是否有其他类的sys priv。 例如 输入:select any table。 输出: create/alter/drop/update/delete any table */ int ObOraSysChecker::build_related_plist( uint64_t obj_type, ObRawPriv& sys_priv, share::ObRawPrivArray& plist) { int ret = OB_SUCCESS; if (obj_type == static_cast(ObObjectType::VIEW)) { OZ (plist.push_back(PRIV_ID_CREATE_ANY_VIEW)); OZ (plist.push_back(PRIV_ID_DROP_ANY_TABLE)); } switch (sys_priv) { case PRIV_ID_SELECT_ANY_TABLE: OZ (plist.push_back(PRIV_ID_CREATE_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_ALTER_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_DROP_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_LOCK_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_COMMENT_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_INSERT_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_UPDATE_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_DELETE_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_FLASHBACK_ANY_TABLE)); break; case PRIV_ID_INSERT_ANY_TABLE: OZ (plist.push_back(PRIV_ID_CREATE_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_ALTER_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_DROP_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_LOCK_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_COMMENT_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_SELECT_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_UPDATE_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_DELETE_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_FLASHBACK_ANY_TABLE)); break; case PRIV_ID_UPDATE_ANY_TABLE: OZ (plist.push_back(PRIV_ID_CREATE_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_ALTER_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_DROP_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_LOCK_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_COMMENT_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_SELECT_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_INSERT_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_DELETE_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_FLASHBACK_ANY_TABLE)); break; case PRIV_ID_DELETE_ANY_TABLE: OZ (plist.push_back(PRIV_ID_CREATE_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_ALTER_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_DROP_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_LOCK_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_COMMENT_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_SELECT_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_INSERT_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_UPDATE_ANY_TABLE)); OZ (plist.push_back(PRIV_ID_FLASHBACK_ANY_TABLE)); break; case PRIV_ID_EXEC_ANY_PROC: OZ (plist.push_back(PRIV_ID_CREATE_ANY_PROC)); OZ (plist.push_back(PRIV_ID_ALTER_ANY_PROC)); OZ (plist.push_back(PRIV_ID_DROP_ANY_PROC)); break; case PRIV_ID_EXEC_ANY_TYPE: OZ (plist.push_back(PRIV_ID_CREATE_ANY_TYPE)); OZ (plist.push_back(PRIV_ID_ALTER_ANY_TYPE)); OZ (plist.push_back(PRIV_ID_DROP_ANY_TYPE)); OZ (plist.push_back(PRIV_ID_UNDER_ANY_TYPE)); break; case PRIV_ID_SELECT_ANY_SEQ: OZ (plist.push_back(PRIV_ID_CREATE_ANY_SEQ)); OZ (plist.push_back(PRIV_ID_ALTER_ANY_SEQ)); OZ (plist.push_back(PRIV_ID_DROP_ANY_TYPE)); break; default: break; } return ret; } int ObOraSysChecker::map_obj_priv_to_sys_priv( const ObRawObjPriv raw_obj_priv, const uint64_t obj_id, const uint64_t obj_type, ObRawPriv& sys_priv) { int ret = OB_SUCCESS; if (!is_ora_sys_view_table(obj_id)) { switch (raw_obj_priv) { case OBJ_PRIV_ID_SELECT: if (obj_type == static_cast(ObObjectType::SEQUENCE)) { sys_priv = PRIV_ID_SELECT_ANY_SEQ; } else if (obj_type == static_cast(ObObjectType::TRIGGER)) { sys_priv = PRIV_ID_CREATE_ANY_TRIG; } else { sys_priv = PRIV_ID_SELECT_ANY_TABLE; } break; case OBJ_PRIV_ID_INSERT: sys_priv = PRIV_ID_INSERT_ANY_TABLE; break; case OBJ_PRIV_ID_UPDATE: sys_priv = PRIV_ID_UPDATE_ANY_TABLE; break; case OBJ_PRIV_ID_DELETE: sys_priv = PRIV_ID_DELETE_ANY_TABLE; break; case OBJ_PRIV_ID_EXECUTE: if (obj_type == static_cast(ObObjectType::TYPE)) { sys_priv = PRIV_ID_EXEC_ANY_TYPE; } else { sys_priv = PRIV_ID_EXEC_ANY_PROC; } break; case OBJ_PRIV_ID_DEBUG: sys_priv = PRIV_ID_DEBUG_ANY_PROC; break; case OBJ_PRIV_ID_INDEX: case OBJ_PRIV_ID_REFERENCES: case OBJ_PRIV_ID_ALTER: /* no sys priv */ break; default: ret = OB_ERR_UNEXPECTED; LOG_WARN("raw obj priv is invalid", K(raw_obj_priv), K(ret)); break; } } else { sys_priv = PRIV_ID_SELECT_ANY_DICTIONARY; } return ret; } int ObOraSysChecker::map_obj_priv_array_to_sys_priv_array( const ObIArray &raw_obj_priv_array, const uint64_t obj_id, const uint64_t obj_type, ObIArray &sys_priv_array) { int ret = OB_SUCCESS; for (int i = 0; OB_SUCC(ret) && i < raw_obj_priv_array.count(); i++) { ObRawPriv sys_priv = PRIV_ID_NONE; OZ (map_obj_priv_to_sys_priv(raw_obj_priv_array.at(i), obj_id, obj_type, sys_priv)); if (OB_SUCC(ret) && sys_priv != PRIV_ID_NONE) { OZ (sys_priv_array.push_back(sys_priv)); } } return ret; } /* 对外接口:check一个用户对一个对象是否有几种权限的任一种 1. 先check is owner 2. 再check syspriv 3. 最后check obj priv 4. 错误码的调整。 */ int ObOraSysChecker::check_ora_obj_privs_or( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_db_id, const uint64_t user_id, const ObString &database_name, const uint64_t obj_id, const uint64_t col_id, const uint64_t org_obj_type, const ObRawObjPrivArray &raw_obj_priv_array, uint64_t check_flag, const uint64_t obj_owner_id, const ObIArray &role_id_array) { int ret = OB_SUCCESS; uint64_t obj_type; uint64_t option = 0; UNUSED(database_name); obj_type = org_obj_type; if (org_obj_type == static_cast(ObObjectType::VIEW) || org_obj_type == static_cast(ObObjectType::TRIGGER)) { obj_type = static_cast(ObObjectType::TABLE); } if (!is_super_user(user_id)) { CK (check_flag != CHECK_FLAG_DIRECT && check_flag != CHECK_FLAG_WITH_GRANT_OPTION); bool is_owner = is_owner_user(user_db_id, obj_owner_id); if (OB_SUCC(ret)) { if (obj_type == static_cast(ObObjectType::TABLE) || obj_type == static_cast(ObObjectType::INDEX) || obj_type == static_cast(ObObjectType::FUNCTION) || obj_type == static_cast(ObObjectType::PROCEDURE) || obj_type == static_cast(ObObjectType::PACKAGE) || obj_type == static_cast(ObObjectType::TYPE) || obj_type == static_cast(ObObjectType::SEQUENCE) || obj_type == static_cast(ObObjectType::TRIGGER)) { /* 1. check owner*/ if (!is_owner) { /* 2. check sys priv */ ObRawPrivArray sys_priv_array; share::ObRawPrivArray plist; /* 传入原始的obj type,对视图,trigger 处理 对于视图:没有任何对于的系统权限 对于trigger:对应的系统权限是:PRIV_ID_CREATE_ANY_TRIG 如果有create any trigger权限,则可以看到任何trigger */ OZ (map_obj_priv_array_to_sys_priv_array(raw_obj_priv_array, obj_id, org_obj_type, sys_priv_array), raw_obj_priv_array, sys_priv_array); OX (option = NO_OPTION); OZX1 (check_plist_or(guard, tenant_id, user_id, sys_priv_array, role_id_array), OB_ERR_NO_PRIVILEGE, tenant_id, user_id, sys_priv_array); if (ret == OB_ERR_NO_PRIVILEGE) { /* 3. check obj priv */ ret = OB_SUCCESS; OZ (check_obj_plist_or(guard, tenant_id, user_id, obj_type, obj_id, col_id, raw_obj_priv_array, role_id_array), tenant_id, user_id, obj_type, obj_id, col_id, raw_obj_priv_array); } /* 调整错误码 */ if (!OB_SUCC(ret)) { /* a. normal: to table or view not exists */ if (ret == OB_ERR_EMPTY_QUERY) { ret = OB_ERR_NO_PRIVILEGE; } } } } else if (obj_type == static_cast(ObObjectType::DIRECTORY)) { /* directory对象的owner是sys */ OZ (check_obj_plist_or(guard, tenant_id, user_id, obj_type, obj_id, col_id, raw_obj_priv_array, role_id_array), tenant_id, user_id, obj_type, obj_id, col_id, raw_obj_priv_array, NO_OPTION); /* 调整错误码 */ if (!OB_SUCC(ret)) { ret = OB_ERR_DIRECTORY_ACCESS_DENIED; } } else { ret = OB_ERR_NO_PRIVILEGE; LOG_WARN("Wrong obj type", K(obj_type)); } } /* 兼容oracle错误码 */ if (ret == OB_ERR_NO_PRIVILEGE) { ret = OB_ERR_NO_SYS_PRIVILEGE; } } return ret; } /* 对外接口:check一个用户对一个对象是否有一种权限 1. 先check is owner 2. 再check syspriv 3. 最后check obj priv 4. 错误码的调整。 */ int ObOraSysChecker::check_ora_obj_priv( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObString &database_name, const uint64_t obj_id, const uint64_t col_id, const uint64_t org_obj_type, const ObRawObjPriv raw_obj_priv, uint64_t check_flag, const uint64_t obj_owner_id, const ObIArray &role_id_array) { int ret = OB_SUCCESS; uint64_t obj_type; uint64_t option = 0; obj_type = org_obj_type; if (org_obj_type == static_cast(ObObjectType::VIEW)) { obj_type = static_cast(ObObjectType::TABLE); } if (!is_super_user(user_id)) { if (check_flag == CHECK_FLAG_DIRECT) { OZ (check_ora_obj_priv_for_create_view(guard, tenant_id, user_id, database_name, obj_id, col_id, obj_type, obj_owner_id)); } else { bool is_owner = is_owner_user(user_id, obj_owner_id); if (OB_SUCC(ret)) { if (obj_type == static_cast(ObObjectType::TABLE) || obj_type == static_cast(ObObjectType::INDEX) || obj_type == static_cast(ObObjectType::FUNCTION) || obj_type == static_cast(ObObjectType::PROCEDURE) || obj_type == static_cast(ObObjectType::PACKAGE) || obj_type == static_cast(ObObjectType::SYS_PACKAGE) || obj_type == static_cast(ObObjectType::SYS_PACKAGE_ONLY_OBJ_PRIV) || obj_type == static_cast(ObObjectType::TYPE) || obj_type == static_cast(ObObjectType::SEQUENCE)) { /* 1. check owner*/ if (!is_owner) { ObRawPriv sys_priv = PRIV_ID_NONE; share::ObRawPrivArray plist; bool has_other_priv = false; /* 2. check sys priv */ if (obj_type != static_cast(ObObjectType::SYS_PACKAGE_ONLY_OBJ_PRIV)) { /* 传入原始的obj type,对视图处理 对于视图的dml,和表一样。 */ OZ (map_obj_priv_to_sys_priv(raw_obj_priv, obj_id, org_obj_type, sys_priv), raw_obj_priv, sys_priv); OZ (build_related_plist(org_obj_type, sys_priv, plist)); OX (option = (check_flag != CHECK_FLAG_WITH_GRANT_OPTION) ? NO_OPTION : GRANT_OPTION); if (!plist.empty()) { OZX1 (check_p1_with_plist_info(guard, tenant_id, user_id, sys_priv, option, plist, has_other_priv, role_id_array), OB_ERR_NO_PRIVILEGE, tenant_id, user_id, sys_priv); } else { has_other_priv = true; OZX1 (check_p1(guard, tenant_id, user_id, sys_priv, role_id_array), OB_ERR_NO_PRIVILEGE, tenant_id, user_id, sys_priv); } } else { ret = OB_ERR_NO_PRIVILEGE; obj_type = static_cast(ObObjectType::SYS_PACKAGE); } if (ret == OB_ERR_NO_PRIVILEGE) { /* 3.a check obj priv */ ret = OB_SUCCESS; OZX1 (check_obj_p1(guard, tenant_id, user_id, obj_type, obj_id, col_id, raw_obj_priv, option, role_id_array), OB_ERR_EMPTY_QUERY, tenant_id, user_id, obj_type, obj_id, col_id, raw_obj_priv); } else if (OB_SUCC(ret) && check_flag == CHECK_FLAG_WITH_GRANT_OPTION) { /* 3.b when check grant option, need check obj privs */ OZ (check_obj_p1(guard, tenant_id, user_id, obj_type, obj_id, col_id, raw_obj_priv, option, role_id_array), tenant_id, user_id, obj_type, obj_id, col_id, raw_obj_priv); } /* 调整错误码 */ if (!OB_SUCC(ret)) { if (check_flag != CHECK_FLAG_WITH_GRANT_OPTION) { /* a. normal: to table or view not exists */ if (ret == OB_ERR_EMPTY_QUERY) { if (!has_other_priv) { if (obj_type == static_cast(ObObjectType::FUNCTION)) { ret = OB_WRONG_COLUMN_NAME; } else { ret = OB_TABLE_NOT_EXIST; } } else { ret = OB_ERR_NO_PRIVILEGE; } } } else if (ret == OB_ERR_EMPTY_QUERY || OB_ERR_NO_PRIVILEGE) { /* b. check grantable: with grant option 调整错误码 ORA-01720: grant option does not exist for */ const ObSimpleTableSchemaV2 *view_schema = NULL; if (OB_FAIL(guard.get_simple_table_schema( tenant_id, obj_id, view_schema))) { LOG_WARN("failed to get table schema", K(ret)); } else if (OB_ISNULL(view_schema)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("null table schema", K(ret)); } else { ret = OB_ERR_NO_GRANT_OPTION; LOG_USER_ERROR(OB_ERR_NO_GRANT_OPTION, database_name.length(), database_name.ptr(), view_schema->get_table_name_str().length(), view_schema->get_table_name_str().ptr()); } } } } } else if (obj_type == static_cast(ObObjectType::DIRECTORY)) { /* directory对象的owner是sys */ OZ (check_obj_p1(guard, tenant_id, user_id, obj_type, obj_id, col_id, raw_obj_priv, NO_OPTION, role_id_array), tenant_id, user_id, obj_type, obj_id, col_id, raw_obj_priv, NO_OPTION); /* 调整错误码 */ if (!OB_SUCC(ret)) { ret = OB_ERR_DIRECTORY_ACCESS_DENIED; } } else { ret = OB_TABLE_NOT_EXIST; LOG_WARN("Wrong obj type", K(obj_type)); } } } /* 兼容oracle错误码 */ if (ret == OB_ERR_NO_PRIVILEGE) { ret = OB_ERR_NO_SYS_PRIVILEGE; } } return ret; } /* 对外接口,判断用户是否有登录权限 */ int ObOraSysChecker::check_ora_connect_priv( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObIArray &role_id_array) { int ret = OB_SUCCESS; if (!is_super_user(user_id)) { const ObUserInfo *user_info = NULL; ObRawPriv need_priv = PRIV_ID_CREATE_SESSION; OZ (guard.get_user_info(tenant_id, user_id, user_info), user_id); OZ (check_p1(guard, tenant_id, user_id, need_priv, role_id_array)); if (ret == OB_ERR_NO_PRIVILEGE) { ret = OB_ERR_NO_LOGIN_PRIVILEGE; if (user_info != NULL) { LOG_USER_ERROR(OB_ERR_NO_LOGIN_PRIVILEGE, user_info->get_user_name_str().length(), user_info->get_user_name_str().ptr()); } } } return ret; } /* ddl的对外接口,供仅需要系统权限场景下调用 1. 需要系统权限 2. 或者对象权限 */ int ObOraSysChecker::check_ora_ddl_priv( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObString &database_name, stmt::StmtType stmt_type, const ObIArray &role_id_array) { int ret = OB_SUCCESS; if (!is_super_user(user_id)) { switch (stmt_type) { case stmt::T_CREATE_TABLE: { DEFINE_CREATE_CHECK_CMD(PRIV_ID_CREATE_ANY_TABLE, PRIV_ID_CREATE_TABLE); break; } /* observer to do : alter index case stmt::T_ALTER_INDEX: { DEFINE_DROP_CHECK_CMD(PRIV_ID_ALTER_ANY_INDEX); break; }*/ case stmt::T_DROP_INDEX: { DEFINE_DROP_CHECK_CMD(PRIV_ID_DROP_ANY_INDEX); break; } case stmt::T_CREATE_VIEW: { DEFINE_CREATE_CHECK_CMD(PRIV_ID_CREATE_ANY_VIEW, PRIV_ID_CREATE_VIEW); break; } case stmt::T_CREATE_ROUTINE: { DEFINE_CREATE_CHECK_CMD(PRIV_ID_CREATE_ANY_PROC, PRIV_ID_CREATE_PROC); break; } case stmt::T_ALTER_ROUTINE: { DEFINE_DROP_CHECK_CMD(PRIV_ID_ALTER_ANY_PROC); break; } case stmt::T_DROP_ROUTINE: { DEFINE_DROP_CHECK_CMD(PRIV_ID_DROP_ANY_PROC); break; } case stmt::T_CREATE_SYNONYM: { DEFINE_CREATE_CHECK_CMD(PRIV_ID_CREATE_ANY_SYN, PRIV_ID_CREATE_SYN); break; } case stmt::T_DROP_SYNONYM: { DEFINE_DROP_CHECK_CMD(PRIV_ID_DROP_ANY_SYN); break; } case stmt::T_CREATE_PUB_SYNONYM: { DEFINE_PUB_CHECK_CMD(PRIV_ID_CREATE_PUB_SYN); break; } case stmt::T_DROP_PUB_SYNONYM: { DEFINE_PUB_CHECK_CMD(PRIV_ID_DROP_PUB_SYN); break; } case stmt::T_CREATE_SEQUENCE: { DEFINE_CREATE_CHECK_CMD(PRIV_ID_CREATE_ANY_SEQ, PRIV_ID_CREATE_SEQ); break; } case stmt::T_DROP_SEQUENCE: { DEFINE_DROP_CHECK_CMD(PRIV_ID_DROP_ANY_SEQ); break; } case stmt::T_CREATE_TRIGGER: { DEFINE_CREATE_CHECK_CMD(PRIV_ID_CREATE_ANY_TRIG, PRIV_ID_CREATE_TRIG); break; } case stmt::T_DROP_TRIGGER: { DEFINE_DROP_CHECK_CMD(PRIV_ID_DROP_ANY_TRIG); break; } case stmt::T_ALTER_TRIGGER: { DEFINE_DROP_CHECK_CMD(PRIV_ID_ALTER_ANY_TRIG); break; } case stmt::T_CREATE_ROLE: { DEFINE_PUB_CHECK_CMD(PRIV_ID_CREATE_ROLE); break; } /* xinqi to do: add admin option*/ case stmt::T_DROP_ROLE: { DEFINE_PUB_CHECK_CMD(PRIV_ID_DROP_ANY_ROLE); break; } case stmt::T_ALTER_ROLE: { DEFINE_PUB_CHECK_CMD(PRIV_ID_ALTER_ANY_ROLE); break; } case stmt::T_CREATE_PROFILE: { DEFINE_PUB_CHECK_CMD(PRIV_ID_CREATE_PROFILE); break; } case stmt::T_ALTER_PROFILE: { DEFINE_PUB_CHECK_CMD(PRIV_ID_ALTER_PROFILE); break; } case stmt::T_DROP_PROFILE: { DEFINE_PUB_CHECK_CMD(PRIV_ID_DROP_PROFILE); break; } case stmt::T_CREATE_USER: { DEFINE_PUB_CHECK_CMD(PRIV_ID_CREATE_USER); break; } case stmt::T_ALTER_USER_PROFILE: case stmt::T_ALTER_USER_PRIMARY_ZONE: case stmt::T_ALTER_USER: { DEFINE_PUB_CHECK_CMD(PRIV_ID_ALTER_USER); break; } case stmt::T_SET_PASSWORD: case stmt::T_LOCK_USER: case stmt::T_RENAME_USER: { DEFINE_PUB_CHECK_CMD(PRIV_ID_ALTER_USER); break; } case stmt::T_DROP_USER: { DEFINE_PUB_CHECK_CMD(PRIV_ID_DROP_USER); break; } case stmt::T_CREATE_TYPE: { DEFINE_CREATE_CHECK_CMD(PRIV_ID_CREATE_ANY_TYPE, PRIV_ID_CREATE_TYPE); break; } case stmt::T_DROP_TYPE: { DEFINE_DROP_CHECK_CMD(PRIV_ID_DROP_ANY_TYPE); break; } case stmt::T_FLASHBACK_TABLE_FROM_RECYCLEBIN: { DEFINE_DROP_CHECK_CMD(PRIV_ID_DROP_ANY_TABLE); break; } case stmt::T_PURGE_TABLE: { DEFINE_DROP_CHECK_CMD(PRIV_ID_DROP_ANY_TABLE); break; } case stmt::T_PURGE_INDEX: { DEFINE_DROP_CHECK_CMD(PRIV_ID_DROP_ANY_INDEX); break; } case stmt::T_PURGE_RECYCLEBIN: { DEFINE_PURGE_CHECK_CMD(PRIV_ID_SYSDBA, PRIV_ID_PURGE_DBA_RECYCLEBIN); break; } case stmt::T_CREATE_OUTLINE: { DEFINE_PUB_CHECK_CMD(PRIV_ID_CREATE_ANY_OUTLINE); break; } case stmt::T_ALTER_OUTLINE: { DEFINE_PUB_CHECK_CMD(PRIV_ID_ALTER_ANY_OUTLINE); break; } case stmt::T_DROP_OUTLINE: { DEFINE_PUB_CHECK_CMD(PRIV_ID_DROP_ANY_OUTLINE); break; } case stmt::T_CREATE_KEYSTORE: case stmt::T_ALTER_KEYSTORE: { DEFINE_PUB_CHECK_CMD(PRIV_ID_SYSKM); break; } case stmt::T_CREATE_TABLESPACE: { DEFINE_PUB_CHECK_CMD(PRIV_ID_CREATE_TABLESPACE); break; } case stmt::T_DROP_TABLESPACE: { DEFINE_PUB_CHECK_CMD(PRIV_ID_DROP_TABLESPACE); break; } case stmt::T_ALTER_SYSTEM_SET_PARAMETER: { DEFINE_PUB_CHECK_CMD(PRIV_ID_ALTER_SYSTEM); break; } case stmt::T_KILL: { DEFINE_PUB_CHECK_CMD(PRIV_ID_ALTER_SYSTEM); break; } case stmt::T_CREATE_DBLINK: { DEFINE_PUB_CHECK_CMD(PRIV_ID_CREATE_DBLINK); break; } case stmt::T_DROP_DBLINK: { DEFINE_PUB_CHECK_CMD(PRIV_ID_DROP_DBLINK); break; } case stmt::T_CREATE_RESTORE_POINT: case stmt::T_DROP_RESTORE_POINT: { DEFINE_PURGE_CHECK_CMD(PRIV_ID_FLASHBACK_ANY_TABLE, PRIV_ID_SELECT_ANY_DICTIONARY); break; } case stmt::T_CREATE_DIRECTORY: { DEFINE_PUB_CHECK_CMD(PRIV_ID_CREATE_ANY_DIRECTORY); break; } case stmt::T_DROP_DIRECTORY: { DEFINE_PUB_CHECK_CMD(PRIV_ID_DROP_ANY_DIRECTORY); break; } case stmt::T_CREATE_CONTEXT: { DEFINE_PUB_CHECK_CMD(PRIV_ID_CREATE_ANY_CONTEXT); break; } case stmt::T_DROP_CONTEXT: { DEFINE_PUB_CHECK_CMD(PRIV_ID_DROP_ANY_CONTEXT); break; } case stmt::T_VARIABLE_SET: { DEFINE_PUB_CHECK_CMD(PRIV_ID_ALTER_SYSTEM); break; } case stmt::T_CREATE_MLOG: { DEFINE_CREATE_CHECK_CMD(PRIV_ID_CREATE_ANY_TABLE, PRIV_ID_CREATE_TABLE); break; } case stmt::T_DROP_MLOG: { DEFINE_DROP_CHECK_CMD(PRIV_ID_DROP_ANY_TABLE); break; } default: { ret = OB_ERR_UNEXPECTED; LOG_WARN("stmt type ddl priv undefined", K(stmt_type)); break; } } } if (ret == OB_ERR_NO_PRIVILEGE) { ret = OB_ERR_NO_SYS_PRIVILEGE; } return ret; } /* ddl的对外接口2,供需要系统权限和对象权限时调用 1. 需要系统权限 2. 或者对象权限 */ int ObOraSysChecker::check_ora_ddl_priv( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObString &database_name, const uint64_t obj_id, const uint64_t obj_type, stmt::StmtType stmt_type, const ObIArray &role_id_array) { int ret = OB_SUCCESS; if (!is_super_user(user_id)) { switch (stmt_type) { case stmt::T_ALTER_TABLE: { if (obj_type == static_cast(ObObjectType::TABLE)) { DEFINE_ALTER_CHECK_CMD(PRIV_ID_ALTER_ANY_TABLE, OBJ_PRIV_ID_ALTER); } else { DEFINE_ALTER_CHECK_CMD(PRIV_ID_ALTER_ANY_INDEX, OBJ_PRIV_ID_ALTER); } break; } case stmt::T_CREATE_INDEX: { DEFINE_ALTER_CHECK_CMD(PRIV_ID_CREATE_ANY_INDEX, OBJ_PRIV_ID_INDEX); break; } case stmt::T_FLASHBACK_TABLE_TO_SCN: { DEFINE_ALTER_CHECK_CMD(PRIV_ID_FLASHBACK_ANY_TABLE, OBJ_PRIV_ID_FLASHBACK); DEFINE_ALTER_CHECK_CMD(PRIV_ID_ALTER_ANY_TABLE, OBJ_PRIV_ID_ALTER); break; } case stmt::T_ALTER_SEQUENCE: { DEFINE_ALTER_CHECK_CMD(PRIV_ID_ALTER_ANY_SEQ, OBJ_PRIV_ID_ALTER); break; } case stmt::T_DROP_VIEW: { DEFINE_DROP_VIEW_CHECK_CMD(PRIV_ID_DROP_ANY_VIEW); break; } case stmt::T_DROP_TABLE: { DEFINE_DROP_TABLE_CHECK_CMD(PRIV_ID_DROP_ANY_TABLE); break; } case stmt::T_TRUNCATE_TABLE: { DEFINE_DROP_TABLE_CHECK_CMD(PRIV_ID_DROP_ANY_TABLE); break; } case stmt::T_CREATE_CONTEXT: { DEFINE_ALTER_CHECK_CMD(PRIV_ID_CREATE_ANY_CONTEXT, OBJ_PRIV_ID_CREATE); break; } case stmt::T_DROP_CONTEXT: { DEFINE_ALTER_CHECK_CMD(PRIV_ID_CREATE_ANY_CONTEXT, OBJ_PRIV_ID_DELETE); } default: { ret = OB_ERR_UNEXPECTED; LOG_WARN("stmt type ddl priv undefined", K(stmt_type)); break; } } } if (ret == OB_ERR_NO_PRIVILEGE) { ret = OB_ERR_NO_SYS_PRIVILEGE; } else if (ret == OB_ERR_EMPTY_QUERY) { /* 根据语句类型,对错误码进行设置 */ switch (stmt_type) { case stmt::T_ALTER_TABLE: case stmt::T_CREATE_INDEX: ret = OB_TABLE_NOT_EXIST; break; case stmt::T_ALTER_SEQUENCE: ret = OB_ERR_SEQ_NOT_EXIST; break; default: { ret = OB_ERR_UNEXPECTED; LOG_WARN("stmt type ddl priv undefined", K(stmt_type)); break; } } } return ret; } // check ora user priv int ObOraSysChecker::check_ora_user_sys_priv( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObString &database_name, const ObRawPriv& priv_id, const ObIArray &role_id_array) { UNUSEDx(guard, database_name); int ret = OB_SUCCESS; if (!is_super_user(user_id)) { DEFINE_PUB_CHECK_CMD(priv_id); } return ret; } // ddl 的对外接口,针对列权限 int ObOraSysChecker::check_ora_ddl_ref_priv( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObString &database_name, const uint64_t obj_id, const ObIArray &col_ids, const uint64_t obj_type, stmt::StmtType stmt_type, const ObIArray &role_id_array) { int ret = OB_SUCCESS; if (!is_super_user(user_id)) { const ObUserInfo *user_info = NULL; bool is_owner = false; OZ (guard.get_user_info(tenant_id, user_id, user_info)); if (OB_SUCC(ret) && OB_ISNULL(user_info)) { ret = OB_USER_NOT_EXIST; LOG_WARN("user not exists", K(ret), K(user_id)); } OX (is_owner = ObOraPrivCheck::user_is_owner(user_info->get_user_name(), database_name)); if (false == is_owner) { switch (stmt_type) { case stmt::T_CREATE_TABLE: case stmt::T_ALTER_TABLE: { share::ObRawObjPrivArray table_privs; OZ (table_privs.push_back(OBJ_PRIV_ID_REFERENCES)); OZX2 (check_obj_and_col_priv(guard, tenant_id, user_id, obj_id, obj_type, OBJ_PRIV_ID_REFERENCES, col_ids, role_id_array), OB_ERR_NO_PRIVILEGE, OB_ERR_EMPTY_QUERY); break; } default: { ret = OB_ERR_UNEXPECTED; LOG_WARN("stmt type ddl priv undefined", K(stmt_type)); break; } } } } if (ret == OB_ERR_NO_PRIVILEGE || ret == OB_ERR_EMPTY_QUERY) { ret = OB_SUCCESS; bool accessible = false; OZ (check_access_to_obj(guard, tenant_id, user_id, obj_type, obj_id, database_name, role_id_array, accessible)); OX (ret = accessible ? OB_ERR_NO_SYS_PRIVILEGE : OB_TABLE_NOT_EXIST); } return ret; } // 检查user_id是否具有对obj_id的对象权限p1,如果没有,则检查时候对所有的列都具有对象权限p1 int ObOraSysChecker::check_obj_and_col_priv( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const uint64_t obj_id, const uint64_t obj_type, const ObRawObjPriv p1, const ObIArray &col_ids, const ObIArray &role_id_array) { int ret = OB_SUCCESS; ObRawObjPrivArray plist; OZ (plist.push_back(p1)); // 1. 检查对于表是否具有对象权限 p1 OZX2(check_obj_plist_or(guard, tenant_id, user_id, obj_type, obj_id, OBJ_LEVEL_FOR_TAB_PRIV, plist, role_id_array), OB_ERR_NO_PRIVILEGE, OB_ERR_EMPTY_QUERY); if (OB_ERR_NO_PRIVILEGE == ret || OB_ERR_EMPTY_QUERY == ret) { ret = OB_SUCCESS; for (int i = 0; OB_SUCC(ret) && i < col_ids.count(); ++i) { OZX2(check_obj_plist_or(guard, tenant_id, user_id, obj_type, obj_id, col_ids.at(i), plist, role_id_array), OB_ERR_NO_PRIVILEGE, OB_ERR_EMPTY_QUERY); } } return ret; } /* grant/revoke role的对外接口 1. grant any role的系统权限 2. 或者 所有role的admin option权限 */ int ObOraSysChecker::check_ora_grant_role_priv( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObSEArray &role_granted_id_array, const ObIArray &role_id_array) { int ret = OB_SUCCESS; ObRawPriv priv_need = PRIV_ID_GRANT_ANY_ROLE; const ObUserInfo *user_info = NULL; if (!is_super_user(user_id)) { OZX1 (check_p1(guard, tenant_id, user_id, priv_need, role_id_array), OB_ERR_NO_PRIVILEGE, tenant_id, user_id, priv_need); if (ret == OB_ERR_NO_PRIVILEGE) { ret = OB_SUCCESS; OZ (guard.get_user_info(tenant_id, user_id, user_info)); if (OB_SUCC(ret) && NULL == user_info) { ret = OB_USER_NOT_EXIST; } if (OB_SUCC(ret)) { /* 先在schema里面获取role id和admin option,暂时不管disable/enable 正常的做法: 1. 遍历生效的role id array 2. 对于每个role id,根据user info,或者下标 3. 调用get nth role option获取option 4. 调用get_admin_option 判断是否有 admin option */ for (int i = 0; OB_SUCC(ret) && i < role_granted_id_array.count(); i++) { if (!user_info->role_exists(role_granted_id_array.at(i), ADMIN_OPTION)) { const ObUserInfo *user_info = NULL; OZ (guard.get_user_info(tenant_id, role_granted_id_array.at(i), user_info)); /* 对于dba角色,报错为:ORA-01031: insufficient privileges . 其余角色报错 ORA-01932 ADMIN option not granted for role */ if (OB_SUCC(ret) && user_info != NULL) { if (is_ora_dba_role(role_granted_id_array.at(i))) { ret = OB_ERR_NO_PRIVILEGE; } else { ret = OB_ERR_ADMIN_OPTION_NOT_GRANTED_FOR_ROLE; LOG_USER_ERROR(OB_ERR_ADMIN_OPTION_NOT_GRANTED_FOR_ROLE, user_info->get_user_name_str().length(), user_info->get_user_name_str().ptr()); } } } } } } } return ret; } /* grant/revoke sys priv的对外接口 1. check if has sys priv: grant any privilege 2. check if has sys privs list with admin option */ int ObOraSysChecker::check_ora_grant_sys_priv( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObRawPrivArray &sys_priv_array, const ObIArray &role_id_array) { int ret = OB_SUCCESS; ObRawPriv priv_need = PRIV_ID_GRANT_ANY_PRIV; if (!is_super_user(user_id)) { // 用户不需要 GRANT_ANY_PRIVILEGE with ADMIN option 就可以执行 grant any system privilege OZX1(check_p1(guard, tenant_id, user_id, priv_need, role_id_array), OB_ERR_NO_PRIVILEGE); if (OB_ERR_NO_PRIVILEGE == ret) { ret = OB_SUCCESS; OZ(check_plist_and(guard, tenant_id, user_id, sys_priv_array, role_id_array, ADMIN_OPTION), tenant_id, user_id); } /* 兼容oracle错误码 */ if (ret == OB_ERR_NO_PRIVILEGE) { ret = OB_ERR_NO_SYS_PRIVILEGE; } } return ret; } /* grant/revoke obj priv的对外接口 1. check if is owner, grantor == owner 2. if not owner 2.1 check if has sys priv: grant any object privilege: grantor == owner 2.2 check if has obj privs with grant option: grantor == user_id */ int ObOraSysChecker::check_ora_grant_obj_priv( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObString &db_name, const uint64_t obj_id, const uint64_t obj_type, const ObRawObjPrivArray &table_priv_array, const ObSEArray &ins_col_ids, const ObSEArray &upd_col_ids, const ObSEArray &ref_col_ids, uint64_t &grantor_id_out, const ObIArray &role_id_array) { int ret = OB_SUCCESS; bool is_owner; const ObUserInfo *user_info = NULL; bool has_sys_priv = false; ObRawPriv priv_need = PRIV_ID_GRANT_ANY_OBJECT_PRIV; if (!is_super_user(user_id)) { OZ (guard.get_user_info(tenant_id, user_id, user_info)); if (OB_SUCC(ret) && NULL == user_info) { ret = OB_USER_NOT_EXIST; LOG_USER_ERROR(OB_USER_NOT_EXIST, db_name.length(), db_name.ptr()); } OX (is_owner = ObOraPrivCheck::user_is_owner(user_info->get_user_name(), db_name)); if (OB_SUCC(ret)) { // 1. check owner if (is_owner) { grantor_id_out = user_id; } else { // 2.1 check sys priv OZX1 (check_p1(guard, tenant_id, user_id, priv_need, role_id_array), OB_ERR_NO_PRIVILEGE); // 2.2 decide grantor_id if (OB_SUCC(ret) || ret == OB_ERR_NO_PRIVILEGE) { has_sys_priv = OB_SUCC(ret); ret = OB_SUCCESS; OZ (decide_grantor_id(guard, has_sys_priv, tenant_id, user_id, db_name, grantor_id_out)); } // 2.3 check obj priv if (OB_SUCC(ret) && !has_sys_priv) { OZ (check_objplist(guard, tenant_id, user_id, obj_id, obj_type, table_priv_array, ins_col_ids, upd_col_ids, ref_col_ids, role_id_array), tenant_id, user_id, obj_id, obj_type, table_priv_array, ins_col_ids, upd_col_ids, ref_col_ids); /* 兼容oracle错误码,没有转授权限,也报无权限 */ if (ret == OB_ERR_NO_PRIVILEGE || ret == OB_ERR_EMPTY_QUERY) { ret = OB_ERR_NO_SYS_PRIVILEGE; } } } } } else { bool is_exists = false; uint64_t obj_owner_id = OB_INVALID_ID; OZ (guard.check_user_exist(tenant_id, db_name, ObString(OB_DEFAULT_HOST_NAME), is_exists, &obj_owner_id)); if (OB_SUCC(ret) && is_exists) { grantor_id_out = obj_owner_id; } } return ret; } bool ObOraSysChecker::is_super_user( const uint64_t user_id) { if (is_ora_sys_user(user_id) || is_root_user(user_id)) { return true; } else { return false; } } bool ObOraSysChecker::is_owner_user( const uint64_t user_id, const uint64_t owner_user_id) { return (user_id == owner_user_id || owner_user_id == OB_INVALID_ID); } int ObOraSysChecker::check_ora_show_process_priv( ObSchemaGetterGuard &guard, const uint64_t tenant_id, const uint64_t user_id, const ObIArray &role_id_array) { int ret = OB_SUCCESS; if (!is_super_user(user_id)) { DEFINE_PUB_CHECK_CMD(PRIV_ID_SHOW_PROCESS); } return ret; } } /* namespace sql */ } /* namespace oceanbase */