Commit 15b1918e authored by Peter Eisentraut's avatar Peter Eisentraut

Improve reporting of permission errors for array types

Because permissions are assigned to element types, not array types,
complaining about permission denied on an array type would be
misleading to users.  So adjust the reporting to refer to the element
type instead.

In order not to duplicate the required logic in two dozen places,
refactor the permission denied reporting for types a bit.

pointed out by Yeb Havinga during the review of the type privilege
feature
parent d933092e
...@@ -573,8 +573,7 @@ BuildDescForRelation(List *schema) ...@@ -573,8 +573,7 @@ BuildDescForRelation(List *schema)
aclresult = pg_type_aclcheck(atttypid, GetUserId(), ACL_USAGE); aclresult = pg_type_aclcheck(atttypid, GetUserId(), ACL_USAGE);
if (aclresult != ACLCHECK_OK) if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_TYPE, aclcheck_error_type(aclresult, atttypid);
format_type_be(atttypid));
attcollation = GetColumnDefCollation(NULL, entry, atttypid); attcollation = GetColumnDefCollation(NULL, entry, atttypid);
attdim = list_length(entry->typeName->arrayBounds); attdim = list_length(entry->typeName->arrayBounds);
......
...@@ -3389,6 +3389,19 @@ aclcheck_error_col(AclResult aclerr, AclObjectKind objectkind, ...@@ -3389,6 +3389,19 @@ aclcheck_error_col(AclResult aclerr, AclObjectKind objectkind,
} }
/*
* Special common handling for types: use element type instead of array type,
* and format nicely
*/
void
aclcheck_error_type(AclResult aclerr, Oid typeOid)
{
Oid element_type = get_element_type(typeOid);
aclcheck_error(aclerr, ACL_KIND_TYPE, format_type_be(element_type ? element_type : typeOid));
}
/* Check if given user has rolcatupdate privilege according to pg_authid */ /* Check if given user has rolcatupdate privilege according to pg_authid */
static bool static bool
has_rolcatupdate(Oid roleid) has_rolcatupdate(Oid roleid)
......
...@@ -937,8 +937,7 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address, ...@@ -937,8 +937,7 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
case OBJECT_DOMAIN: case OBJECT_DOMAIN:
case OBJECT_ATTRIBUTE: case OBJECT_ATTRIBUTE:
if (!pg_type_ownercheck(address.objectId, roleid)) if (!pg_type_ownercheck(address.objectId, roleid))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, aclcheck_error_type(ACLCHECK_NOT_OWNER, address.objectId);
format_type_be(address.objectId));
break; break;
case OBJECT_AGGREGATE: case OBJECT_AGGREGATE:
case OBJECT_FUNCTION: case OBJECT_FUNCTION:
......
...@@ -208,19 +208,16 @@ AggregateCreate(const char *aggName, ...@@ -208,19 +208,16 @@ AggregateCreate(const char *aggName,
{ {
aclresult = pg_type_aclcheck(aggArgTypes[i], GetUserId(), ACL_USAGE); aclresult = pg_type_aclcheck(aggArgTypes[i], GetUserId(), ACL_USAGE);
if (aclresult != ACLCHECK_OK) if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_TYPE, aclcheck_error_type(aclresult, aggArgTypes[i]);
format_type_be(aggArgTypes[i]));
} }
aclresult = pg_type_aclcheck(aggTransType, GetUserId(), ACL_USAGE); aclresult = pg_type_aclcheck(aggTransType, GetUserId(), ACL_USAGE);
if (aclresult != ACLCHECK_OK) if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_TYPE, aclcheck_error_type(aclresult, aggTransType);
format_type_be(aggTransType));
aclresult = pg_type_aclcheck(finaltype, GetUserId(), ACL_USAGE); aclresult = pg_type_aclcheck(finaltype, GetUserId(), ACL_USAGE);
if (aclresult != ACLCHECK_OK) if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_TYPE, aclcheck_error_type(aclresult, finaltype);
format_type_be(finaltype));
/* /*
......
...@@ -154,8 +154,7 @@ compute_return_type(TypeName *returnType, Oid languageOid, ...@@ -154,8 +154,7 @@ compute_return_type(TypeName *returnType, Oid languageOid,
aclresult = pg_type_aclcheck(rettype, GetUserId(), ACL_USAGE); aclresult = pg_type_aclcheck(rettype, GetUserId(), ACL_USAGE);
if (aclresult != ACLCHECK_OK) if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_TYPE, aclcheck_error_type(aclresult, rettype);
format_type_be(rettype));
*prorettype_p = rettype; *prorettype_p = rettype;
*returnsSet_p = returnType->setof; *returnsSet_p = returnType->setof;
...@@ -247,8 +246,7 @@ examine_parameter_list(List *parameters, Oid languageOid, ...@@ -247,8 +246,7 @@ examine_parameter_list(List *parameters, Oid languageOid,
aclresult = pg_type_aclcheck(toid, GetUserId(), ACL_USAGE); aclresult = pg_type_aclcheck(toid, GetUserId(), ACL_USAGE);
if (aclresult != ACLCHECK_OK) if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_TYPE, aclcheck_error_type(aclresult, toid);
format_type_be(toid));
if (t->setof) if (t->setof)
ereport(ERROR, ereport(ERROR,
...@@ -1510,13 +1508,11 @@ CreateCast(CreateCastStmt *stmt) ...@@ -1510,13 +1508,11 @@ CreateCast(CreateCastStmt *stmt)
aclresult = pg_type_aclcheck(sourcetypeid, GetUserId(), ACL_USAGE); aclresult = pg_type_aclcheck(sourcetypeid, GetUserId(), ACL_USAGE);
if (aclresult != ACLCHECK_OK) if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_TYPE, aclcheck_error_type(aclresult, sourcetypeid);
format_type_be(sourcetypeid));
aclresult = pg_type_aclcheck(targettypeid, GetUserId(), ACL_USAGE); aclresult = pg_type_aclcheck(targettypeid, GetUserId(), ACL_USAGE);
if (aclresult != ACLCHECK_OK) if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_TYPE, aclcheck_error_type(aclresult, targettypeid);
format_type_be(targettypeid));
/* Domains are allowed for historical reasons, but we warn */ /* Domains are allowed for historical reasons, but we warn */
if (sourcetyptype == TYPTYPE_DOMAIN) if (sourcetyptype == TYPTYPE_DOMAIN)
......
...@@ -414,8 +414,7 @@ DefineOpClass(CreateOpClassStmt *stmt) ...@@ -414,8 +414,7 @@ DefineOpClass(CreateOpClassStmt *stmt)
/* XXX this is unnecessary given the superuser check above */ /* XXX this is unnecessary given the superuser check above */
/* Check we have ownership of the datatype */ /* Check we have ownership of the datatype */
if (!pg_type_ownercheck(typeoid, GetUserId())) if (!pg_type_ownercheck(typeoid, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, aclcheck_error_type(ACLCHECK_NOT_OWNER, typeoid);
format_type_be(typeoid));
#endif #endif
/* /*
...@@ -565,8 +564,7 @@ DefineOpClass(CreateOpClassStmt *stmt) ...@@ -565,8 +564,7 @@ DefineOpClass(CreateOpClassStmt *stmt)
/* XXX this is unnecessary given the superuser check above */ /* XXX this is unnecessary given the superuser check above */
/* Check we have ownership of the datatype */ /* Check we have ownership of the datatype */
if (!pg_type_ownercheck(storageoid, GetUserId())) if (!pg_type_ownercheck(storageoid, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, aclcheck_error_type(ACLCHECK_NOT_OWNER, storageoid);
format_type_be(storageoid));
#endif #endif
break; break;
default: default:
......
...@@ -181,16 +181,14 @@ DefineOperator(List *names, List *parameters) ...@@ -181,16 +181,14 @@ DefineOperator(List *names, List *parameters)
{ {
aclresult = pg_type_aclcheck(typeId1, GetUserId(), ACL_USAGE); aclresult = pg_type_aclcheck(typeId1, GetUserId(), ACL_USAGE);
if (aclresult != ACLCHECK_OK) if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_TYPE, aclcheck_error_type(aclresult, typeId1);
format_type_be(typeId1));
} }
if (typeName2) if (typeName2)
{ {
aclresult = pg_type_aclcheck(typeId2, GetUserId(), ACL_USAGE); aclresult = pg_type_aclcheck(typeId2, GetUserId(), ACL_USAGE);
if (aclresult != ACLCHECK_OK) if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_TYPE, aclcheck_error_type(aclresult, typeId2);
format_type_be(typeId2));
} }
/* /*
...@@ -227,8 +225,7 @@ DefineOperator(List *names, List *parameters) ...@@ -227,8 +225,7 @@ DefineOperator(List *names, List *parameters)
rettype = get_func_rettype(functionOid); rettype = get_func_rettype(functionOid);
aclresult = pg_type_aclcheck(rettype, GetUserId(), ACL_USAGE); aclresult = pg_type_aclcheck(rettype, GetUserId(), ACL_USAGE);
if (aclresult != ACLCHECK_OK) if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_TYPE, aclcheck_error_type(aclresult, rettype);
format_type_be(rettype));
/* /*
* Look up restriction estimator if specified * Look up restriction estimator if specified
......
...@@ -526,8 +526,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId) ...@@ -526,8 +526,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId)
aclresult = pg_type_aclcheck(ofTypeId, GetUserId(), ACL_USAGE); aclresult = pg_type_aclcheck(ofTypeId, GetUserId(), ACL_USAGE);
if (aclresult != ACLCHECK_OK) if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_TYPE, aclcheck_error_type(aclresult, ofTypeId);
format_type_be(ofTypeId));
} }
else else
ofTypeId = InvalidOid; ofTypeId = InvalidOid;
...@@ -4500,8 +4499,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, ...@@ -4500,8 +4499,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
aclresult = pg_type_aclcheck(typeOid, GetUserId(), ACL_USAGE); aclresult = pg_type_aclcheck(typeOid, GetUserId(), ACL_USAGE);
if (aclresult != ACLCHECK_OK) if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_TYPE, aclcheck_error_type(aclresult, typeOid);
format_type_be(typeOid));
collOid = GetColumnDefCollation(NULL, colDef, typeOid); collOid = GetColumnDefCollation(NULL, colDef, typeOid);
...@@ -7248,8 +7246,7 @@ ATPrepAlterColumnType(List **wqueue, ...@@ -7248,8 +7246,7 @@ ATPrepAlterColumnType(List **wqueue,
aclresult = pg_type_aclcheck(targettype, GetUserId(), ACL_USAGE); aclresult = pg_type_aclcheck(targettype, GetUserId(), ACL_USAGE);
if (aclresult != ACLCHECK_OK) if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_TYPE, aclcheck_error_type(aclresult, targettype);
format_type_be(targettype));
/* And the collation */ /* And the collation */
targetcollid = GetColumnDefCollation(NULL, def, targettype); targetcollid = GetColumnDefCollation(NULL, def, targettype);
......
...@@ -758,8 +758,7 @@ DefineDomain(CreateDomainStmt *stmt) ...@@ -758,8 +758,7 @@ DefineDomain(CreateDomainStmt *stmt)
aclresult = pg_type_aclcheck(basetypeoid, GetUserId(), ACL_USAGE); aclresult = pg_type_aclcheck(basetypeoid, GetUserId(), ACL_USAGE);
if (aclresult != ACLCHECK_OK) if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_TYPE, aclcheck_error_type(aclresult, basetypeoid);
format_type_be(basetypeoid));
/* /*
* Identify the collation if any * Identify the collation if any
...@@ -1208,8 +1207,7 @@ checkEnumOwner(HeapTuple tup) ...@@ -1208,8 +1207,7 @@ checkEnumOwner(HeapTuple tup)
/* Permission check: must own type */ /* Permission check: must own type */
if (!pg_type_ownercheck(HeapTupleGetOid(tup), GetUserId())) if (!pg_type_ownercheck(HeapTupleGetOid(tup), GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, aclcheck_error_type(ACLCHECK_NOT_OWNER, HeapTupleGetOid(tup));
format_type_be(HeapTupleGetOid(tup)));
} }
...@@ -2809,8 +2807,7 @@ checkDomainOwner(HeapTuple tup) ...@@ -2809,8 +2807,7 @@ checkDomainOwner(HeapTuple tup)
/* Permission check: must own type */ /* Permission check: must own type */
if (!pg_type_ownercheck(HeapTupleGetOid(tup), GetUserId())) if (!pg_type_ownercheck(HeapTupleGetOid(tup), GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, aclcheck_error_type(ACLCHECK_NOT_OWNER, HeapTupleGetOid(tup));
format_type_be(HeapTupleGetOid(tup)));
} }
/* /*
...@@ -3116,8 +3113,7 @@ RenameType(RenameStmt *stmt) ...@@ -3116,8 +3113,7 @@ RenameType(RenameStmt *stmt)
/* check permissions on type */ /* check permissions on type */
if (!pg_type_ownercheck(typeOid, GetUserId())) if (!pg_type_ownercheck(typeOid, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, aclcheck_error_type(ACLCHECK_NOT_OWNER, typeOid);
format_type_be(typeOid));
/* ALTER DOMAIN used on a non-domain? */ /* ALTER DOMAIN used on a non-domain? */
if (stmt->renameType == OBJECT_DOMAIN && typTup->typtype != TYPTYPE_DOMAIN) if (stmt->renameType == OBJECT_DOMAIN && typTup->typtype != TYPTYPE_DOMAIN)
...@@ -3238,8 +3234,7 @@ AlterTypeOwner(List *names, Oid newOwnerId, ObjectType objecttype) ...@@ -3238,8 +3234,7 @@ AlterTypeOwner(List *names, Oid newOwnerId, ObjectType objecttype)
{ {
/* Otherwise, must be owner of the existing object */ /* Otherwise, must be owner of the existing object */
if (!pg_type_ownercheck(HeapTupleGetOid(tup), GetUserId())) if (!pg_type_ownercheck(HeapTupleGetOid(tup), GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, aclcheck_error_type(ACLCHECK_NOT_OWNER, HeapTupleGetOid(tup));
format_type_be(HeapTupleGetOid(tup)));
/* Must be able to become new owner */ /* Must be able to become new owner */
check_is_member_of_role(GetUserId(), newOwnerId); check_is_member_of_role(GetUserId(), newOwnerId);
...@@ -3367,8 +3362,7 @@ AlterTypeNamespace_oid(Oid typeOid, Oid nspOid) ...@@ -3367,8 +3362,7 @@ AlterTypeNamespace_oid(Oid typeOid, Oid nspOid)
/* check permissions on type */ /* check permissions on type */
if (!pg_type_ownercheck(typeOid, GetUserId())) if (!pg_type_ownercheck(typeOid, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, aclcheck_error_type(ACLCHECK_NOT_OWNER, typeOid);
format_type_be(typeOid));
/* don't allow direct alteration of array types */ /* don't allow direct alteration of array types */
elemOid = get_element_type(typeOid); elemOid = get_element_type(typeOid);
......
...@@ -302,6 +302,8 @@ extern void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, ...@@ -302,6 +302,8 @@ extern void aclcheck_error(AclResult aclerr, AclObjectKind objectkind,
extern void aclcheck_error_col(AclResult aclerr, AclObjectKind objectkind, extern void aclcheck_error_col(AclResult aclerr, AclObjectKind objectkind,
const char *objectname, const char *colname); const char *objectname, const char *colname);
extern void aclcheck_error_type(AclResult aclerr, Oid typeOid);
/* ownercheck routines just return true (owner) or false (not) */ /* ownercheck routines just return true (owner) or false (not) */
extern bool pg_class_ownercheck(Oid class_oid, Oid roleid); extern bool pg_class_ownercheck(Oid class_oid, Oid roleid);
extern bool pg_type_ownercheck(Oid type_oid, Oid roleid); extern bool pg_type_ownercheck(Oid type_oid, Oid roleid);
......
...@@ -547,7 +547,7 @@ ERROR: permission denied for type testdomain1 ...@@ -547,7 +547,7 @@ ERROR: permission denied for type testdomain1
CREATE TABLE test6a OF testtype1; CREATE TABLE test6a OF testtype1;
ERROR: permission denied for type testtype1 ERROR: permission denied for type testtype1
CREATE TABLE test10a (a int[], b testtype1[]); CREATE TABLE test10a (a int[], b testtype1[]);
ERROR: permission denied for type testtype1[] ERROR: permission denied for type testtype1
CREATE TABLE test9a (a int, b int); CREATE TABLE test9a (a int, b int);
ALTER TABLE test9a ADD COLUMN c testdomain1; ALTER TABLE test9a ADD COLUMN c testdomain1;
ERROR: permission denied for type testdomain1 ERROR: permission denied for type testdomain1
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment