From fc98a7bdb9f2d1a47f67305c78aecc385cc10f21 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Fri, 14 Oct 2022 09:16:51 +0200 Subject: [PATCH] Refactor ownercheck functions Instead of dozens of mostly-duplicate pg_foo_ownercheck() functions, write one common function object_ownercheck() that can handle almost all of them. We already have all the information we need, such as which system catalog corresponds to which catalog table, and which column is the owner column. I kept a few pg_foo_ownercheck() around as thin wrappers because they are widely used through the code. And there are also a couple that don't work via the generic function, so those stay as is. --- src/backend/catalog/aclchk.c | 517 ++---------------------- src/backend/catalog/objectaddress.c | 92 +---- src/backend/commands/collationcmds.c | 2 +- src/backend/commands/event_trigger.c | 4 +- src/backend/commands/foreigncmds.c | 6 +- src/backend/commands/proclang.c | 2 +- src/backend/commands/publicationcmds.c | 4 +- src/backend/commands/statscmds.c | 2 +- src/backend/commands/subscriptioncmds.c | 6 +- src/backend/commands/tablespace.c | 6 +- src/backend/commands/tsearchcmds.c | 4 +- src/include/utils/acl.h | 22 +- 12 files changed, 71 insertions(+), 596 deletions(-) diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index aa5a2ed9483e..d67d3b522cef 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -32,6 +32,7 @@ #include "catalog/pg_am.h" #include "catalog/pg_authid.h" #include "catalog/pg_cast.h" +#include "catalog/pg_class.h" #include "catalog/pg_collation.h" #include "catalog/pg_conversion.h" #include "catalog/pg_database.h" @@ -5111,25 +5112,30 @@ pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode) } /* - * Ownership check for a relation (specified by OID). + * Generic ownership check for an object */ bool -pg_class_ownercheck(Oid class_oid, Oid roleid) +object_ownercheck(Oid classid, Oid objectid, Oid roleid) { HeapTuple tuple; Oid ownerId; + bool isnull; /* Superusers bypass all permission checking. */ if (superuser_arg(roleid)) return true; - tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(class_oid)); + tuple = SearchSysCache1(get_object_catcache_oid(classid), ObjectIdGetDatum(objectid)); if (!HeapTupleIsValid(tuple)) ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_TABLE), - errmsg("relation with OID %u does not exist", class_oid))); + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("%s with OID %u does not exist", get_object_class_descr(classid), objectid))); - ownerId = ((Form_pg_class) GETSTRUCT(tuple))->relowner; + ownerId = DatumGetObjectId(SysCacheGetAttr(get_object_catcache_oid(classid), + tuple, + get_object_attnum_owner(classid), + &isnull)); + Assert(!isnull); ReleaseSysCache(tuple); @@ -5137,107 +5143,43 @@ pg_class_ownercheck(Oid class_oid, Oid roleid) } /* - * Ownership check for a type (specified by OID). + * Wrapper functions for commonly used cases */ + bool -pg_type_ownercheck(Oid type_oid, Oid roleid) +pg_class_ownercheck(Oid class_oid, Oid roleid) { - HeapTuple tuple; - Oid ownerId; - - /* Superusers bypass all permission checking. */ - if (superuser_arg(roleid)) - return true; - - tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_oid)); - if (!HeapTupleIsValid(tuple)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("type with OID %u does not exist", type_oid))); - - ownerId = ((Form_pg_type) GETSTRUCT(tuple))->typowner; - - ReleaseSysCache(tuple); + return object_ownercheck(RelationRelationId, class_oid, roleid); +} - return has_privs_of_role(roleid, ownerId); +bool +pg_type_ownercheck(Oid type_oid, Oid roleid) +{ + return object_ownercheck(TypeRelationId, type_oid, roleid); } -/* - * Ownership check for an operator (specified by OID). - */ bool pg_oper_ownercheck(Oid oper_oid, Oid roleid) { - HeapTuple tuple; - Oid ownerId; - - /* Superusers bypass all permission checking. */ - if (superuser_arg(roleid)) - return true; - - tuple = SearchSysCache1(OPEROID, ObjectIdGetDatum(oper_oid)); - if (!HeapTupleIsValid(tuple)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_FUNCTION), - errmsg("operator with OID %u does not exist", oper_oid))); - - ownerId = ((Form_pg_operator) GETSTRUCT(tuple))->oprowner; - - ReleaseSysCache(tuple); - - return has_privs_of_role(roleid, ownerId); + return object_ownercheck(OperatorRelationId, oper_oid, roleid); } -/* - * Ownership check for a function (specified by OID). - */ bool pg_proc_ownercheck(Oid proc_oid, Oid roleid) { - HeapTuple tuple; - Oid ownerId; - - /* Superusers bypass all permission checking. */ - if (superuser_arg(roleid)) - return true; - - tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(proc_oid)); - if (!HeapTupleIsValid(tuple)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_FUNCTION), - errmsg("function with OID %u does not exist", proc_oid))); - - ownerId = ((Form_pg_proc) GETSTRUCT(tuple))->proowner; - - ReleaseSysCache(tuple); - - return has_privs_of_role(roleid, ownerId); + return object_ownercheck(ProcedureRelationId, proc_oid, roleid); } -/* - * Ownership check for a procedural language (specified by OID) - */ bool -pg_language_ownercheck(Oid lan_oid, Oid roleid) +pg_namespace_ownercheck(Oid nsp_oid, Oid roleid) { - HeapTuple tuple; - Oid ownerId; - - /* Superusers bypass all permission checking. */ - if (superuser_arg(roleid)) - return true; - - tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(lan_oid)); - if (!HeapTupleIsValid(tuple)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_FUNCTION), - errmsg("language with OID %u does not exist", lan_oid))); - - ownerId = ((Form_pg_language) GETSTRUCT(tuple))->lanowner; - - ReleaseSysCache(tuple); + return object_ownercheck(NamespaceRelationId, nsp_oid, roleid); +} - return has_privs_of_role(roleid, ownerId); +bool +pg_database_ownercheck(Oid db_oid, Oid roleid) +{ + return object_ownercheck(DatabaseRelationId, db_oid, roleid); } /* @@ -5286,326 +5228,6 @@ pg_largeobject_ownercheck(Oid lobj_oid, Oid roleid) return has_privs_of_role(roleid, ownerId); } -/* - * Ownership check for a namespace (specified by OID). - */ -bool -pg_namespace_ownercheck(Oid nsp_oid, Oid roleid) -{ - HeapTuple tuple; - Oid ownerId; - - /* Superusers bypass all permission checking. */ - if (superuser_arg(roleid)) - return true; - - tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nsp_oid)); - if (!HeapTupleIsValid(tuple)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_SCHEMA), - errmsg("schema with OID %u does not exist", nsp_oid))); - - ownerId = ((Form_pg_namespace) GETSTRUCT(tuple))->nspowner; - - ReleaseSysCache(tuple); - - return has_privs_of_role(roleid, ownerId); -} - -/* - * Ownership check for a tablespace (specified by OID). - */ -bool -pg_tablespace_ownercheck(Oid spc_oid, Oid roleid) -{ - HeapTuple spctuple; - Oid spcowner; - - /* Superusers bypass all permission checking. */ - if (superuser_arg(roleid)) - return true; - - /* Search syscache for pg_tablespace */ - spctuple = SearchSysCache1(TABLESPACEOID, ObjectIdGetDatum(spc_oid)); - if (!HeapTupleIsValid(spctuple)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("tablespace with OID %u does not exist", spc_oid))); - - spcowner = ((Form_pg_tablespace) GETSTRUCT(spctuple))->spcowner; - - ReleaseSysCache(spctuple); - - return has_privs_of_role(roleid, spcowner); -} - -/* - * Ownership check for an operator class (specified by OID). - */ -bool -pg_opclass_ownercheck(Oid opc_oid, Oid roleid) -{ - HeapTuple tuple; - Oid ownerId; - - /* Superusers bypass all permission checking. */ - if (superuser_arg(roleid)) - return true; - - tuple = SearchSysCache1(CLAOID, ObjectIdGetDatum(opc_oid)); - if (!HeapTupleIsValid(tuple)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("operator class with OID %u does not exist", - opc_oid))); - - ownerId = ((Form_pg_opclass) GETSTRUCT(tuple))->opcowner; - - ReleaseSysCache(tuple); - - return has_privs_of_role(roleid, ownerId); -} - -/* - * Ownership check for an operator family (specified by OID). - */ -bool -pg_opfamily_ownercheck(Oid opf_oid, Oid roleid) -{ - HeapTuple tuple; - Oid ownerId; - - /* Superusers bypass all permission checking. */ - if (superuser_arg(roleid)) - return true; - - tuple = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opf_oid)); - if (!HeapTupleIsValid(tuple)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("operator family with OID %u does not exist", - opf_oid))); - - ownerId = ((Form_pg_opfamily) GETSTRUCT(tuple))->opfowner; - - ReleaseSysCache(tuple); - - return has_privs_of_role(roleid, ownerId); -} - -/* - * Ownership check for a text search dictionary (specified by OID). - */ -bool -pg_ts_dict_ownercheck(Oid dict_oid, Oid roleid) -{ - HeapTuple tuple; - Oid ownerId; - - /* Superusers bypass all permission checking. */ - if (superuser_arg(roleid)) - return true; - - tuple = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(dict_oid)); - if (!HeapTupleIsValid(tuple)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("text search dictionary with OID %u does not exist", - dict_oid))); - - ownerId = ((Form_pg_ts_dict) GETSTRUCT(tuple))->dictowner; - - ReleaseSysCache(tuple); - - return has_privs_of_role(roleid, ownerId); -} - -/* - * Ownership check for a text search configuration (specified by OID). - */ -bool -pg_ts_config_ownercheck(Oid cfg_oid, Oid roleid) -{ - HeapTuple tuple; - Oid ownerId; - - /* Superusers bypass all permission checking. */ - if (superuser_arg(roleid)) - return true; - - tuple = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(cfg_oid)); - if (!HeapTupleIsValid(tuple)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("text search configuration with OID %u does not exist", - cfg_oid))); - - ownerId = ((Form_pg_ts_config) GETSTRUCT(tuple))->cfgowner; - - ReleaseSysCache(tuple); - - return has_privs_of_role(roleid, ownerId); -} - -/* - * Ownership check for a foreign-data wrapper (specified by OID). - */ -bool -pg_foreign_data_wrapper_ownercheck(Oid srv_oid, Oid roleid) -{ - HeapTuple tuple; - Oid ownerId; - - /* Superusers bypass all permission checking. */ - if (superuser_arg(roleid)) - return true; - - tuple = SearchSysCache1(FOREIGNDATAWRAPPEROID, ObjectIdGetDatum(srv_oid)); - if (!HeapTupleIsValid(tuple)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("foreign-data wrapper with OID %u does not exist", - srv_oid))); - - ownerId = ((Form_pg_foreign_data_wrapper) GETSTRUCT(tuple))->fdwowner; - - ReleaseSysCache(tuple); - - return has_privs_of_role(roleid, ownerId); -} - -/* - * Ownership check for a foreign server (specified by OID). - */ -bool -pg_foreign_server_ownercheck(Oid srv_oid, Oid roleid) -{ - HeapTuple tuple; - Oid ownerId; - - /* Superusers bypass all permission checking. */ - if (superuser_arg(roleid)) - return true; - - tuple = SearchSysCache1(FOREIGNSERVEROID, ObjectIdGetDatum(srv_oid)); - if (!HeapTupleIsValid(tuple)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("foreign server with OID %u does not exist", - srv_oid))); - - ownerId = ((Form_pg_foreign_server) GETSTRUCT(tuple))->srvowner; - - ReleaseSysCache(tuple); - - return has_privs_of_role(roleid, ownerId); -} - -/* - * Ownership check for an event trigger (specified by OID). - */ -bool -pg_event_trigger_ownercheck(Oid et_oid, Oid roleid) -{ - HeapTuple tuple; - Oid ownerId; - - /* Superusers bypass all permission checking. */ - if (superuser_arg(roleid)) - return true; - - tuple = SearchSysCache1(EVENTTRIGGEROID, ObjectIdGetDatum(et_oid)); - if (!HeapTupleIsValid(tuple)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("event trigger with OID %u does not exist", - et_oid))); - - ownerId = ((Form_pg_event_trigger) GETSTRUCT(tuple))->evtowner; - - ReleaseSysCache(tuple); - - return has_privs_of_role(roleid, ownerId); -} - -/* - * Ownership check for a database (specified by OID). - */ -bool -pg_database_ownercheck(Oid db_oid, Oid roleid) -{ - HeapTuple tuple; - Oid dba; - - /* Superusers bypass all permission checking. */ - if (superuser_arg(roleid)) - return true; - - tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(db_oid)); - if (!HeapTupleIsValid(tuple)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_DATABASE), - errmsg("database with OID %u does not exist", db_oid))); - - dba = ((Form_pg_database) GETSTRUCT(tuple))->datdba; - - ReleaseSysCache(tuple); - - return has_privs_of_role(roleid, dba); -} - -/* - * Ownership check for a collation (specified by OID). - */ -bool -pg_collation_ownercheck(Oid coll_oid, Oid roleid) -{ - HeapTuple tuple; - Oid ownerId; - - /* Superusers bypass all permission checking. */ - if (superuser_arg(roleid)) - return true; - - tuple = SearchSysCache1(COLLOID, ObjectIdGetDatum(coll_oid)); - if (!HeapTupleIsValid(tuple)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("collation with OID %u does not exist", coll_oid))); - - ownerId = ((Form_pg_collation) GETSTRUCT(tuple))->collowner; - - ReleaseSysCache(tuple); - - return has_privs_of_role(roleid, ownerId); -} - -/* - * Ownership check for a conversion (specified by OID). - */ -bool -pg_conversion_ownercheck(Oid conv_oid, Oid roleid) -{ - HeapTuple tuple; - Oid ownerId; - - /* Superusers bypass all permission checking. */ - if (superuser_arg(roleid)) - return true; - - tuple = SearchSysCache1(CONVOID, ObjectIdGetDatum(conv_oid)); - if (!HeapTupleIsValid(tuple)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("conversion with OID %u does not exist", conv_oid))); - - ownerId = ((Form_pg_conversion) GETSTRUCT(tuple))->conowner; - - ReleaseSysCache(tuple); - - return has_privs_of_role(roleid, ownerId); -} - /* * Ownership check for an extension (specified by OID). */ @@ -5648,85 +5270,6 @@ pg_extension_ownercheck(Oid ext_oid, Oid roleid) return has_privs_of_role(roleid, ownerId); } -/* - * Ownership check for a publication (specified by OID). - */ -bool -pg_publication_ownercheck(Oid pub_oid, Oid roleid) -{ - HeapTuple tuple; - Oid ownerId; - - /* Superusers bypass all permission checking. */ - if (superuser_arg(roleid)) - return true; - - tuple = SearchSysCache1(PUBLICATIONOID, ObjectIdGetDatum(pub_oid)); - if (!HeapTupleIsValid(tuple)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("publication with OID %u does not exist", pub_oid))); - - ownerId = ((Form_pg_publication) GETSTRUCT(tuple))->pubowner; - - ReleaseSysCache(tuple); - - return has_privs_of_role(roleid, ownerId); -} - -/* - * Ownership check for a subscription (specified by OID). - */ -bool -pg_subscription_ownercheck(Oid sub_oid, Oid roleid) -{ - HeapTuple tuple; - Oid ownerId; - - /* Superusers bypass all permission checking. */ - if (superuser_arg(roleid)) - return true; - - tuple = SearchSysCache1(SUBSCRIPTIONOID, ObjectIdGetDatum(sub_oid)); - if (!HeapTupleIsValid(tuple)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("subscription with OID %u does not exist", sub_oid))); - - ownerId = ((Form_pg_subscription) GETSTRUCT(tuple))->subowner; - - ReleaseSysCache(tuple); - - return has_privs_of_role(roleid, ownerId); -} - -/* - * Ownership check for a statistics object (specified by OID). - */ -bool -pg_statistics_object_ownercheck(Oid stat_oid, Oid roleid) -{ - HeapTuple tuple; - Oid ownerId; - - /* Superusers bypass all permission checking. */ - if (superuser_arg(roleid)) - return true; - - tuple = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(stat_oid)); - if (!HeapTupleIsValid(tuple)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("statistics object with OID %u does not exist", - stat_oid))); - - ownerId = ((Form_pg_statistic_ext) GETSTRUCT(tuple))->stxowner; - - ReleaseSysCache(tuple); - - return has_privs_of_role(roleid, ownerId); -} - /* * Check whether specified role has CREATEROLE privilege (or is a superuser) * diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c index 284ca55469e0..80c9110fd1a8 100644 --- a/src/backend/catalog/objectaddress.c +++ b/src/backend/catalog/objectaddress.c @@ -2443,11 +2443,6 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address, aclcheck_error(ACLCHECK_NOT_OWNER, objtype, RelationGetRelationName(relation)); break; - case OBJECT_DATABASE: - if (!pg_database_ownercheck(address.objectId, roleid)) - aclcheck_error(ACLCHECK_NOT_OWNER, objtype, - strVal(object)); - break; case OBJECT_TYPE: case OBJECT_DOMAIN: case OBJECT_ATTRIBUTE: @@ -2481,27 +2476,32 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address, case OBJECT_FUNCTION: case OBJECT_PROCEDURE: case OBJECT_ROUTINE: - if (!pg_proc_ownercheck(address.objectId, roleid)) - aclcheck_error(ACLCHECK_NOT_OWNER, objtype, - NameListToString((castNode(ObjectWithArgs, object))->objname)); - break; case OBJECT_OPERATOR: - if (!pg_oper_ownercheck(address.objectId, roleid)) + if (!object_ownercheck(address.classId, address.objectId, roleid)) aclcheck_error(ACLCHECK_NOT_OWNER, objtype, NameListToString((castNode(ObjectWithArgs, object))->objname)); break; + case OBJECT_DATABASE: + case OBJECT_EVENT_TRIGGER: + case OBJECT_FDW: + case OBJECT_FOREIGN_SERVER: + case OBJECT_LANGUAGE: + case OBJECT_PUBLICATION: case OBJECT_SCHEMA: - if (!pg_namespace_ownercheck(address.objectId, roleid)) + case OBJECT_SUBSCRIPTION: + case OBJECT_TABLESPACE: + if (!object_ownercheck(address.classId, address.objectId, roleid)) aclcheck_error(ACLCHECK_NOT_OWNER, objtype, strVal(object)); break; case OBJECT_COLLATION: - if (!pg_collation_ownercheck(address.objectId, roleid)) - aclcheck_error(ACLCHECK_NOT_OWNER, objtype, - NameListToString(castNode(List, object))); - break; case OBJECT_CONVERSION: - if (!pg_conversion_ownercheck(address.objectId, roleid)) + case OBJECT_OPCLASS: + case OBJECT_OPFAMILY: + case OBJECT_STATISTIC_EXT: + case OBJECT_TSDICTIONARY: + case OBJECT_TSCONFIGURATION: + if (!object_ownercheck(address.classId, address.objectId, roleid)) aclcheck_error(ACLCHECK_NOT_OWNER, objtype, NameListToString(castNode(List, object))); break; @@ -2510,36 +2510,6 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address, aclcheck_error(ACLCHECK_NOT_OWNER, objtype, strVal(object)); break; - case OBJECT_FDW: - if (!pg_foreign_data_wrapper_ownercheck(address.objectId, roleid)) - aclcheck_error(ACLCHECK_NOT_OWNER, objtype, - strVal(object)); - break; - case OBJECT_FOREIGN_SERVER: - if (!pg_foreign_server_ownercheck(address.objectId, roleid)) - aclcheck_error(ACLCHECK_NOT_OWNER, objtype, - strVal(object)); - break; - case OBJECT_EVENT_TRIGGER: - if (!pg_event_trigger_ownercheck(address.objectId, roleid)) - aclcheck_error(ACLCHECK_NOT_OWNER, objtype, - strVal(object)); - break; - case OBJECT_LANGUAGE: - if (!pg_language_ownercheck(address.objectId, roleid)) - aclcheck_error(ACLCHECK_NOT_OWNER, objtype, - strVal(object)); - break; - case OBJECT_OPCLASS: - if (!pg_opclass_ownercheck(address.objectId, roleid)) - aclcheck_error(ACLCHECK_NOT_OWNER, objtype, - NameListToString(castNode(List, object))); - break; - case OBJECT_OPFAMILY: - if (!pg_opfamily_ownercheck(address.objectId, roleid)) - aclcheck_error(ACLCHECK_NOT_OWNER, objtype, - NameListToString(castNode(List, object))); - break; case OBJECT_LARGEOBJECT: if (!lo_compat_privileges && !pg_largeobject_ownercheck(address.objectId, roleid)) @@ -2565,16 +2535,6 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address, format_type_be(targettypeid)))); } break; - case OBJECT_PUBLICATION: - if (!pg_publication_ownercheck(address.objectId, roleid)) - aclcheck_error(ACLCHECK_NOT_OWNER, objtype, - strVal(object)); - break; - case OBJECT_SUBSCRIPTION: - if (!pg_subscription_ownercheck(address.objectId, roleid)) - aclcheck_error(ACLCHECK_NOT_OWNER, objtype, - strVal(object)); - break; case OBJECT_TRANSFORM: { TypeName *typename = linitial_node(TypeName, castNode(List, object)); @@ -2584,21 +2544,6 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address, aclcheck_error_type(ACLCHECK_NOT_OWNER, typeid); } break; - case OBJECT_TABLESPACE: - if (!pg_tablespace_ownercheck(address.objectId, roleid)) - aclcheck_error(ACLCHECK_NOT_OWNER, objtype, - strVal(object)); - break; - case OBJECT_TSDICTIONARY: - if (!pg_ts_dict_ownercheck(address.objectId, roleid)) - aclcheck_error(ACLCHECK_NOT_OWNER, objtype, - NameListToString(castNode(List, object))); - break; - case OBJECT_TSCONFIGURATION: - if (!pg_ts_config_ownercheck(address.objectId, roleid)) - aclcheck_error(ACLCHECK_NOT_OWNER, objtype, - NameListToString(castNode(List, object))); - break; case OBJECT_ROLE: /* @@ -2630,11 +2575,6 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("must be superuser"))); break; - case OBJECT_STATISTIC_EXT: - if (!pg_statistics_object_ownercheck(address.objectId, roleid)) - aclcheck_error(ACLCHECK_NOT_OWNER, objtype, - NameListToString(castNode(List, object))); - break; default: elog(ERROR, "unrecognized object type: %d", (int) objtype); diff --git a/src/backend/commands/collationcmds.c b/src/backend/commands/collationcmds.c index fcfc02d2aede..25c1e485c458 100644 --- a/src/backend/commands/collationcmds.c +++ b/src/backend/commands/collationcmds.c @@ -365,7 +365,7 @@ AlterCollation(AlterCollationStmt *stmt) rel = table_open(CollationRelationId, RowExclusiveLock); collOid = get_collation_oid(stmt->collname, false); - if (!pg_collation_ownercheck(collOid, GetUserId())) + if (!object_ownercheck(CollationRelationId, collOid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_COLLATION, NameListToString(stmt->collname)); diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c index 441f29d684ff..7ed9c80fc63c 100644 --- a/src/backend/commands/event_trigger.c +++ b/src/backend/commands/event_trigger.c @@ -379,7 +379,7 @@ AlterEventTrigger(AlterEventTrigStmt *stmt) evtForm = (Form_pg_event_trigger) GETSTRUCT(tup); trigoid = evtForm->oid; - if (!pg_event_trigger_ownercheck(trigoid, GetUserId())) + if (!object_ownercheck(EventTriggerRelationId, trigoid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_EVENT_TRIGGER, stmt->trigname); @@ -471,7 +471,7 @@ AlterEventTriggerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) if (form->evtowner == newOwnerId) return; - if (!pg_event_trigger_ownercheck(form->oid, GetUserId())) + if (!object_ownercheck(EventTriggerRelationId, form->oid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_EVENT_TRIGGER, NameStr(form->evtname)); diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c index 91f4dd30de18..e6e6d128d11a 100644 --- a/src/backend/commands/foreigncmds.c +++ b/src/backend/commands/foreigncmds.c @@ -358,7 +358,7 @@ AlterForeignServerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) srvId = form->oid; /* Must be owner */ - if (!pg_foreign_server_ownercheck(srvId, GetUserId())) + if (!object_ownercheck(ForeignServerRelationId, srvId, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_FOREIGN_SERVER, NameStr(form->srvname)); @@ -998,7 +998,7 @@ AlterForeignServer(AlterForeignServerStmt *stmt) /* * Only owner or a superuser can ALTER a SERVER. */ - if (!pg_foreign_server_ownercheck(srvId, GetUserId())) + if (!object_ownercheck(ForeignServerRelationId, srvId, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_FOREIGN_SERVER, stmt->servername); @@ -1076,7 +1076,7 @@ user_mapping_ddl_aclcheck(Oid umuserid, Oid serverid, const char *servername) { Oid curuserid = GetUserId(); - if (!pg_foreign_server_ownercheck(serverid, curuserid)) + if (!object_ownercheck(ForeignServerRelationId, serverid, curuserid)) { if (umuserid == curuserid) { diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c index 4a093f45d85a..96a524be36aa 100644 --- a/src/backend/commands/proclang.c +++ b/src/backend/commands/proclang.c @@ -134,7 +134,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) /* This is currently pointless, since we already checked superuser */ #ifdef NOT_USED - if (!pg_language_ownercheck(oldform->oid, languageOwner)) + if (!object_ownercheck(LanguageRelationId, oldform->oid, languageOwner)) aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_LANGUAGE, languageName); #endif diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c index a8b75eb1be8b..3d0f712a4faf 100644 --- a/src/backend/commands/publicationcmds.c +++ b/src/backend/commands/publicationcmds.c @@ -1394,7 +1394,7 @@ AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt) pubform = (Form_pg_publication) GETSTRUCT(tup); /* must be owner */ - if (!pg_publication_ownercheck(pubform->oid, GetUserId())) + if (!object_ownercheck(PublicationRelationId, pubform->oid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_PUBLICATION, stmt->pubname); @@ -1905,7 +1905,7 @@ AlterPublicationOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) AclResult aclresult; /* Must be owner */ - if (!pg_publication_ownercheck(form->oid, GetUserId())) + if (!object_ownercheck(PublicationRelationId, form->oid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_PUBLICATION, NameStr(form->pubname)); diff --git a/src/backend/commands/statscmds.c b/src/backend/commands/statscmds.c index 55216d28916b..0d87318e0233 100644 --- a/src/backend/commands/statscmds.c +++ b/src/backend/commands/statscmds.c @@ -665,7 +665,7 @@ AlterStatistics(AlterStatsStmt *stmt) elog(ERROR, "cache lookup failed for extended statistics object %u", stxoid); /* Must be owner of the existing statistics object */ - if (!pg_statistics_object_ownercheck(stxoid, GetUserId())) + if (!object_ownercheck(StatisticExtRelationId, stxoid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_STATISTIC_EXT, NameListToString(stmt->defnames)); diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c index 8fb89a9392c8..a69b9a38bdcf 100644 --- a/src/backend/commands/subscriptioncmds.c +++ b/src/backend/commands/subscriptioncmds.c @@ -1032,7 +1032,7 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, subid = form->oid; /* must be owner */ - if (!pg_subscription_ownercheck(subid, GetUserId())) + if (!object_ownercheck(SubscriptionRelationId, subid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_SUBSCRIPTION, stmt->subname); @@ -1413,7 +1413,7 @@ DropSubscription(DropSubscriptionStmt *stmt, bool isTopLevel) subid = form->oid; /* must be owner */ - if (!pg_subscription_ownercheck(subid, GetUserId())) + if (!object_ownercheck(SubscriptionRelationId, subid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_SUBSCRIPTION, stmt->subname); @@ -1704,7 +1704,7 @@ AlterSubscriptionOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) if (form->subowner == newOwnerId) return; - if (!pg_subscription_ownercheck(form->oid, GetUserId())) + if (!object_ownercheck(SubscriptionRelationId, form->oid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_SUBSCRIPTION, NameStr(form->subname)); diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c index b69ff37dbbdc..12c7993b15aa 100644 --- a/src/backend/commands/tablespace.c +++ b/src/backend/commands/tablespace.c @@ -446,7 +446,7 @@ DropTableSpace(DropTableSpaceStmt *stmt) tablespaceoid = spcform->oid; /* Must be tablespace owner */ - if (!pg_tablespace_ownercheck(tablespaceoid, GetUserId())) + if (!object_ownercheck(TableSpaceRelationId, tablespaceoid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TABLESPACE, tablespacename); @@ -966,7 +966,7 @@ RenameTableSpace(const char *oldname, const char *newname) table_endscan(scan); /* Must be owner */ - if (!pg_tablespace_ownercheck(tspId, GetUserId())) + if (!object_ownercheck(TableSpaceRelationId, tspId, GetUserId())) aclcheck_error(ACLCHECK_NO_PRIV, OBJECT_TABLESPACE, oldname); /* Validate new name */ @@ -1051,7 +1051,7 @@ AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt) tablespaceoid = ((Form_pg_tablespace) GETSTRUCT(tup))->oid; /* Must be owner of the existing object */ - if (!pg_tablespace_ownercheck(tablespaceoid, GetUserId())) + if (!object_ownercheck(TableSpaceRelationId, tablespaceoid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TABLESPACE, stmt->tablespacename); diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c index 4cc4e3c00f8e..365bfd30fdfe 100644 --- a/src/backend/commands/tsearchcmds.c +++ b/src/backend/commands/tsearchcmds.c @@ -510,7 +510,7 @@ AlterTSDictionary(AlterTSDictionaryStmt *stmt) dictId); /* must be owner */ - if (!pg_ts_dict_ownercheck(dictId, GetUserId())) + if (!object_ownercheck(TSDictionaryRelationId, dictId, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TSDICTIONARY, NameListToString(stmt->dictname)); @@ -1124,7 +1124,7 @@ AlterTSConfiguration(AlterTSConfigurationStmt *stmt) cfgId = ((Form_pg_ts_config) GETSTRUCT(tup))->oid; /* must be owner */ - if (!pg_ts_config_ownercheck(cfgId, GetUserId())) + if (!object_ownercheck(TSConfigRelationId, cfgId, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TSCONFIGURATION, NameListToString(stmt->cfgname)); diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h index 9a4df3a5dacc..bf461f24fde7 100644 --- a/src/include/utils/acl.h +++ b/src/include/utils/acl.h @@ -306,28 +306,20 @@ extern void removeExtObjInitPriv(Oid objoid, Oid classoid); /* ownercheck routines just return true (owner) or false (not) */ +extern bool object_ownercheck(Oid classid, Oid objectid, Oid roleid); + +/* wrapper functions for commonly used cases */ extern bool pg_class_ownercheck(Oid class_oid, Oid roleid); extern bool pg_type_ownercheck(Oid type_oid, Oid roleid); extern bool pg_oper_ownercheck(Oid oper_oid, Oid roleid); extern bool pg_proc_ownercheck(Oid proc_oid, Oid roleid); -extern bool pg_language_ownercheck(Oid lan_oid, Oid roleid); -extern bool pg_largeobject_ownercheck(Oid lobj_oid, Oid roleid); extern bool pg_namespace_ownercheck(Oid nsp_oid, Oid roleid); -extern bool pg_tablespace_ownercheck(Oid spc_oid, Oid roleid); -extern bool pg_opclass_ownercheck(Oid opc_oid, Oid roleid); -extern bool pg_opfamily_ownercheck(Oid opf_oid, Oid roleid); extern bool pg_database_ownercheck(Oid db_oid, Oid roleid); -extern bool pg_collation_ownercheck(Oid coll_oid, Oid roleid); -extern bool pg_conversion_ownercheck(Oid conv_oid, Oid roleid); -extern bool pg_ts_dict_ownercheck(Oid dict_oid, Oid roleid); -extern bool pg_ts_config_ownercheck(Oid cfg_oid, Oid roleid); -extern bool pg_foreign_data_wrapper_ownercheck(Oid srv_oid, Oid roleid); -extern bool pg_foreign_server_ownercheck(Oid srv_oid, Oid roleid); -extern bool pg_event_trigger_ownercheck(Oid et_oid, Oid roleid); + +/* special cases */ +extern bool pg_largeobject_ownercheck(Oid lobj_oid, Oid roleid); extern bool pg_extension_ownercheck(Oid ext_oid, Oid roleid); -extern bool pg_publication_ownercheck(Oid pub_oid, Oid roleid); -extern bool pg_subscription_ownercheck(Oid sub_oid, Oid roleid); -extern bool pg_statistics_object_ownercheck(Oid stat_oid, Oid roleid); + extern bool has_createrole_privilege(Oid roleid); extern bool has_bypassrls_privilege(Oid roleid); -- 2.37.3