diff --git a/src/share/parameter/ob_parameter_seed.ipp b/src/share/parameter/ob_parameter_seed.ipp index 98cbf2ea4..03327b1e8 100644 --- a/src/share/parameter/ob_parameter_seed.ipp +++ b/src/share/parameter/ob_parameter_seed.ipp @@ -1400,3 +1400,6 @@ DEF_STR(_load_tde_encrypt_engine, OB_CLUSTER_PARAMETER, "NONE", DEF_INT(_pipelined_table_function_memory_limit, OB_TENANT_PARAMETER, "524288000", "[1024,18446744073709551615]", "pipeline table function result set memory size limit. default 524288000 (500M), Range: [1024,18446744073709551615]", ObParameterAttr(Section::OBSERVER, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE)); +DEF_BOOL(_enable_reserved_user_dcl_restriction, OB_CLUSTER_PARAMETER, "False", + "specifies whether to forbid non-reserved user to modify reserved users", + ObParameterAttr(Section::OBSERVER, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE)); diff --git a/src/sql/resolver/dcl/ob_alter_user_primary_zone_resolver.cpp b/src/sql/resolver/dcl/ob_alter_user_primary_zone_resolver.cpp index 5fb78df58..2f206cd23 100644 --- a/src/sql/resolver/dcl/ob_alter_user_primary_zone_resolver.cpp +++ b/src/sql/resolver/dcl/ob_alter_user_primary_zone_resolver.cpp @@ -51,8 +51,17 @@ int ObAlterUserPrimaryZoneResolver::resolve(const ParseNode &parse_tree) LOG_WARN("unexpected null user or null primary zone", K(primary_zone_node), K(user_node), K(ret)); } else { ObString user_name; + ObString host_name; user_name.assign_ptr(user_node->children_[0]->str_value_, static_cast(user_node->children_[0]->str_len_)); + host_name.assign_ptr(OB_DEFAULT_HOST_NAME, static_cast(STRLEN(OB_DEFAULT_HOST_NAME))); + if (OB_FAIL(check_dcl_on_inner_user(parse_tree.type_, + params_.session_info_->get_priv_user_id(), + user_name, + host_name))) { + LOG_WARN("failed to check dcl on inner-user or unsupport to modify reserved user", K(ret), + K(params_.session_info_->get_user_name()), K(user_name)); + } OZ(ObDatabaseResolver::resolve_primary_zone( stmt, primary_zone_node)); stmt->set_tenant_id(params_.session_info_->get_effective_tenant_id()); diff --git a/src/sql/resolver/dcl/ob_alter_user_profile_resolver.cpp b/src/sql/resolver/dcl/ob_alter_user_profile_resolver.cpp index a48c3db1e..9eee2aed0 100644 --- a/src/sql/resolver/dcl/ob_alter_user_profile_resolver.cpp +++ b/src/sql/resolver/dcl/ob_alter_user_profile_resolver.cpp @@ -321,16 +321,16 @@ int ObAlterUserProfileResolver::resolve_default_role(const ParseNode &parse_tree } OZ (params_.schema_checker_->get_user_info(tenant_id, user_name, host_name, user_info), tenant_id, user_name, host_name); - if (ret == OB_USER_NOT_EXIST) { + if (ret == OB_USER_NOT_EXIST || OB_ISNULL(user_info)) { + ret = OB_USER_NOT_EXIST; LOG_USER_ERROR(OB_USER_NOT_EXIST, user_name.length(), user_name.ptr()); - } - if (OB_SUCC(ret)) { - if (user_info == NULL) { - ret = OB_USER_NOT_EXIST; - LOG_USER_ERROR(OB_USER_NOT_EXIST, user_name.length(), user_name.ptr()); - } else { - arg.user_id_ = user_info->get_user_id(); - } + } else if (OB_FAIL(check_dcl_on_inner_user(parse_tree.type_, + session_info_->get_priv_user_id(), + user_info->get_user_id()))) { + LOG_WARN("failed to check dcl on inner-user or unsupport to modify reserved user", K(ret), + K(session_info_->get_user_name()), K(user_name)); + } else { + arg.user_id_ = user_info->get_user_id(); } /* 2. resolve default role */ @@ -403,8 +403,14 @@ int ObAlterUserProfileResolver::resolve(const ParseNode &parse_tree) arg.profile_name_ = ObString(profile_name->str_len_, profile_name->str_value_); } arg.tenant_id_ = params_.session_info_->get_effective_tenant_id(); + if (OB_FAIL(check_dcl_on_inner_user(parse_tree.type_, + session_info_->get_priv_user_id(), + arg.user_name_, + arg.host_name_))) { + LOG_WARN("failed to check dcl on inner-user or unsupport to modify reserved user", K(ret), + K(params_.session_info_->get_user_name()), K(arg.user_name_)); + } } - if (OB_SUCC(ret) && T_SET_ROLE != parse_tree.type_ && ObSchemaChecker::is_ora_priv_check()) { OZ (schema_checker_->check_ora_ddl_priv( diff --git a/src/sql/resolver/dcl/ob_dcl_resolver.cpp b/src/sql/resolver/dcl/ob_dcl_resolver.cpp index 0642e026c..dd2d49c72 100644 --- a/src/sql/resolver/dcl/ob_dcl_resolver.cpp +++ b/src/sql/resolver/dcl/ob_dcl_resolver.cpp @@ -361,3 +361,104 @@ int ObDCLResolver::mask_password_for_passwd_node(ObIAllocator *allocator, LOG_DEBUG("finish mask_password_for_passwd_node", K(src), K(masked_sql)); return ret; } + +int ObDCLResolver::check_dcl_on_inner_user(const ObItemType &type, + const uint64_t &session_user_id, + const ObString &user_name, + const ObString &host_name) { + int ret = OB_SUCCESS; + uint64_t user_id = OB_INVALID_ID; + bool is_valid = true; + if (GCONF._enable_reserved_user_dcl_restriction) { + if (T_ALTER_USER_DEFAULT_ROLE == type || + T_ALTER_USER_PRIMARY_ZONE == type || + T_ALTER_USER_PROFILE == type || + T_DROP_USER == type || + T_GRANT == type || + T_LOCK_USER == type || + T_RENAME_USER == type || + T_REVOKE == type || + T_REVOKE_ALL == type || + T_REVOKE_ROLE == type || + T_SET_PASSWORD == type || + T_SET_ROLE == type || + T_SYSTEM_REVOKE == type) { + if (user_name.empty() || session_user_id == OB_INVALID_ID) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("failed. get empty user name or invalid session user id", K(ret), K(user_name), + K(session_user_id)); + } else if (OB_ISNULL(schema_checker_) || OB_ISNULL(params_.session_info_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("failed. get NULL ptr", K(ret), K(schema_checker_), K(params_.session_info_)); + } else if (OB_FAIL(schema_checker_->get_user_id( + params_.session_info_->get_effective_tenant_id(), + user_name, + host_name, + user_id))) { + if (OB_USER_NOT_EXIST == ret) { + ret = OB_ERR_USER_OR_ROLE_DOES_NOT_EXIST; + LOG_USER_ERROR(OB_ERR_USER_OR_ROLE_DOES_NOT_EXIST, user_name.length(), user_name.ptr()); + } + LOG_WARN("failed to get user id", K(ret), K(user_name)); + } + if (OB_SUCC(ret)) { + if (OB_SYS_USER_ID == user_id || + OB_ORA_SYS_USER_ID == user_id || + OB_ORA_AUDITOR_USER_ID == user_id || + OB_ORA_LBACSYS_USER_ID == user_id) { + if (session_user_id != user_id && + OB_SYS_USER_ID != session_user_id && + OB_ORA_SYS_USER_ID != session_user_id) { + is_valid = false; + } + } + } + } + } + if (OB_SUCC(ret) && !is_valid) { + ret = OB_NOT_SUPPORTED; + LOG_USER_ERROR(OB_NOT_SUPPORTED, "modify on reserved user"); + } + return ret; +} + +int ObDCLResolver::check_dcl_on_inner_user(const ObItemType &type, + const uint64_t &session_user_id, + const uint64_t &user_id) { + int ret = OB_SUCCESS; + bool is_valid = true; + if (GCONF._enable_reserved_user_dcl_restriction) { + if (T_ALTER_USER_DEFAULT_ROLE == type || + T_ALTER_USER_PRIMARY_ZONE == type || + T_ALTER_USER_PROFILE == type || + T_DROP_USER == type || + T_GRANT == type || + T_LOCK_USER == type || + T_RENAME_USER == type || + T_REVOKE == type || + T_REVOKE_ALL == type || + T_REVOKE_ROLE == type || + T_SET_PASSWORD == type || + T_SET_ROLE == type || + T_SYSTEM_REVOKE == type) { + if (OB_INVALID_ID == user_id || OB_INVALID_ID == session_user_id) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("failed.invalid session user id/user id", K(ret), K(user_id), K(session_user_id)); + } else if (OB_SYS_USER_ID == user_id || + OB_ORA_SYS_USER_ID == user_id || + OB_ORA_AUDITOR_USER_ID == user_id || + OB_ORA_LBACSYS_USER_ID == user_id) { + if (session_user_id != user_id && + OB_SYS_USER_ID != session_user_id && + OB_ORA_SYS_USER_ID != session_user_id) { + is_valid = false; + } + } + } + } + if (OB_SUCC(ret) && !is_valid) { + ret = OB_NOT_SUPPORTED; + LOG_USER_ERROR(OB_NOT_SUPPORTED, "modify on reserved user"); + } + return ret; +} \ No newline at end of file diff --git a/src/sql/resolver/dcl/ob_dcl_resolver.h b/src/sql/resolver/dcl/ob_dcl_resolver.h index 9472af9bf..0a15aa1e6 100644 --- a/src/sql/resolver/dcl/ob_dcl_resolver.h +++ b/src/sql/resolver/dcl/ob_dcl_resolver.h @@ -40,6 +40,13 @@ protected: int64_t profile_id, common::ObString &password, common::ObString &user_name); + int check_dcl_on_inner_user(const ObItemType &type, + const uint64_t &session_user_id, + const ObString &user_name, + const ObString &host_name); + int check_dcl_on_inner_user(const ObItemType &type, + const uint64_t &session_user_id, + const uint64_t &user_id); static int mask_password_for_single_user(ObIAllocator *allocator, const common::ObString &src, const ParseNode *user_node, diff --git a/src/sql/resolver/dcl/ob_drop_user_resolver.cpp b/src/sql/resolver/dcl/ob_drop_user_resolver.cpp index 511f06c92..5b898a91c 100644 --- a/src/sql/resolver/dcl/ob_drop_user_resolver.cpp +++ b/src/sql/resolver/dcl/ob_drop_user_resolver.cpp @@ -127,8 +127,12 @@ int ObDropUserResolver::resolve(const ParseNode &parse_tree) } else if (is_inner_user_or_role(user_info->get_user_id())) { ret = OB_ERR_NO_PRIVILEGE; SQL_RESV_LOG(WARN, "Can not drop internal user", K(ret)); + } else if (OB_FAIL(check_dcl_on_inner_user(top_node->type_, + params_.session_info_->get_priv_user_id(), + user_info->get_user_id()))) { + LOG_WARN("failed to check dcl on inner-user or unsupport to modify reserved user", + K(ret), K(params_.session_info_->get_user_name()), K(user_name)); } - if (OB_SUCC(ret)) { if (OB_FAIL(drop_user_stmt->add_user(user_name, host_name))) { LOG_WARN("Add user error", K(user_name), K(ret)); diff --git a/src/sql/resolver/dcl/ob_grant_resolver.cpp b/src/sql/resolver/dcl/ob_grant_resolver.cpp index ab680a377..f8f025133 100644 --- a/src/sql/resolver/dcl/ob_grant_resolver.cpp +++ b/src/sql/resolver/dcl/ob_grant_resolver.cpp @@ -1072,6 +1072,12 @@ int ObGrantResolver::resolve_grant_obj_privileges( if (user_name.length() > OB_MAX_USER_NAME_LENGTH) { ret = OB_WRONG_USER_NAME_LENGTH; LOG_USER_ERROR(OB_WRONG_USER_NAME_LENGTH, user_name.length(), user_name.ptr()); + } else if (OB_FAIL(check_dcl_on_inner_user(node->type_, + session_info_->get_priv_user_id(), + user_name, + host_name))) { + LOG_WARN("failed to check dcl on inner-user or unsupport to modify reserved user", + K(ret), K(session_info_->get_user_name()), K(user_name)); } else if (OB_FAIL(grant_stmt->add_grantee(user_name))) { LOG_WARN("Add grantee error", K(user_name), K(ret)); } else if (OB_FAIL(grant_stmt->add_user(user_name, host_name, pwd, need_enc))) { @@ -1307,6 +1313,12 @@ int ObGrantResolver::resolve_mysql(const ParseNode &parse_tree) if (user_name.length() > OB_MAX_USER_NAME_LENGTH) { ret = OB_WRONG_USER_NAME_LENGTH; LOG_USER_ERROR(OB_WRONG_USER_NAME_LENGTH, user_name.length(), user_name.ptr()); + } else if (OB_FAIL(check_dcl_on_inner_user(node->type_, + session_info_->get_priv_user_id(), + user_name, + host_name))) { + LOG_WARN("failed to check dcl on inner-user or unsupport to modify reserved user", + K(ret), K(session_info_->get_user_name()), K(user_name)); } else if (OB_FAIL(grant_stmt->add_grantee(user_name))) { LOG_WARN("Add grantee error", K(user_name), K(ret)); } else if (OB_FAIL(grant_stmt->add_user(user_name, host_name, pwd, need_enc))) { diff --git a/src/sql/resolver/dcl/ob_lock_user_resolver.cpp b/src/sql/resolver/dcl/ob_lock_user_resolver.cpp index ff659f3aa..770a33de8 100644 --- a/src/sql/resolver/dcl/ob_lock_user_resolver.cpp +++ b/src/sql/resolver/dcl/ob_lock_user_resolver.cpp @@ -95,10 +95,14 @@ int ObLockUserResolver::resolve(const ParseNode &parse_tree) host_name.assign_ptr(user_hostname_node->children_[1]->str_value_, static_cast(user_hostname_node->children_[1]->str_len_)); } - if (OB_FAIL(lock_user_stmt->add_user(user_name, host_name))) { + if (OB_FAIL(check_dcl_on_inner_user(node->type_, + session_info_->get_priv_user_id(), + user_name, + host_name))) { + LOG_WARN("failed to check dcl on inner-user or unsupport to modify reserved user", + K(ret), K(params_.session_info_->get_user_name()), K(user_name)); + } else if (OB_FAIL(lock_user_stmt->add_user(user_name, host_name))) { SQL_RESV_LOG(WARN, "Add user error", K(user_name), K(host_name), K(ret)); - } else { - //do nothing } } } diff --git a/src/sql/resolver/dcl/ob_rename_user_resolver.cpp b/src/sql/resolver/dcl/ob_rename_user_resolver.cpp index 9b0e65e5b..dcd2508b5 100644 --- a/src/sql/resolver/dcl/ob_rename_user_resolver.cpp +++ b/src/sql/resolver/dcl/ob_rename_user_resolver.cpp @@ -65,7 +65,6 @@ int ObRenameUserResolver::resolve(const ParseNode &parse_tree) to_host.assign_ptr(rename_info->children_[3]->str_value_, static_cast(rename_info->children_[3]->str_len_)); } - if ((0 == to_user.case_compare(OB_RESTORE_USER_NAME)) || (0 == from_user.case_compare(OB_RESTORE_USER_NAME))) { ret = OB_ERR_NO_PRIVILEGE; LOG_WARN("__oceanbase_inner_restore_user is reserved", K(ret)); @@ -73,6 +72,12 @@ int ObRenameUserResolver::resolve(const ParseNode &parse_tree) LOG_USER_ERROR(OB_WRONG_USER_NAME_LENGTH, from_user.length(), from_user.ptr()); } else if (to_user.length() > OB_MAX_USER_NAME_LENGTH) { LOG_USER_ERROR(OB_WRONG_USER_NAME_LENGTH, to_user.length(), to_user.ptr()); + } else if (OB_FAIL(check_dcl_on_inner_user(node->type_, + session_info_->get_priv_user_id(), + from_user, + from_host))) { + LOG_WARN("failed to check dcl on inner-user or unsupport to modify reserved user", + K(ret), K(session_info_->get_user_name()), K(from_user)); } else if (OB_FAIL(rename_user_stmt->add_rename_info(from_user, from_host, to_user, to_host))) { LOG_WARN("Failed to add user to ObRenameUserStmt", K(ret)); } else { diff --git a/src/sql/resolver/dcl/ob_revoke_resolver.cpp b/src/sql/resolver/dcl/ob_revoke_resolver.cpp index f2897cc55..4c20fac68 100644 --- a/src/sql/resolver/dcl/ob_revoke_resolver.cpp +++ b/src/sql/resolver/dcl/ob_revoke_resolver.cpp @@ -107,6 +107,11 @@ int ObRevokeResolver::resolve_revoke_role_inner( LOG_USER_ERROR(OB_ERR_USER_OR_ROLE_DOES_NOT_EXIST, user_name.length(), user_name.ptr()); } LOG_WARN("fail to get user id", K(ret), K(user_name), K(host_name)); + } else if (OB_FAIL(check_dcl_on_inner_user(revoke_role->type_, + params_.session_info_->get_priv_user_id(), + user_id))) { + LOG_WARN("failed to check dcl on inner-user or unsupport to modify reserved user", K(ret), + K(session_info_->get_priv_user_id()), K(user_name)); } OZ (revoke_stmt->add_grantee(user_name)); OZ (params_.schema_checker_->get_user_info(tenant_id, user_id, user_info), user_id); @@ -193,6 +198,11 @@ int ObRevokeResolver::resolve_revoke_sysprivs_inner( LOG_USER_ERROR(OB_ERR_USER_OR_ROLE_DOES_NOT_EXIST, user_name.length(), user_name.ptr()); } LOG_WARN("fail to get user id", K(ret), K(user_name), K(host_name)); + } else if (OB_FAIL(check_dcl_on_inner_user(revoke_role->type_, + params_.session_info_->get_priv_user_id(), + user_id))) { + LOG_WARN("failed to check dcl on inner-user or unsupport to modify reserved user", K(ret), + K(session_info_->get_priv_user_id()), K(user_name)); } OZ (params_.schema_checker_->get_user_info( revoke_stmt->get_tenant_id(), user_id, user_info), user_id); @@ -363,6 +373,11 @@ int ObRevokeResolver::resolve_mysql(const ParseNode &parse_tree) ret = OB_NOT_SUPPORTED; LOG_WARN("Revoke privilege from root at global level is not supported", K(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "Revoke privilege from root at global level"); + } else if (OB_FAIL(check_dcl_on_inner_user(node->type_, + params_.session_info_->get_priv_user_id(), + user_id))) { + LOG_WARN("failed to check dcl on inner-user or unsupport to modify reserved user", + K(ret), K(session_info_->get_priv_user_id()), K(user_name)); } else if (OB_FAIL(revoke_stmt->add_user(user_id))) { LOG_WARN("Add user to grant_stmt error", K(ret), K(user_id)); } else { @@ -608,6 +623,11 @@ int ObRevokeResolver::resolve_revoke_role_and_sysprivs_inner(const ParseNode *no LOG_USER_ERROR(OB_ERR_USER_OR_ROLE_DOES_NOT_EXIST, user_name.length(), user_name.ptr()); } LOG_WARN("fail to get user id", K(ret), K(user_name), K(host_name)); + } else if (OB_FAIL(check_dcl_on_inner_user(node->type_, + params_.session_info_->get_priv_user_id(), + user_id))) { + LOG_WARN("failed to check dcl on inner-user or unsupport to modify reserved user", K(ret), + K(session_info_->get_priv_user_id()), K(user_id)); } OZ (revoke_stmt->add_grantee(user_name)); OZ (params_.schema_checker_->get_user_info(tenant_id, user_id, user_info), user_id); @@ -784,6 +804,11 @@ int ObRevokeResolver::resolve_revoke_obj_priv_inner(const ParseNode *node, ret = OB_NOT_SUPPORTED; LOG_WARN("Revoke privilege from root at global level is not supported", K(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "Revoke privilege from root at global level"); + } else if (OB_FAIL(check_dcl_on_inner_user(node->type_, + params_.session_info_->get_priv_user_id(), + user_id))) { + LOG_WARN("failed to check dcl on inner-user or unsupport to modify reserved user", + K(ret), K(params_.session_info_->get_priv_user_id()), K(user_id)); } else if (OB_FAIL(revoke_stmt->add_user(user_id))) { LOG_WARN("Add user to grant_stmt error", K(ret), K(user_id)); } else { diff --git a/src/sql/resolver/dcl/ob_set_password_resolver.cpp b/src/sql/resolver/dcl/ob_set_password_resolver.cpp index f369db277..3b7d730f7 100644 --- a/src/sql/resolver/dcl/ob_set_password_resolver.cpp +++ b/src/sql/resolver/dcl/ob_set_password_resolver.cpp @@ -108,7 +108,15 @@ int ObSetPasswordResolver::resolve(const ParseNode &parse_tree) host_name = session_host_name; set_pwd_stmt->set_for_current_user(true); } - + if (OB_SUCC(ret)) { + if (OB_FAIL(check_dcl_on_inner_user(node->type_, + params_.session_info_->get_priv_user_id(), + user_name, + host_name))) { + LOG_WARN("failed to check dcl on inner-user or unsupport to modify reserved user", K(ret), + K(params_.session_info_->get_priv_user_id()), K(user_name)); + } + } if (OB_SUCC(ret)) { // replace password to *** in query_string for audit ObString masked_sql; diff --git a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/all_virtual_sys_parameter_stat.result b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/all_virtual_sys_parameter_stat.result index 767d3e6cc..97209af17 100644 --- a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/all_virtual_sys_parameter_stat.result +++ b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/all_virtual_sys_parameter_stat.result @@ -262,6 +262,7 @@ _enable_protocol_diagnose _enable_px_batch_rescan _enable_px_bloom_filter_sync _enable_px_ordered_coord +_enable_reserved_user_dcl_restriction _enable_resource_limit_spec _enable_tenant_sql_net_thread _enable_trace_session_leak