diff options
Diffstat (limited to 'src/backend/catalog/objectaddress.c')
-rw-r--r-- | src/backend/catalog/objectaddress.c | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c index aeb07710e84..b8b89ab7c19 100644 --- a/src/backend/catalog/objectaddress.c +++ b/src/backend/catalog/objectaddress.c @@ -52,6 +52,8 @@ #include "commands/proclang.h" #include "commands/tablespace.h" #include "commands/trigger.h" +#include "libpq/be-fsstubs.h" +#include "miscadmin.h" #include "nodes/makefuncs.h" #include "parser/parse_func.h" #include "parser/parse_oper.h" @@ -78,6 +80,7 @@ static ObjectAddress get_object_address_opcf(ObjectType objtype, List *objname, List *objargs); static bool object_exists(ObjectAddress address); + /* * Translate an object name and arguments (as passed by the parser) to an * ObjectAddress. @@ -688,3 +691,151 @@ object_exists(ObjectAddress address) heap_close(rel, AccessShareLock); return found; } + + +/* + * Check ownership of an object previously identified by get_object_address. + */ +void +check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address, + List *objname, List *objargs, Relation relation) +{ + switch (objtype) + { + case OBJECT_INDEX: + case OBJECT_SEQUENCE: + case OBJECT_TABLE: + case OBJECT_VIEW: + case OBJECT_FOREIGN_TABLE: + case OBJECT_COLUMN: + case OBJECT_RULE: + case OBJECT_TRIGGER: + case OBJECT_CONSTRAINT: + if (!pg_class_ownercheck(RelationGetRelid(relation), roleid)) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, + RelationGetRelationName(relation)); + break; + case OBJECT_DATABASE: + if (!pg_database_ownercheck(address.objectId, roleid)) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE, + NameListToString(objname)); + break; + case OBJECT_TYPE: + case OBJECT_DOMAIN: + case OBJECT_ATTRIBUTE: + if (!pg_type_ownercheck(address.objectId, roleid)) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, + format_type_be(address.objectId)); + break; + case OBJECT_AGGREGATE: + case OBJECT_FUNCTION: + if (!pg_proc_ownercheck(address.objectId, roleid)) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC, + NameListToString(objname)); + break; + case OBJECT_OPERATOR: + if (!pg_oper_ownercheck(address.objectId, roleid)) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPER, + NameListToString(objname)); + break; + case OBJECT_SCHEMA: + if (!pg_namespace_ownercheck(address.objectId, roleid)) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_NAMESPACE, + NameListToString(objname)); + break; + case OBJECT_COLLATION: + if (!pg_collation_ownercheck(address.objectId, roleid)) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_COLLATION, + NameListToString(objname)); + break; + case OBJECT_CONVERSION: + if (!pg_conversion_ownercheck(address.objectId, roleid)) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION, + NameListToString(objname)); + break; + case OBJECT_EXTENSION: + if (!pg_extension_ownercheck(address.objectId, roleid)) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EXTENSION, + NameListToString(objname)); + break; + case OBJECT_FOREIGN_SERVER: + if (!pg_foreign_server_ownercheck(address.objectId, roleid)) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FOREIGN_SERVER, + NameListToString(objname)); + break; + case OBJECT_LANGUAGE: + if (!pg_language_ownercheck(address.objectId, roleid)) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_LANGUAGE, + NameListToString(objname)); + break; + case OBJECT_OPCLASS: + if (!pg_opclass_ownercheck(address.objectId, roleid)) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPCLASS, + NameListToString(objname)); + break; + case OBJECT_OPFAMILY: + if (!pg_opfamily_ownercheck(address.objectId, roleid)) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPFAMILY, + NameListToString(objname)); + break; + case OBJECT_LARGEOBJECT: + if (!lo_compat_privileges && + !pg_largeobject_ownercheck(address.objectId, roleid)) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("must be owner of large object %u", + address.objectId))); + break; + case OBJECT_CAST: + { + /* We can only check permissions on the source/target types */ + TypeName *sourcetype = (TypeName *) linitial(objname); + TypeName *targettype = (TypeName *) linitial(objargs); + Oid sourcetypeid = typenameTypeId(NULL, sourcetype); + Oid targettypeid = typenameTypeId(NULL, targettype); + + if (!pg_type_ownercheck(sourcetypeid, roleid) + && !pg_type_ownercheck(targettypeid, roleid)) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("must be owner of type %s or type %s", + format_type_be(sourcetypeid), + format_type_be(targettypeid)))); + } + break; + case OBJECT_TABLESPACE: + if (!pg_tablespace_ownercheck(address.objectId, roleid)) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TABLESPACE, + NameListToString(objname)); + break; + case OBJECT_ROLE: + if (!has_privs_of_role(roleid, address.objectId)) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("must be member of role \"%s\"", + NameListToString(objname)))); + break; + case OBJECT_TSDICTIONARY: + if (!pg_ts_dict_ownercheck(address.objectId, roleid)) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSDICTIONARY, + NameListToString(objname)); + break; + case OBJECT_TSCONFIGURATION: + if (!pg_ts_config_ownercheck(address.objectId, roleid)) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSCONFIGURATION, + NameListToString(objname)); + break; + case OBJECT_FDW: + case OBJECT_TSPARSER: + case OBJECT_TSTEMPLATE: + /* We treat these object types as being owned by superusers */ + if (!superuser_arg(roleid)) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("must be superuser"))); + break; + default: + elog(ERROR, "unrecognized object type: %d", + (int) objtype); + } +} |