diff --git a/deps/oblib/src/lib/mysqlclient/ob_isql_connection.h b/deps/oblib/src/lib/mysqlclient/ob_isql_connection.h index e2794c45e2..e764c624b5 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_isql_connection.h +++ b/deps/oblib/src/lib/mysqlclient/ob_isql_connection.h @@ -101,7 +101,8 @@ public: last_set_client_charset_cstr_(NULL), last_set_connection_charset_cstr_(NULL), last_set_results_charset_cstr_(NULL), - next_conn_(NULL) + next_conn_(NULL), + check_priv_(false) {} virtual ~ObISQLConnection() { allocator_.reset(); @@ -265,6 +266,8 @@ public: void dblink_unwlock() { dblink_lock_.wlock()->unlock(); } ObISQLConnection *get_next_conn() { return next_conn_; } void set_next_conn(ObISQLConnection *conn) { next_conn_ = conn; } + void set_check_priv(bool on) { check_priv_ = on; } + bool is_check_priv() { return check_priv_; } protected: bool oracle_mode_; bool is_inited_; // for oracle dblink, we have to init remote env with some sql @@ -283,6 +286,7 @@ protected: common::ObArenaAllocator allocator_; obsys::ObRWLock dblink_lock_; ObISQLConnection *next_conn_; // used in dblink_conn_map_ + bool check_priv_; }; } // end namespace sqlclient diff --git a/src/observer/ob_inner_sql_connection.cpp b/src/observer/ob_inner_sql_connection.cpp index 0badc0d342..3e5bbeed65 100644 --- a/src/observer/ob_inner_sql_connection.cpp +++ b/src/observer/ob_inner_sql_connection.cpp @@ -441,8 +441,8 @@ int ObInnerSQLConnection::init_result(ObInnerSQLResult &res, result_set.get_exec_context().set_sql_ctx(&res.sql_ctx()); res.sql_ctx().retry_times_ = retry_cnt; res.sql_ctx().session_info_ = &get_session(); - res.sql_ctx().disable_privilege_check_ = OB_SYS_TENANT_ID == res.sql_ctx().session_info_->get_priv_tenant_id() - ? PRIV_CHECK_FLAG_DISABLE : PRIV_CHECK_FLAG_DISABLE; + res.sql_ctx().disable_privilege_check_ = is_check_priv() + ? PRIV_CHECK_FLAG_NORMAL : PRIV_CHECK_FLAG_DISABLE; res.sql_ctx().secondary_namespace_ = secondary_namespace; res.sql_ctx().is_prepare_protocol_ = is_prepare_protocol; res.sql_ctx().is_prepare_stage_ = is_prepare_stage; diff --git a/src/observer/virtual_table/ob_mysql_db_table.cpp b/src/observer/virtual_table/ob_mysql_db_table.cpp index 07c4b83d6a..f4260afa7a 100644 --- a/src/observer/virtual_table/ob_mysql_db_table.cpp +++ b/src/observer/virtual_table/ob_mysql_db_table.cpp @@ -121,9 +121,9 @@ int ObMySQLDBTable::inner_get_next_row(common::ObNewRow *&row) NO_EXIST_PRIV_CASE(LOCK_TABLES); EXIST_PRIV_CASE(CREATE_VIEW); EXIST_PRIV_CASE(SHOW_VIEW); - NO_EXIST_PRIV_CASE(CREATE_ROUTINE); - NO_EXIST_PRIV_CASE(ALTER_ROUTINE); - NO_EXIST_PRIV_CASE(EXECUTE); + EXIST_PRIV_CASE(CREATE_ROUTINE); + EXIST_PRIV_CASE(ALTER_ROUTINE); + EXIST_PRIV_CASE(EXECUTE); NO_EXIST_PRIV_CASE(EVENT); NO_EXIST_PRIV_CASE(TRIGGER); diff --git a/src/observer/virtual_table/ob_mysql_user_table.cpp b/src/observer/virtual_table/ob_mysql_user_table.cpp index 397d441661..bc8024c358 100644 --- a/src/observer/virtual_table/ob_mysql_user_table.cpp +++ b/src/observer/virtual_table/ob_mysql_user_table.cpp @@ -135,15 +135,15 @@ int ObMySQLUserTable::inner_get_next_row(common::ObNewRow *&row) EXIST_PRIV_CASE(SUPER); NO_EXIST_PRIV_CASE(CREATE_TMP_TABLE); NO_EXIST_PRIV_CASE(LOCK_TABLES); - NO_EXIST_PRIV_CASE(EXECUTE); + EXIST_PRIV_CASE(EXECUTE); EXIST_PRIV_CASE(REPL_SLAVE); EXIST_PRIV_CASE(REPL_CLIENT); EXIST_PRIV_CASE(DROP_DATABASE_LINK); EXIST_PRIV_CASE(CREATE_DATABASE_LINK); EXIST_PRIV_CASE(CREATE_VIEW); EXIST_PRIV_CASE(SHOW_VIEW); - NO_EXIST_PRIV_CASE(CREATE_ROUTINE); - NO_EXIST_PRIV_CASE(ALTER_ROUTINE); + EXIST_PRIV_CASE(CREATE_ROUTINE); + EXIST_PRIV_CASE(ALTER_ROUTINE); EXIST_PRIV_CASE(CREATE_USER); NO_EXIST_PRIV_CASE(EVENT); NO_EXIST_PRIV_CASE(TRIGGER); diff --git a/src/rootserver/ob_ddl_operator.cpp b/src/rootserver/ob_ddl_operator.cpp index 5923a71167..030e8ca5d0 100644 --- a/src/rootserver/ob_ddl_operator.cpp +++ b/src/rootserver/ob_ddl_operator.cpp @@ -8139,6 +8139,7 @@ int ObDDLOperator::revoke_table( const uint64_t tenant_id = table_priv_key.tenant_id_; ObSchemaGetterGuard schema_guard; ObSchemaService *schema_sql_service = schema_service_.get_schema_service(); + bool is_oracle_mode = false; if (OB_ISNULL(schema_sql_service)) { ret = OB_ERR_SYS; LOG_ERROR("schama service_impl and schema manage must not null", @@ -8149,6 +8150,8 @@ int ObDDLOperator::revoke_table( LOG_WARN("db_priv_key is invalid", K(table_priv_key), K(ret)); } else if (OB_FAIL(schema_service_.get_tenant_schema_guard(tenant_id, schema_guard))) { LOG_WARN("failed to get schema guard", K(ret)); + } else if (OB_FAIL(ObCompatModeGetter::check_is_oracle_mode_with_tenant_id(tenant_id, is_oracle_mode))) { + LOG_WARN("fail to get compat mode", K(ret)); } else { ObPrivSet table_priv_set = OB_PRIV_SET_EMPTY; if (OB_FAIL(schema_guard.get_table_priv_set(table_priv_key, table_priv_set))) { @@ -8229,6 +8232,8 @@ int ObDDLOperator::revoke_table( if (OB_SUCC(ret) && revoke_all_ora) { OZ (revoke_table_all(schema_guard, tenant_id, obj_priv_key, ddl_sql, trans)); } + } else if (!is_oracle_mode) { + //do nothing } else { ObSqlString ddl_stmt_str; ObString ddl_sql; diff --git a/src/share/ob_compatibility_security_feature_def.h b/src/share/ob_compatibility_security_feature_def.h index 006079bc5d..bc98008a11 100644 --- a/src/share/ob_compatibility_security_feature_def.h +++ b/src/share/ob_compatibility_security_feature_def.h @@ -17,4 +17,10 @@ DEF_COMPAT_CONTROL_FEATURE(MYSQL_PRIV_ENHANCE, "add privilege check to some command", MOCK_CLUSTER_VERSION_4_2_3_0, CLUSTER_VERSION_4_3_0_0, CLUSTER_VERSION_4_3_2_0) +DEF_COMPAT_CONTROL_FEATURE(MYSQL_SET_VAR_PRIV_ENHANCE, "check privilege for set var subquery", + MOCK_CLUSTER_VERSION_4_2_4_0, CLUSTER_VERSION_4_3_0_0, + CLUSTER_VERSION_4_3_2_0) +DEF_COMPAT_CONTROL_FEATURE(MYSQL_USER_REVOKE_ALL_ENHANCE, "use create_user to check privilege for revoke all from user", + MOCK_CLUSTER_VERSION_4_2_4_0, CLUSTER_VERSION_4_3_0_0, + CLUSTER_VERSION_4_3_2_0) #endif diff --git a/src/share/schema/ob_ddl_sql_service.cpp b/src/share/schema/ob_ddl_sql_service.cpp index 9e5a82f2ba..352d7ffdf2 100644 --- a/src/share/schema/ob_ddl_sql_service.cpp +++ b/src/share/schema/ob_ddl_sql_service.cpp @@ -38,6 +38,8 @@ int ObDDLSqlService::log_operation( ObString ddl_str_hex; ObSqlString hex_sql_string; ObSqlString tmp_sql_string; + ObSqlString hex_database_string; + ObSqlString hex_table_string; ObSqlString *sql_string = (NULL != public_sql_string ? public_sql_string : &tmp_sql_string); sql_string->reuse(); auto *tsi_value = GET_TSI(TSIDDLVar); @@ -63,6 +65,10 @@ int ObDDLSqlService::log_operation( } else if (OB_ISNULL(tsi_value)) { int tmp_ret = OB_ERR_UNEXPECTED; LOG_WARN("Failed to get TSIDDLVar", K(tmp_ret), K(schema_operation)); + } else if (OB_FAIL(sql_append_hex_escape_str(schema_operation.database_name_, hex_database_string))) { + LOG_WARN("sql_append_hex_escape_str failed", K(ret), K(schema_operation.database_name_)); + } else if (OB_FAIL(sql_append_hex_escape_str(schema_operation.table_name_, hex_table_string))) { + LOG_WARN("sql_append_hex_escape_str failed", K(ret), K(schema_operation.table_name_)); } else if (OB_FAIL(sql_append_hex_escape_str(schema_operation.ddl_stmt_str_, hex_sql_string))) { LOG_WARN("sql_append_hex_escape_str failed", K(schema_operation.ddl_stmt_str_)); } else { @@ -77,19 +83,19 @@ int ObDDLSqlService::log_operation( int64_t affected_rows = 0; if (OB_FAIL(sql_string->append_fmt("INSERT INTO %s (SCHEMA_VERSION, TENANT_ID, EXEC_TENANT_ID, USER_ID, DATABASE_ID, " "DATABASE_NAME, TABLEGROUP_ID, TABLE_ID, TABLE_NAME, OPERATION_TYPE, DDL_STMT_STR, gmt_modified) " - "values (%ld, %lu, %lu, %lu, %lu, '%.*s', %ld, %lu, '%.*s', %d, %.*s, now(6))", + "values (%ld, %lu, %lu, %lu, %lu, %.*s, %ld, %lu, %.*s, %d, %.*s, now(6))", OB_ALL_DDL_OPERATION_TNAME, schema_operation.schema_version_, is_tenant_operation(schema_operation.op_type_) ? schema_operation.tenant_id_ : OB_INVALID_TENANT_ID, static_cast(exec_tenant_id), // not used after schema splited fill_schema_id(sql_tenant_id, schema_operation.user_id_), fill_schema_id(sql_tenant_id, schema_operation.database_id_), - schema_operation.database_name_.length(), - schema_operation.database_name_.ptr(), + hex_database_string.string().length(), + hex_database_string.string().ptr(), fill_schema_id(sql_tenant_id, schema_operation.tablegroup_id_), fill_schema_id(sql_tenant_id, schema_operation.table_id_), - schema_operation.table_name_.length(), - schema_operation.table_name_.ptr(), + hex_table_string.string().length(), + hex_table_string.string().ptr(), schema_operation.op_type_, ddl_str_hex.length(), ddl_str_hex.ptr()))) { diff --git a/src/share/schema/ob_priv_sql_service.cpp b/src/share/schema/ob_priv_sql_service.cpp index 3c918b7976..897b112ca2 100644 --- a/src/share/schema/ob_priv_sql_service.cpp +++ b/src/share/schema/ob_priv_sql_service.cpp @@ -614,7 +614,7 @@ int ObPrivSqlService::delete_db_priv( exec_tenant_id, org_db_key.tenant_id_))) || OB_FAIL(dml.add_pk_column("USER_ID", ObSchemaUtils::get_extract_schema_id( exec_tenant_id, org_db_key.user_id_))) - || OB_FAIL(dml.add_pk_column("DATABASE_NAME", org_db_key.db_)) + || OB_FAIL(dml.add_pk_column("DATABASE_NAME", ObHexEscapeSqlStr(org_db_key.db_))) || OB_FAIL(dml.add_gmt_modified())) { LOG_WARN("add column failed", K(ret)); } @@ -698,8 +698,8 @@ int ObPrivSqlService::delete_table_priv( exec_tenant_id, table_priv_key.tenant_id_))) || OB_FAIL(dml.add_pk_column("USER_ID", ObSchemaUtils::get_extract_schema_id( exec_tenant_id, table_priv_key.user_id_))) - || OB_FAIL(dml.add_pk_column("DATABASE_NAME", table_priv_key.db_)) - || OB_FAIL(dml.add_pk_column("TABLE_NAME", table_priv_key.table_)) + || OB_FAIL(dml.add_pk_column("DATABASE_NAME", ObHexEscapeSqlStr(table_priv_key.db_))) + || OB_FAIL(dml.add_pk_column("TABLE_NAME", ObHexEscapeSqlStr(table_priv_key.table_))) || OB_FAIL(dml.add_gmt_modified())) { LOG_WARN("add column failed", K(ret)); } @@ -930,8 +930,8 @@ int ObPrivSqlService::gen_table_priv_dml( exec_tenant_id, table_priv_key.tenant_id_))) || OB_FAIL(dml.add_pk_column("user_id", ObSchemaUtils::get_extract_schema_id( exec_tenant_id, table_priv_key.user_id_))) - || OB_FAIL(dml.add_pk_column("database_name", table_priv_key.db_)) - || OB_FAIL(dml.add_pk_column("table_name", table_priv_key.table_)) + || OB_FAIL(dml.add_pk_column("database_name", ObHexEscapeSqlStr(table_priv_key.db_))) + || OB_FAIL(dml.add_pk_column("table_name", ObHexEscapeSqlStr(table_priv_key.table_))) || OB_FAIL(dml.add_column("PRIV_ALTER", priv_set & OB_PRIV_ALTER ? 1 : 0)) || OB_FAIL(dml.add_column("PRIV_CREATE", priv_set & OB_PRIV_CREATE ? 1 : 0)) || OB_FAIL(dml.add_column("PRIV_DELETE", priv_set & OB_PRIV_DELETE ? 1 : 0)) @@ -969,8 +969,8 @@ int ObPrivSqlService::gen_routine_priv_dml( if ((priv_set & OB_PRIV_GRANT) != 0) { all_priv |= 4; } if (OB_FAIL(dml.add_pk_column("tenant_id", 0)) || OB_FAIL(dml.add_pk_column("user_id", routine_priv_key.user_id_)) - || OB_FAIL(dml.add_pk_column("database_name", routine_priv_key.db_)) - || OB_FAIL(dml.add_pk_column("routine_name", routine_priv_key.routine_)) + || OB_FAIL(dml.add_pk_column("database_name", ObHexEscapeSqlStr(routine_priv_key.db_))) + || OB_FAIL(dml.add_pk_column("routine_name", ObHexEscapeSqlStr(routine_priv_key.routine_))) || OB_FAIL(dml.add_pk_column("routine_type", routine_priv_key.routine_type_)) || OB_FAIL(dml.add_column("all_priv", all_priv))) { LOG_WARN("add column failed", K(ret)); @@ -997,7 +997,7 @@ int ObPrivSqlService::gen_db_priv_dml( exec_tenant_id, db_priv_key.tenant_id_))) || OB_FAIL(dml.add_pk_column("user_id", ObSchemaUtils::get_extract_schema_id( exec_tenant_id, db_priv_key.user_id_))) - || OB_FAIL(dml.add_pk_column("database_name", db_priv_key.db_)) + || OB_FAIL(dml.add_pk_column("database_name", ObHexEscapeSqlStr(db_priv_key.db_))) || OB_FAIL(dml.add_column("PRIV_ALTER", priv_set & OB_PRIV_ALTER ? 1 : 0)) || OB_FAIL(dml.add_column("PRIV_CREATE", priv_set & OB_PRIV_CREATE ? 1 : 0)) || OB_FAIL(dml.add_column("PRIV_DELETE", priv_set & OB_PRIV_DELETE ? 1 : 0)) diff --git a/src/share/schema/ob_user_sql_service.cpp b/src/share/schema/ob_user_sql_service.cpp index b236818f6c..a86697fb21 100644 --- a/src/share/schema/ob_user_sql_service.cpp +++ b/src/share/schema/ob_user_sql_service.cpp @@ -1016,7 +1016,7 @@ int ObUserSqlService::gen_user_dml( || OB_FAIL(dml.add_pk_column("user_id", ObSchemaUtils::get_extract_schema_id( exec_tenant_id,user.get_user_id()))) || OB_FAIL(dml.add_column("user_name", ObHexEscapeSqlStr(user.get_user_name()))) - || OB_FAIL(dml.add_column("host", user.get_host_name())) + || OB_FAIL(dml.add_column("host", ObHexEscapeSqlStr(user.get_host_name()))) || OB_FAIL(dml.add_column("passwd", user.get_passwd())) || OB_FAIL(dml.add_column("info", user.get_info())) || OB_FAIL(dml.add_column("PRIV_ALTER", user.get_priv(OB_PRIV_ALTER) ? 1 : 0)) diff --git a/src/sql/engine/cmd/ob_variable_set_executor.cpp b/src/sql/engine/cmd/ob_variable_set_executor.cpp index b8a1d30744..ed7cff5bec 100644 --- a/src/sql/engine/cmd/ob_variable_set_executor.cpp +++ b/src/sql/engine/cmd/ob_variable_set_executor.cpp @@ -36,7 +36,7 @@ #include "observer/ob_server.h" #include "sql/rewrite/ob_transform_pre_process.h" #include "sql/engine/cmd/ob_set_names_executor.h" - +#include "sql/privilege_check/ob_privilege_check.h" using namespace oceanbase::common; using namespace oceanbase::share; using namespace oceanbase::share::schema; @@ -466,7 +466,14 @@ int ObVariableSetExecutor::execute_subquery_expr(ObExecContext &ctx, ObObj tmp_value; SMART_VAR(ObISQLClient::ReadResult, res) { common::sqlclient::ObMySQLResult *result = NULL; - if (OB_FAIL(conn->execute_read(tenant_id, subquery_expr.ptr(), res))) { + bool need_check = false; + if (OB_FAIL(session_info->check_feature_enable(ObCompatFeatureType::MYSQL_SET_VAR_PRIV_ENHANCE, need_check))) { + LOG_WARN("failed to check feature enable", K(ret)); + } else if (need_check) { + conn->set_check_priv(true); + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(conn->execute_read(tenant_id, subquery_expr.ptr(), res))) { LOG_WARN("failed to execute sql", K(ret), K(subquery_expr)); } else if (OB_ISNULL(result = res.get_result())) { ret = OB_ERR_UNEXPECTED; diff --git a/src/sql/engine/expr/ob_expr_user_can_access_obj.cpp b/src/sql/engine/expr/ob_expr_user_can_access_obj.cpp index 3b55548888..c76d8992eb 100644 --- a/src/sql/engine/expr/ob_expr_user_can_access_obj.cpp +++ b/src/sql/engine/expr/ob_expr_user_can_access_obj.cpp @@ -117,7 +117,8 @@ int ObExprUserCanAccessObj::build_real_obj_type_for_sym( uint64_t tenant_id, share::schema::ObSchemaGetterGuard *schema_guard, uint64_t &obj_type, - uint64_t &obj_id) + uint64_t &obj_id, + uint64_t &owner_id) { int ret = OB_SUCCESS; const share::schema::ObSimpleSynonymSchema *synonym_info = NULL; @@ -131,6 +132,7 @@ int ObExprUserCanAccessObj::build_real_obj_type_for_sym( } else { const share::schema::ObSimpleTableSchemaV2 *simple_table_schema = NULL; uint64_t db_id = synonym_info->get_object_database_id(); + owner_id = db_id; const ObString &obj_name = synonym_info->get_object_name_str(); OZ (schema_guard->get_simple_table_schema(tenant_id, db_id, @@ -246,7 +248,7 @@ int ObExprUserCanAccessObj::check_user_access_obj( if (OB_SUCC(ret)) { if (obj_type == static_cast(share::schema::ObObjectType::SYNONYM)) { OZ (build_real_obj_type_for_sym(session->get_effective_tenant_id(), - schema_guard, obj_type, obj_id), + schema_guard, obj_type, obj_id, owner_id), obj_type, obj_id); /* 忽略synonym对于的object不存在的错误 */ if (ret == OB_TABLE_NOT_EXIST) { diff --git a/src/sql/engine/expr/ob_expr_user_can_access_obj.h b/src/sql/engine/expr/ob_expr_user_can_access_obj.h index c1542bd26c..119b0690ab 100644 --- a/src/sql/engine/expr/ob_expr_user_can_access_obj.h +++ b/src/sql/engine/expr/ob_expr_user_can_access_obj.h @@ -52,7 +52,8 @@ private: uint64_t tenant_id, share::schema::ObSchemaGetterGuard *schema_guard, uint64_t &obj_type, - uint64_t &obj_id); + uint64_t &obj_id, + uint64_t &owner_id); static int check_user_access_obj( share::schema::ObSchemaGetterGuard *schema_guard, diff --git a/src/sql/parser/sql_parser_mysql_mode.y b/src/sql/parser/sql_parser_mysql_mode.y index 86b3b74a48..7644f5e6d6 100644 --- a/src/sql/parser/sql_parser_mysql_mode.y +++ b/src/sql/parser/sql_parser_mysql_mode.y @@ -14542,6 +14542,24 @@ user opt_host_name need_enc_node->value_ = 0; malloc_non_terminal_node($$, result->malloc_pool_, T_CREATE_USER_SPEC, 5, $1, NULL, need_enc_node, $2, NULL); } +| CURRENT_USER +{ + ParseNode *need_enc_node = NULL; + malloc_terminal_node(need_enc_node, result->malloc_pool_, T_BOOL); + need_enc_node->value_ = 0; + ParseNode *cur_user = NULL; + malloc_terminal_node(cur_user, result->malloc_pool_, T_FUN_SYS_CURRENT_USER); + malloc_non_terminal_node($$, result->malloc_pool_, T_CREATE_USER_SPEC, 5, cur_user, NULL, need_enc_node, NULL, NULL); +} +| CURRENT_USER '(' ')' +{ + ParseNode *need_enc_node = NULL; + malloc_terminal_node(need_enc_node, result->malloc_pool_, T_BOOL); + need_enc_node->value_ = 0; + ParseNode *cur_user = NULL; + malloc_terminal_node(cur_user, result->malloc_pool_, T_FUN_SYS_CURRENT_USER); + malloc_non_terminal_node($$, result->malloc_pool_, T_CREATE_USER_SPEC, 5, cur_user, NULL, need_enc_node, NULL, NULL); +} ; user_specification_with_password: @@ -14559,6 +14577,24 @@ user opt_host_name IDENTIFIED opt_auth_plugin BY password need_enc_node->value_ = 0; malloc_non_terminal_node($$, result->malloc_pool_, T_CREATE_USER_SPEC, 5, $1, $7, need_enc_node, $2, $4); } +| CURRENT_USER IDENTIFIED opt_auth_plugin BY password +{ + ParseNode *need_enc_node = NULL; + malloc_terminal_node(need_enc_node, result->malloc_pool_, T_BOOL); + need_enc_node->value_ = 0; + ParseNode *cur_user = NULL; + malloc_terminal_node(cur_user, result->malloc_pool_, T_FUN_SYS_CURRENT_USER); + malloc_non_terminal_node($$, result->malloc_pool_, T_CREATE_USER_SPEC, 5, cur_user, $5, need_enc_node, NULL, $3); +} +| CURRENT_USER '(' ')' IDENTIFIED opt_auth_plugin BY PASSWORD password +{ + ParseNode *need_enc_node = NULL; + malloc_terminal_node(need_enc_node, result->malloc_pool_, T_BOOL); + need_enc_node->value_ = 0; + ParseNode *cur_user = NULL; + malloc_terminal_node(cur_user, result->malloc_pool_, T_FUN_SYS_CURRENT_USER); + malloc_non_terminal_node($$, result->malloc_pool_, T_CREATE_USER_SPEC, 5, cur_user, $8, need_enc_node, NULL, $5); +} ; require_specification: @@ -14695,6 +14731,18 @@ user opt_host_name { malloc_non_terminal_node($$, result->malloc_pool_, T_USER_WITH_HOST_NAME, 2, $1, $2); } +| CURRENT_USER +{ + ParseNode *cur_user = NULL; + malloc_terminal_node(cur_user, result->malloc_pool_, T_FUN_SYS_CURRENT_USER); + malloc_non_terminal_node($$, result->malloc_pool_, T_USER_WITH_HOST_NAME, 2, cur_user, NULL); +} +| CURRENT_USER '(' ')' +{ + ParseNode *cur_user = NULL; + malloc_terminal_node(cur_user, result->malloc_pool_, T_FUN_SYS_CURRENT_USER); + malloc_non_terminal_node($$, result->malloc_pool_, T_USER_WITH_HOST_NAME, 2, cur_user, NULL); +} ; password: diff --git a/src/sql/privilege_check/ob_privilege_check.cpp b/src/sql/privilege_check/ob_privilege_check.cpp index 75675e25e7..f2b217f318 100644 --- a/src/sql/privilege_check/ob_privilege_check.cpp +++ b/src/sql/privilege_check/ob_privilege_check.cpp @@ -71,6 +71,7 @@ #include "sql/resolver/dcl/ob_alter_user_profile_stmt.h" #include "pl/ob_pl_stmt.h" #include "sql/resolver/expr/ob_raw_expr_util.h" +#include "sql/optimizer/ob_optimizer_util.h" namespace oceanbase { using namespace share; @@ -845,8 +846,54 @@ int add_seqs_priv_in_dml( CK (ctx.schema_guard_ != NULL); CK (ctx.session_info_ != NULL); CK (dml_stmt != NULL); - const common::ObIArray &nextval_sequence_ids = dml_stmt->get_nextval_sequence_ids(); - const common::ObIArray &currval_sequence_ids = dml_stmt->get_currval_sequence_ids(); + common::ObArray nextval_sequence_ids; + common::ObArray currval_sequence_ids; + ObArray exprs; + if (dml_stmt->is_update_stmt()) { + const ObUpdateStmt *stmt = static_cast(dml_stmt); + for (int64_t k = 0; k < dml_stmt->get_column_items().count() && OB_SUCC(ret); k++) { + for (int i = 0; OB_SUCC(ret) && i < stmt->get_update_table_info().count(); i++) { + CK (stmt->get_update_table_info().at(i) != NULL); + for (int j = 0; OB_SUCC(ret) && j < stmt->get_update_table_info().at(i)->assignments_.count(); j++) { + if (stmt->get_update_table_info().at(i)->assignments_.at(j).column_expr_ == dml_stmt->get_column_items().at(k).get_expr()) { + const ObRawExpr *default_expr = NULL; + if (NULL != (default_expr = dml_stmt->get_column_items().at(k).default_value_expr_) + && default_expr->has_flag(CNT_SEQ_EXPR)) { + OZ (exprs.push_back(default_expr)); + } + } + } + } + } + while(OB_SUCC(ret) && !exprs.empty()) { + const ObRawExpr *expr = NULL; + OZ (exprs.pop_back(expr)); + CK (expr != NULL); + if (OB_SUCC(ret)) { + if (expr->has_flag(IS_SEQ_EXPR)) { + const ObSequenceRawExpr *seq_raw_expr = static_cast(expr); + uint64_t sequence_id = seq_raw_expr->get_sequence_id(); + const ObString &action = seq_raw_expr->get_action(); + if (sequence_id == OB_INVALID_ID) { + } else if (action.case_compare("CURRVAL")) { + OZ (currval_sequence_ids.push_back(sequence_id)); + } else { + OZ (nextval_sequence_ids.push_back(sequence_id)); + } + } else { + for (int i = 0; OB_SUCC(ret) && i < expr->get_param_count(); i++) { + const ObRawExpr *child_expr = expr->get_param_expr(i); + if (child_expr->has_flag(CNT_SEQ_EXPR)) { + OZ (exprs.push_back(child_expr)); + } + } + } + } + } + } else { + OZ (append(nextval_sequence_ids, dml_stmt->get_nextval_sequence_ids())); + OZ (append(currval_sequence_ids, dml_stmt->get_currval_sequence_ids())); + } if (OB_SUCC(ret)) { OZ (add_seqs_priv_in_dml_inner(user_id, ctx, nextval_sequence_ids, OBJ_PRIV_ID_SELECT, need_privs, check_flag)); @@ -1943,6 +1990,7 @@ int get_revoke_stmt_need_privs( ObIArray &need_privs) { int ret = OB_SUCCESS; + bool check_revoke_all_user_create_user = false; if (OB_ISNULL(basic_stmt)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("Basic stmt should be not be NULL", K(ret)); @@ -1950,10 +1998,41 @@ int get_revoke_stmt_need_privs( ret = OB_INVALID_ARGUMENT; LOG_WARN("Stmt type should be T_REVOKE", K(ret), "stmt type", basic_stmt->get_stmt_type()); + } else if (OB_FAIL(ObPrivilegeCheck::get_priv_need_check(session_priv, + ObCompatFeatureType::MYSQL_USER_REVOKE_ALL_ENHANCE, check_revoke_all_user_create_user))) { + LOG_WARN("failed to get priv need check", K(ret)); } else { ObNeedPriv need_priv; const ObRevokeStmt *stmt = static_cast(basic_stmt); - if (OB_FAIL(ObPrivilegeCheck::can_do_grant_on_db_table(session_priv, stmt->get_priv_set(), + if (check_revoke_all_user_create_user && + stmt->get_grant_level() == OB_PRIV_USER_LEVEL && stmt->get_priv_set() == OB_PRIV_ALL) { + need_priv.db_ = stmt->get_database_name(); + need_priv.table_ = stmt->get_table_name(); + need_priv.priv_set_ = OB_PRIV_CREATE_USER; + need_priv.priv_level_ = stmt->get_grant_level(); + need_priv.obj_type_ = stmt->get_object_type(); + ADD_NEED_PRIV(need_priv); + + ObSchemaGetterGuard schema_guard; + bool need_add = false; + CK (GCTX.schema_service_ != NULL); + OZ(GCTX.schema_service_->get_tenant_schema_guard(session_priv.tenant_id_, schema_guard)); + for (int i = 0; OB_SUCC(ret) && i < stmt->get_users().count(); i++) { + const ObUserInfo *user_info = NULL; + OZ(schema_guard.get_user_info(session_priv.tenant_id_, stmt->get_users().at(i), user_info)); + CK (user_info != NULL); + need_add = (0 != (user_info->get_priv_set() & OB_PRIV_SUPER)); + } + if (OB_FAIL(ret)) { + } else if (need_add) { //mysql8.0 if exists dynamic privs, then need SYSTEM_USER dynamic privilge to revoke all, now use SUPER to do so. + need_priv.db_ = stmt->get_database_name(); + need_priv.table_ = stmt->get_table_name(); + need_priv.priv_set_ = OB_PRIV_SUPER; + need_priv.priv_level_ = stmt->get_grant_level(); + need_priv.obj_type_ = stmt->get_object_type(); + ADD_NEED_PRIV(need_priv); + } + } else if (OB_FAIL(ObPrivilegeCheck::can_do_grant_on_db_table(session_priv, stmt->get_priv_set(), stmt->get_database_name(), stmt->get_table_name()))) { LOG_WARN("Can not grant information_schema database", K(ret)); diff --git a/src/sql/resolver/dcl/ob_dcl_resolver.cpp b/src/sql/resolver/dcl/ob_dcl_resolver.cpp index 0618efaf3f..64983a25e9 100644 --- a/src/sql/resolver/dcl/ob_dcl_resolver.cpp +++ b/src/sql/resolver/dcl/ob_dcl_resolver.cpp @@ -448,7 +448,12 @@ int ObDCLResolver::resolve_user_host(const ParseNode *user_pass, ret = OB_INVALID_ARGUMENT; LOG_WARN("Child 0 of user_pass should not be NULL", K(ret)); } else { - user_name = ObString(user_pass->children_[0]->str_len_, user_pass->children_[0]->str_value_); + if (user_pass->children_[0]->type_ == T_FUN_SYS_CURRENT_USER) { + user_name = session_info_->get_user_name(); + host_name = session_info_->get_host_name(); + } else { + user_name = ObString(user_pass->children_[0]->str_len_, user_pass->children_[0]->str_value_); + } if (user_pass->children_[0]->type_ != T_IDENT && OB_FAIL(ObSQLUtils::convert_sql_text_to_schema_for_storing( @@ -459,7 +464,11 @@ int ObDCLResolver::resolve_user_host(const ParseNode *user_pass, ret = OB_ERR_NO_PRIVILEGE; LOG_WARN("__oceanbase_inner_restore_user is reserved", K(ret)); } else if (NULL == user_pass->children_[3]) { - host_name.assign_ptr(OB_DEFAULT_HOST_NAME, static_cast(STRLEN(OB_DEFAULT_HOST_NAME))); + if (user_pass->children_[0]->type_ == T_FUN_SYS_CURRENT_USER) { + //skip + } else { + host_name.assign_ptr(OB_DEFAULT_HOST_NAME, static_cast(STRLEN(OB_DEFAULT_HOST_NAME))); + } } else { host_name.assign_ptr(user_pass->children_[3]->str_value_, static_cast(user_pass->children_[3]->str_len_)); diff --git a/src/sql/resolver/dcl/ob_grant_resolver.cpp b/src/sql/resolver/dcl/ob_grant_resolver.cpp index 2fe64906fd..2ef5d5eeb3 100644 --- a/src/sql/resolver/dcl/ob_grant_resolver.cpp +++ b/src/sql/resolver/dcl/ob_grant_resolver.cpp @@ -105,8 +105,13 @@ int ObGrantResolver::resolve_grant_user( ret = OB_ERR_UNEXPECTED; LOG_WARN("Parse node error in grentee ", K(ret)); } else { - user_name.assign_ptr(const_cast(grant_user->children_[0]->str_value_), + if (grant_user->children_[0]->type_ == T_FUN_SYS_CURRENT_USER) { + user_name = session_info->get_user_name(); + host_name = session_info->get_host_name(); + } else { + user_name.assign_ptr(const_cast(grant_user->children_[0]->str_value_), static_cast(grant_user->children_[0]->str_len_)); + } if (NULL != grant_user->children_[3]) { // host name is not default host_name.assign_ptr(const_cast(grant_user->children_[3]->str_value_), @@ -1488,10 +1493,19 @@ int ObGrantResolver::resolve_mysql(const ParseNode &parse_tree) ret = OB_ERR_PARSE_SQL; LOG_WARN("The child 0 should not be NULL", K(ret)); } else { - user_name.assign_ptr(const_cast(user_node->children_[0]->str_value_), - static_cast(user_node->children_[0]->str_len_)); + + if (user_node->children_[0]->type_ == T_FUN_SYS_CURRENT_USER) { + user_name = session_info_->get_user_name(); + host_name = session_info_->get_host_name(); + } else { + user_name.assign_ptr(const_cast(user_node->children_[0]->str_value_), + static_cast(user_node->children_[0]->str_len_)); + } if (NULL == user_node->children_[3]) { - host_name.assign_ptr(OB_DEFAULT_HOST_NAME, static_cast(STRLEN(OB_DEFAULT_HOST_NAME))); + if (user_node->children_[0]->type_ == T_FUN_SYS_CURRENT_USER) { + } else { + host_name.assign_ptr(OB_DEFAULT_HOST_NAME, static_cast(STRLEN(OB_DEFAULT_HOST_NAME))); + } } else { host_name.assign_ptr(user_node->children_[3]->str_value_, static_cast(user_node->children_[3]->str_len_)); diff --git a/src/sql/resolver/dcl/ob_revoke_resolver.cpp b/src/sql/resolver/dcl/ob_revoke_resolver.cpp index fbe39633ac..62638d94dc 100644 --- a/src/sql/resolver/dcl/ob_revoke_resolver.cpp +++ b/src/sql/resolver/dcl/ob_revoke_resolver.cpp @@ -501,12 +501,21 @@ int ObRevokeResolver::resolve_mysql(const ParseNode &parse_tree) } else { uint64_t user_id = OB_INVALID_ID; //0: user name; 1: host name - ObString user_name(static_cast(user_hostname_node->children_[0]->str_len_), - user_hostname_node->children_[0]->str_value_); + ObString user_name; ObString host_name; + if (user_hostname_node->children_[0]->type_ == T_FUN_SYS_CURRENT_USER) { + user_name = params_.session_info_->get_user_name(); + } else { + user_name = ObString(static_cast(user_hostname_node->children_[0]->str_len_), + user_hostname_node->children_[0]->str_value_); + } if (NULL == user_hostname_node->children_[1]) { - host_name.assign_ptr(OB_DEFAULT_HOST_NAME, + if (user_hostname_node->children_[0]->type_ == T_FUN_SYS_CURRENT_USER) { + host_name = params_.session_info_->get_host_name(); + } else { + host_name.assign_ptr(OB_DEFAULT_HOST_NAME, static_cast(STRLEN(OB_DEFAULT_HOST_NAME))); + } } else { host_name.assign_ptr(user_hostname_node->children_[1]->str_value_, static_cast(user_hostname_node->children_[1]->str_len_));