diff --git a/src/dsql/DdlNodes.epp b/src/dsql/DdlNodes.epp index 57f7d09945..6035d5e329 100644 --- a/src/dsql/DdlNodes.epp +++ b/src/dsql/DdlNodes.epp @@ -10959,6 +10959,79 @@ void GrantRevokeNode::modifyPrivileges(thread_db* tdbb, jrd_tra* transaction, SS } +static bool checkObjectExist(thread_db* tdbb, jrd_tra* transaction, const MetaName& name, int type) +{ + bool rc = false; + + switch (type) + { + case obj_procedure: + { + AutoCacheRequest request(tdbb, drq_proc_exist, DYN_REQUESTS); + FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction) + X IN RDB$PROCEDURES + WITH X.RDB$PROCEDURE_NAME EQ name.c_str() AND X.RDB$PACKAGE_NAME MISSING + { + rc = true; + } + END_FOR + break; + } + case obj_udf: + { + AutoCacheRequest request(tdbb, drq_udf_exist, DYN_REQUESTS); + FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction) + X IN RDB$FUNCTIONS + WITH X.RDB$FUNCTION_NAME EQ name.c_str() AND X.RDB$PACKAGE_NAME MISSING + { + rc = true; + } + END_FOR + break; + } + case obj_package_header: + { + AutoCacheRequest request(tdbb, drq_package_exist, DYN_REQUESTS); + FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction) + X IN RDB$PACKAGES + WITH X.RDB$PACKAGE_NAME EQ name.c_str() + { + rc = true; + } + END_FOR + break; + } + case obj_trigger: + { + AutoCacheRequest request(tdbb, drq_trigger_exist, DYN_REQUESTS); + FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction) + X IN RDB$TRIGGERS + WITH X.RDB$TRIGGER_NAME EQ name.c_str() + { + rc = true; + } + END_FOR + break; + } + case obj_relation: + case obj_view: + { + AutoCacheRequest request(tdbb, drq_rel_exist, DYN_REQUESTS); + FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction) + X IN RDB$RELATIONS + WITH X.RDB$RELATION_NAME EQ name.c_str() + { + rc = (type != obj_view) || (X.RDB$RELATION_TYPE == rel_view); + } + END_FOR + break; + } + } + + return rc; +} + + // Execute SQL grant/revoke operation. void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const GranteeClause* object, const GranteeClause* userNod, const char* privs, @@ -11010,12 +11083,36 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G } } else - { userType = obj_user; - } break; case obj_user: + // We may grant privilege to non existing user + break; + + case obj_udf: + if (!checkObjectExist(tdbb, transaction, user, userType)) + status_exception::raise(Arg::PrivateDyn(301) << user.c_str()); + break; + + case obj_procedure: + if (!checkObjectExist(tdbb, transaction, user, userType)) + status_exception::raise(Arg::PrivateDyn(302) << user.c_str()); + break; + + case obj_package_header: + if (!checkObjectExist(tdbb, transaction, user, userType)) + status_exception::raise(Arg::PrivateDyn(303) << user.c_str()); + break; + + case obj_trigger: + if (!checkObjectExist(tdbb, transaction, user, userType)) + status_exception::raise(Arg::PrivateDyn(304) << user.c_str()); + break; + + case obj_view: + if (!checkObjectExist(tdbb, transaction, user, userType)) + status_exception::raise(Arg::PrivateDyn(305) << user.c_str()); break; case obj_sql_role: diff --git a/src/jrd/drq.h b/src/jrd/drq.h index 76c47f3684..3c29d43715 100644 --- a/src/jrd/drq.h +++ b/src/jrd/drq.h @@ -235,6 +235,11 @@ enum drq_type_t drq_l_trigger_relname, // loopup relation name for trigger drq_l_grant_option, // loopup grant option for privilege drq_l_grant_object, // check grantor can grant object + drq_proc_exist, // check if procedure exists + drq_udf_exist, // check if udf exists + drq_package_exist, // check if package exists + drq_trigger_exist, // check if trigger exists + drq_rel_exist, // check if relation or view exists drq_MAX }; diff --git a/src/msgs/messages2.sql b/src/msgs/messages2.sql index 4cb3bf1743..6e2c0d777d 100644 --- a/src/msgs/messages2.sql +++ b/src/msgs/messages2.sql @@ -1974,6 +1974,11 @@ COMMIT WORK; ('dyn_incompat_alter_database', 'AlterDatabaseNode::execute', 'DdlNodes.epp', NULL, 8, 298, NULL, 'Incompatible ALTER DATABASE clauses: ''@1'' and ''@2''', NULL, NULL); (NULL, 'checkGrantorCanGrantObject', 'DdlNodes.epp', NULL, 8, 299, NULL, 'no @1 privilege with grant option on DDL @2', NULL, NULL); (NULL, 'checkGrantorCanGrantObject', 'DdlNodes.epp', NULL, 8, 300, NULL, 'no @1 privilege with grant option on object @2', NULL, NULL); +(NULL, 'GrantRevokeNode::grantRevoke', 'DdlNodes.epp', NULL, 8, 301, NULL, 'Function @1 does not exist', NULL, NULL); +(NULL, 'GrantRevokeNode::grantRevoke', 'DdlNodes.epp', NULL, 8, 302, NULL, 'Procedure @1 does not exist', NULL, NULL); +(NULL, 'GrantRevokeNode::grantRevoke', 'DdlNodes.epp', NULL, 8, 303, NULL, 'Package @1 does not exist', NULL, NULL); +(NULL, 'GrantRevokeNode::grantRevoke', 'DdlNodes.epp', NULL, 8, 304, NULL, 'Trigger @1 does not exist', NULL, NULL); +(NULL, 'GrantRevokeNode::grantRevoke', 'DdlNodes.epp', NULL, 8, 305, NULL, 'View @1 does not exist', NULL, NULL); COMMIT WORK; -- TEST (NULL, 'main', 'test.c', NULL, 11, 0, NULL, 'This is a modified text message', NULL, NULL);