diff options
| author | Tom Lane <tgl@sss.pgh.pa.us> | 2002-04-27 03:45:03 +0000 |
|---|---|---|
| committer | Tom Lane <tgl@sss.pgh.pa.us> | 2002-04-27 03:45:03 +0000 |
| commit | 31c775adeb2251a9c66328cbc9016877e5e4f085 (patch) | |
| tree | 065014ccecaae449f8a1c977319e823d54364c4b /src/backend/commands | |
| parent | aafe72efb2d9a01db77bacf94b9b103042b5eb60 (diff) | |
| download | postgresql-31c775adeb2251a9c66328cbc9016877e5e4f085.tar.gz | |
Restructure aclcheck error reporting to make permission-failure
messages more uniform and internationalizable: the global array
aclcheck_error_strings[] is gone in favor of a subroutine
aclcheck_error(). Partial implementation of namespace-related
permission checks --- not all done yet.
Diffstat (limited to 'src/backend/commands')
| -rw-r--r-- | src/backend/commands/aggregatecmds.c | 30 | ||||
| -rw-r--r-- | src/backend/commands/comment.c | 34 | ||||
| -rw-r--r-- | src/backend/commands/copy.c | 10 | ||||
| -rw-r--r-- | src/backend/commands/functioncmds.c | 40 | ||||
| -rw-r--r-- | src/backend/commands/indexcmds.c | 21 | ||||
| -rw-r--r-- | src/backend/commands/lockcmds.c | 7 | ||||
| -rw-r--r-- | src/backend/commands/operatorcmds.c | 18 | ||||
| -rw-r--r-- | src/backend/commands/schemacmds.c | 15 | ||||
| -rw-r--r-- | src/backend/commands/tablecmds.c | 51 | ||||
| -rw-r--r-- | src/backend/commands/trigger.c | 14 | ||||
| -rw-r--r-- | src/backend/commands/typecmds.c | 32 |
11 files changed, 171 insertions, 101 deletions
diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c index 7ee0c8f078..c3c1ed16df 100644 --- a/src/backend/commands/aggregatecmds.c +++ b/src/backend/commands/aggregatecmds.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/aggregatecmds.c,v 1.1 2002/04/15 05:22:03 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/aggregatecmds.c,v 1.2 2002/04/27 03:45:00 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -26,6 +26,7 @@ #include "catalog/catname.h" #include "catalog/namespace.h" #include "catalog/pg_aggregate.h" +#include "catalog/pg_proc.h" #include "commands/comment.h" #include "commands/defrem.h" #include "miscadmin.h" @@ -45,6 +46,7 @@ DefineAggregate(List *names, List *parameters) { char *aggName; Oid aggNamespace; + AclResult aclresult; List *transfuncName = NIL; List *finalfuncName = NIL; TypeName *baseType = NULL; @@ -57,6 +59,11 @@ DefineAggregate(List *names, List *parameters) /* Convert list of names to a name and namespace */ aggNamespace = QualifiedNameGetCreationNamespace(names, &aggName); + /* Check we have creation rights in target namespace */ + aclresult = pg_namespace_aclcheck(aggNamespace, GetUserId(), ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, get_namespace_name(aggNamespace)); + foreach(pl, parameters) { DefElem *defel = (DefElem *) lfirst(pl); @@ -157,20 +164,6 @@ RemoveAggregate(List *aggName, TypeName *aggType) procOid = find_aggregate_func("RemoveAggregate", aggName, basetypeID); - /* Permission check */ - - if (!pg_proc_ownercheck(procOid, GetUserId())) - { - if (basetypeID == InvalidOid) - elog(ERROR, "RemoveAggregate: aggregate %s for all types: permission denied", - NameListToString(aggName)); - else - elog(ERROR, "RemoveAggregate: aggregate %s for type %s: permission denied", - NameListToString(aggName), format_type_be(basetypeID)); - } - - /* Remove the pg_proc tuple */ - relation = heap_openr(ProcedureRelationName, RowExclusiveLock); tup = SearchSysCache(PROCOID, @@ -180,9 +173,16 @@ RemoveAggregate(List *aggName, TypeName *aggType) elog(ERROR, "RemoveAggregate: couldn't find pg_proc tuple for %s", NameListToString(aggName)); + /* Permission check: must own agg or its namespace */ + if (!pg_proc_ownercheck(procOid, GetUserId()) && + !pg_namespace_ownercheck(((Form_pg_proc) GETSTRUCT(tup))->pronamespace, + GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(aggName)); + /* Delete any comments associated with this function */ DeleteComments(procOid, RelationGetRelid(relation)); + /* Remove the pg_proc tuple */ simple_heap_delete(relation, &tup->t_self); ReleaseSysCache(tup); diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c index 3968ef14ef..0eb59b912f 100644 --- a/src/backend/commands/comment.c +++ b/src/backend/commands/comment.c @@ -7,7 +7,7 @@ * Copyright (c) 1999-2001, PostgreSQL Global Development Group * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.44 2002/04/24 02:50:30 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.45 2002/04/27 03:45:00 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -324,8 +324,7 @@ CommentRelation(int objtype, List *relname, char *comment) /* Check object security */ if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId())) - elog(ERROR, "you are not permitted to comment on class '%s'", - RelationGetRelationName(relation)); + aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(relation)); /* Next, verify that the relation type matches the intent */ @@ -395,8 +394,7 @@ CommentAttribute(List *qualname, char *comment) /* Check object security */ if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId())) - elog(ERROR, "you are not permitted to comment on class '%s'", - RelationGetRelationName(relation)); + aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(relation)); /* Now, fetch the attribute number from the system cache */ @@ -498,7 +496,7 @@ CommentRule(List *qualname, char *comment) Oid reloid; Oid ruleoid; Oid classoid; - int32 aclcheck; + AclResult aclcheck; /* Separate relname and trig name */ nnames = length(qualname); @@ -573,8 +571,7 @@ CommentRule(List *qualname, char *comment) aclcheck = pg_class_aclcheck(reloid, GetUserId(), ACL_RULE); if (aclcheck != ACLCHECK_OK) - elog(ERROR, "you are not permitted to comment on rule '%s'", - rulename); + aclcheck_error(aclcheck, rulename); /* pg_rewrite doesn't have a hard-coded OID, so must look it up */ @@ -613,8 +610,7 @@ CommentType(List *typename, char *comment) /* Check object security */ if (!pg_type_ownercheck(oid, GetUserId())) - elog(ERROR, "you are not permitted to comment on type %s", - TypeNameToString(tname)); + aclcheck_error(ACLCHECK_NOT_OWNER, TypeNameToString(tname)); /* Call CreateComments() to create/drop the comments */ @@ -649,14 +645,7 @@ CommentAggregate(List *aggregate, List *arguments, char *comment) /* Next, validate the user's attempt to comment */ if (!pg_proc_ownercheck(oid, GetUserId())) - { - if (baseoid == InvalidOid) - elog(ERROR, "you are not permitted to comment on aggregate %s for all types", - NameListToString(aggregate)); - else - elog(ERROR, "you are not permitted to comment on aggregate %s for type %s", - NameListToString(aggregate), format_type_be(baseoid)); - } + aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(aggregate)); /* Call CreateComments() to create/drop the comments */ @@ -685,8 +674,7 @@ CommentProc(List *function, List *arguments, char *comment) /* Now, validate the user's ability to comment on this function */ if (!pg_proc_ownercheck(oid, GetUserId())) - elog(ERROR, "you are not permitted to comment on function %s", - NameListToString(function)); + aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(function)); /* Call CreateComments() to create/drop the comments */ @@ -723,8 +711,7 @@ CommentOperator(List *opername, List *arguments, char *comment) /* Valid user's ability to comment on this operator */ if (!pg_oper_ownercheck(oid, GetUserId())) - elog(ERROR, "you are not permitted to comment on operator '%s'", - NameListToString(opername)); + aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(opername)); /* Get the procedure associated with the operator */ @@ -775,8 +762,7 @@ CommentTrigger(List *qualname, char *comment) /* Check object security */ if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId())) - elog(ERROR, "you are not permitted to comment on trigger '%s' for relation '%s'", - trigname, RelationGetRelationName(relation)); + aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(relation)); /* * Fetch the trigger tuple from pg_trigger. There can be only one diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 45e108027f..1ab3ae14fc 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.152 2002/03/29 19:06:05 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.153 2002/04/27 03:45:00 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -266,8 +266,8 @@ DoCopy(const RangeVar *relation, bool binary, bool oids, bool from, bool pipe, { FILE *fp; Relation rel; - const AclMode required_access = (from ? ACL_INSERT : ACL_SELECT); - int32 aclresult; + AclMode required_access = (from ? ACL_INSERT : ACL_SELECT); + AclResult aclresult; /* * Open and lock the relation, using the appropriate lock type. @@ -278,9 +278,7 @@ DoCopy(const RangeVar *relation, bool binary, bool oids, bool from, bool pipe, aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(), required_access); if (aclresult != ACLCHECK_OK) - elog(ERROR, "%s: %s", - RelationGetRelationName(rel), - aclcheck_error_strings[aclresult]); + aclcheck_error(aclresult, RelationGetRelationName(rel)); if (!pipe && !superuser()) elog(ERROR, "You must have Postgres superuser privilege to do a COPY " "directly to or from a file. Anyone can COPY to stdout or " diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index 86b7cd50ec..ce4b43b593 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.2 2002/04/21 00:26:42 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.3 2002/04/27 03:45:01 tgl Exp $ * * DESCRIPTION * These routines take the parse tree and pick out the @@ -86,6 +86,7 @@ compute_return_type(TypeName *returnType, Oid languageOid, else { Oid namespaceId; + AclResult aclresult; char *typname; if (languageOid == SQLlanguageId) @@ -94,6 +95,10 @@ compute_return_type(TypeName *returnType, Oid languageOid, typnam); namespaceId = QualifiedNameGetCreationNamespace(returnType->names, &typname); + aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), + ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, get_namespace_name(namespaceId)); rettype = TypeShellMake(typname, namespaceId); if (!OidIsValid(rettype)) elog(ERROR, "could not create type %s", typnam); @@ -295,6 +300,7 @@ CreateFunction(ProcedureStmt *stmt) Oid languageOid; char *funcname; Oid namespaceId; + AclResult aclresult; int parameterCount; Oid parameterTypes[FUNC_MAX_ARGS]; int32 byte_pct, @@ -311,6 +317,11 @@ CreateFunction(ProcedureStmt *stmt) namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname, &funcname); + /* Check we have creation rights in target namespace */ + aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, get_namespace_name(namespaceId)); + /* Convert language name to canonical case */ case_translate_language_name(stmt->language, languageName); @@ -324,10 +335,21 @@ CreateFunction(ProcedureStmt *stmt) languageOid = languageTuple->t_data->t_oid; languageStruct = (Form_pg_language) GETSTRUCT(languageTuple); - if (!((languageStruct->lanpltrusted - && pg_language_aclcheck(languageOid, GetUserId(), ACL_USAGE) == ACLCHECK_OK) - || superuser())) - elog(ERROR, "permission denied"); + if (languageStruct->lanpltrusted) + { + /* if trusted language, need USAGE privilege */ + AclResult aclresult; + + aclresult = pg_language_aclcheck(languageOid, GetUserId(), ACL_USAGE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, NameStr(languageStruct->lanname)); + } + else + { + /* if untrusted language, must be superuser */ + if (!superuser()) + aclcheck_error(ACLCHECK_NO_PRIV, NameStr(languageStruct->lanname)); + } ReleaseSysCache(languageTuple); @@ -404,9 +426,11 @@ RemoveFunction(List *functionName, /* function name to be removed */ elog(ERROR, "RemoveFunction: couldn't find tuple for function %s", NameListToString(functionName)); - if (!pg_proc_ownercheck(funcOid, GetUserId())) - elog(ERROR, "RemoveFunction: function '%s': permission denied", - NameListToString(functionName)); + /* Permission check: must own func or its namespace */ + if (!pg_proc_ownercheck(funcOid, GetUserId()) && + !pg_namespace_ownercheck(((Form_pg_proc) GETSTRUCT(tup))->pronamespace, + GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(functionName)); if (((Form_pg_proc) GETSTRUCT(tup))->proisagg) elog(ERROR, "RemoveFunction: function '%s' is an aggregate" diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 14889a4f0c..df6f81cd1d 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.71 2002/04/17 20:57:56 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.72 2002/04/27 03:45:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -30,6 +30,7 @@ #include "parser/parsetree.h" #include "parser/parse_coerce.h" #include "parser/parse_func.h" +#include "utils/acl.h" #include "utils/builtins.h" #include "utils/lsyscache.h" #include "utils/syscache.h" @@ -73,6 +74,7 @@ DefineIndex(RangeVar *heapRelation, Oid *classObjectId; Oid accessMethodId; Oid relationId; + Oid namespaceId; Relation rel; HeapTuple tuple; Form_pg_am accessMethodForm; @@ -102,6 +104,7 @@ DefineIndex(RangeVar *heapRelation, heapRelation->relname); relationId = RelationGetRelid(rel); + namespaceId = RelationGetNamespace(rel); if (!IsBootstrapProcessingMode() && IsSystemRelation(rel) && @@ -111,6 +114,22 @@ DefineIndex(RangeVar *heapRelation, heap_close(rel, NoLock); /* + * Verify we (still) have CREATE rights in the rel's namespace. + * (Presumably we did when the rel was created, but maybe not anymore.) + * Skip check if bootstrapping, since permissions machinery may not + * be working yet; also, always allow if it's a temp table. + */ + if (!IsBootstrapProcessingMode() && !isTempNamespace(namespaceId)) + { + AclResult aclresult; + + aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), + ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, get_namespace_name(namespaceId)); + } + + /* * look up the access method, verify it can handle the requested * features */ diff --git a/src/backend/commands/lockcmds.c b/src/backend/commands/lockcmds.c index c91669572e..80e42e3aa1 100644 --- a/src/backend/commands/lockcmds.c +++ b/src/backend/commands/lockcmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/lockcmds.c,v 1.1 2002/04/15 05:22:03 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/lockcmds.c,v 1.2 2002/04/27 03:45:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,7 @@ #include "commands/lockcmds.h" #include "miscadmin.h" #include "utils/acl.h" +#include "utils/lsyscache.h" /* @@ -38,7 +39,7 @@ LockTableCommand(LockStmt *lockstmt) { RangeVar *relation = lfirst(p); Oid reloid; - int32 aclresult; + AclResult aclresult; Relation rel; /* @@ -55,7 +56,7 @@ LockTableCommand(LockStmt *lockstmt) ACL_UPDATE | ACL_DELETE); if (aclresult != ACLCHECK_OK) - elog(ERROR, "LOCK TABLE: permission denied"); + aclcheck_error(aclresult, get_rel_name(reloid)); rel = relation_open(reloid, lockstmt->mode); diff --git a/src/backend/commands/operatorcmds.c b/src/backend/commands/operatorcmds.c index ffc35ea1ae..de8ec06acb 100644 --- a/src/backend/commands/operatorcmds.c +++ b/src/backend/commands/operatorcmds.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/operatorcmds.c,v 1.2 2002/04/16 23:08:10 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/operatorcmds.c,v 1.3 2002/04/27 03:45:01 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -44,6 +44,7 @@ #include "parser/parse_oper.h" #include "parser/parse_type.h" #include "utils/acl.h" +#include "utils/lsyscache.h" #include "utils/syscache.h" @@ -60,6 +61,7 @@ DefineOperator(List *names, List *parameters) { char *oprName; Oid oprNamespace; + AclResult aclresult; uint16 precedence = 0; /* operator precedence */ bool canHash = false; /* operator hashes */ bool canMerge = false; /* operator merges */ @@ -85,6 +87,11 @@ DefineOperator(List *names, List *parameters) /* Convert list of names to a name and namespace */ oprNamespace = QualifiedNameGetCreationNamespace(names, &oprName); + /* Check we have creation rights in target namespace */ + aclresult = pg_namespace_aclcheck(oprNamespace, GetUserId(), ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, get_namespace_name(oprNamespace)); + /* * loop over the definition list and extract the information we need. */ @@ -226,14 +233,15 @@ RemoveOperator(List *operatorName, /* operator name */ tup = SearchSysCacheCopy(OPEROID, ObjectIdGetDatum(operOid), 0, 0, 0); - if (!HeapTupleIsValid(tup)) /* should not happen */ elog(ERROR, "RemoveOperator: failed to find tuple for operator '%s'", NameListToString(operatorName)); - if (!pg_oper_ownercheck(operOid, GetUserId())) - elog(ERROR, "RemoveOperator: operator '%s': permission denied", - NameListToString(operatorName)); + /* Permission check: must own operator or its namespace */ + if (!pg_oper_ownercheck(operOid, GetUserId()) && + !pg_namespace_ownercheck(((Form_pg_operator) GETSTRUCT(tup))->oprnamespace, + GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(operatorName)); /* Delete any comments associated with this operator */ DeleteComments(operOid, RelationGetRelid(relation)); diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c index 191d5e329b..30bc4077d3 100644 --- a/src/backend/commands/schemacmds.c +++ b/src/backend/commands/schemacmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/schemacmds.c,v 1.1 2002/04/15 05:22:03 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/schemacmds.c,v 1.2 2002/04/27 03:45:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -20,6 +20,7 @@ #include "miscadmin.h" #include "parser/analyze.h" #include "tcop/utility.h" +#include "utils/acl.h" #include "utils/lsyscache.h" @@ -36,9 +37,14 @@ CreateSchemaCommand(CreateSchemaStmt *stmt) const char *owner_name; Oid owner_userid; Oid saved_userid; + AclResult aclresult; saved_userid = GetUserId(); + /* + * Figure out user identities. + */ + if (!authId) { owner_userid = saved_userid; @@ -67,6 +73,13 @@ CreateSchemaCommand(CreateSchemaStmt *stmt) owner_name, authId); } + /* + * Permissions checks. + */ + aclresult = pg_database_aclcheck(MyDatabaseId, saved_userid, ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, DatabaseName); + if (!allowSystemTableMods && IsReservedName(schemaName)) elog(ERROR, "CREATE SCHEMA: Illegal schema name: \"%s\" -- pg_ is reserved for system schemas", schemaName); diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 7bdc238e77..32930710c6 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.10 2002/04/26 19:29:47 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.11 2002/04/27 03:45:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -106,10 +106,22 @@ DefineRelation(CreateStmt *stmt, char relkind) /* * Look up the namespace in which we are supposed to create the - * relation. + * relation. Check we have permission to create there. + * Skip check if bootstrapping, since permissions machinery may not + * be working yet; also, always allow if it's a temp table. */ namespaceId = RangeVarGetCreationNamespace(stmt->relation); + if (!IsBootstrapProcessingMode() && !isTempNamespace(namespaceId)) + { + AclResult aclresult; + + aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), + ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, get_namespace_name(namespaceId)); + } + /* * Merge domain attributes into the known columns before processing table * inheritance. Otherwise we risk adding double constraints to a @@ -307,8 +319,7 @@ TruncateRelation(const RangeVar *relation) RelationGetRelationName(rel)); if (!pg_class_ownercheck(relid, GetUserId())) - elog(ERROR, "you do not own relation \"%s\"", - RelationGetRelationName(rel)); + aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(rel)); /* Keep the lock until transaction commit */ heap_close(rel, NoLock); @@ -483,8 +494,8 @@ MergeAttributes(List *schema, List *supers, bool istemp, * demand that creator of a child table own the parent. */ if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId())) - elog(ERROR, "you do not own table \"%s\"", - parent->relname); + aclcheck_error(ACLCHECK_NOT_OWNER, + RelationGetRelationName(relation)); /* * Reject duplications in the list of parents. @@ -1003,8 +1014,8 @@ renameatt(Oid relid, elog(ERROR, "renameatt: class \"%s\" is a system catalog", RelationGetRelationName(targetrelation)); if (!pg_class_ownercheck(relid, GetUserId())) - elog(ERROR, "renameatt: you do not own class \"%s\"", - RelationGetRelationName(targetrelation)); + aclcheck_error(ACLCHECK_NOT_OWNER, + RelationGetRelationName(targetrelation)); /* * if the 'recurse' flag is set then we are supposed to rename this @@ -1558,8 +1569,7 @@ AlterTableAddColumn(Oid myrelid, elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog", RelationGetRelationName(rel)); if (!pg_class_ownercheck(myrelid, GetUserId())) - elog(ERROR, "ALTER TABLE: \"%s\": permission denied", - RelationGetRelationName(rel)); + aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(rel)); /* * Recurse to add the column to child classes, if requested. @@ -1761,8 +1771,7 @@ AlterTableAlterColumnDropNotNull(Oid myrelid, RelationGetRelationName(rel)); if (!pg_class_ownercheck(myrelid, GetUserId())) - elog(ERROR, "ALTER TABLE: \"%s\": permission denied", - RelationGetRelationName(rel)); + aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(rel)); /* * Propagate to children if desired @@ -1912,8 +1921,7 @@ AlterTableAlterColumnSetNotNull(Oid myrelid, RelationGetRelationName(rel)); if (!pg_class_ownercheck(myrelid, GetUserId())) - elog(ERROR, "ALTER TABLE: \"%s\": permission denied", - RelationGetRelationName(rel)); + aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(rel)); /* * Propagate to children if desired @@ -2048,8 +2056,7 @@ AlterTableAlterColumnDefault(Oid myrelid, RelationGetRelationName(rel)); if (!pg_class_ownercheck(myrelid, GetUserId())) - elog(ERROR, "ALTER TABLE: \"%s\": permission denied", - RelationGetRelationName(rel)); + aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(rel)); /* * Propagate to children if desired @@ -2208,8 +2215,7 @@ AlterTableAlterColumnFlags(Oid myrelid, RelationGetRelationName(rel)); if (!pg_class_ownercheck(myrelid, GetUserId())) - elog(ERROR, "ALTER TABLE: \"%s\": permission denied", - RelationGetRelationName(rel)); + aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(rel)); /* * Check the supplied parameters before anything else @@ -2370,8 +2376,7 @@ AlterTableAddConstraint(Oid myrelid, RelationGetRelationName(rel)); if (!pg_class_ownercheck(myrelid, GetUserId())) - elog(ERROR, "ALTER TABLE: \"%s\": permission denied", - RelationGetRelationName(rel)); + aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(rel)); if (inh) { @@ -2695,8 +2700,7 @@ AlterTableDropConstraint(Oid myrelid, RelationGetRelationName(rel)); if (!pg_class_ownercheck(myrelid, GetUserId())) - elog(ERROR, "ALTER TABLE: \"%s\": permission denied", - RelationGetRelationName(rel)); + aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(rel)); /* * Since all we have is the name of the constraint, we have to look @@ -2857,8 +2861,7 @@ AlterTableCreateToastTable(Oid relOid, bool silent) RelationGetRelationName(rel)); if (!pg_class_ownercheck(relOid, GetUserId())) - elog(ERROR, "ALTER TABLE: \"%s\": permission denied", - RelationGetRelationName(rel)); + aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(rel)); /* * lock the pg_class tuple for update (is that really needed?) diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index b826297a71..52e9761d75 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.115 2002/04/26 19:29:47 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.116 2002/04/27 03:45:02 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -58,6 +58,7 @@ CreateTrigger(CreateTrigStmt *stmt) Datum values[Natts_pg_trigger]; char nulls[Natts_pg_trigger]; Relation rel; + AclResult aclresult; Relation tgrel; SysScanDesc tgscan; ScanKeyData key; @@ -84,10 +85,10 @@ CreateTrigger(CreateTrigStmt *stmt) elog(ERROR, "CreateTrigger: can't create trigger for system relation %s", stmt->relation->relname); - if (pg_class_aclcheck(RelationGetRelid(rel), GetUserId(), - stmt->isconstraint ? ACL_REFERENCES : ACL_TRIGGER) - != ACLCHECK_OK) - elog(ERROR, "permission denied"); + aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(), + stmt->isconstraint ? ACL_REFERENCES : ACL_TRIGGER); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, RelationGetRelationName(rel)); /* * If trigger is an RI constraint, use trigger name as constraint name @@ -337,8 +338,7 @@ DropTrigger(Oid relid, const char *trigname) RelationGetRelationName(rel)); if (!pg_class_ownercheck(relid, GetUserId())) - elog(ERROR, "%s: %s", RelationGetRelationName(rel), - aclcheck_error_strings[ACLCHECK_NOT_OWNER]); + aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(rel)); /* * Search pg_trigger, delete target trigger, count remaining triggers diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index 13dbf04aaa..74e5a15cc8 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.1 2002/04/15 05:22:03 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.2 2002/04/27 03:45:02 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -45,6 +45,7 @@ #include "utils/acl.h" #include "utils/builtins.h" #include "utils/fmgroids.h" +#include "utils/lsyscache.h" #include "utils/syscache.h" @@ -60,6 +61,7 @@ DefineType(List *names, List *parameters) { char *typeName; Oid typeNamespace; + AclResult aclresult; int16 internalLength = -1; /* int2 */ int16 externalLength = -1; /* int2 */ Oid elemType = InvalidOid; @@ -83,6 +85,11 @@ DefineType(List *names, List *parameters) /* Convert list of names to a name and namespace */ typeNamespace = QualifiedNameGetCreationNamespace(names, &typeName); + /* Check we have creation rights in target namespace */ + aclresult = pg_namespace_aclcheck(typeNamespace, GetUserId(), ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, get_namespace_name(typeNamespace)); + /* * Type names must be one character shorter than other names, allowing * room to create the corresponding array type name with prepended @@ -288,9 +295,11 @@ RemoveType(List *names) elog(ERROR, "Type \"%s\" does not exist", TypeNameToString(typename)); - if (!pg_type_ownercheck(typeoid, GetUserId())) - elog(ERROR, "RemoveType: type '%s': permission denied", - TypeNameToString(typename)); + /* Permission check: must own type or its namespace */ + if (!pg_type_ownercheck(typeoid, GetUserId()) && + !pg_namespace_ownercheck(((Form_pg_type) GETSTRUCT(tup))->typnamespace, + GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, TypeNameToString(typename)); /* Delete any comments associated with this type */ DeleteComments(typeoid, RelationGetRelid(relation)); @@ -334,6 +343,7 @@ DefineDomain(CreateDomainStmt *stmt) { char *domainName; Oid domainNamespace; + AclResult aclresult; int16 internalLength; int16 externalLength; Oid inputProcedure; @@ -360,6 +370,12 @@ DefineDomain(CreateDomainStmt *stmt) domainNamespace = QualifiedNameGetCreationNamespace(stmt->domainname, &domainName); + /* Check we have creation rights in target namespace */ + aclresult = pg_namespace_aclcheck(domainNamespace, GetUserId(), + ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, get_namespace_name(domainNamespace)); + /* * Domainnames, unlike typenames don't need to account for the '_' * prefix. So they can be one character longer. @@ -586,9 +602,11 @@ RemoveDomain(List *names, int behavior) elog(ERROR, "RemoveDomain: type '%s' does not exist", TypeNameToString(typename)); - if (!pg_type_ownercheck(typeoid, GetUserId())) - elog(ERROR, "RemoveDomain: type '%s': permission denied", - TypeNameToString(typename)); + /* Permission check: must own type or its namespace */ + if (!pg_type_ownercheck(typeoid, GetUserId()) && + !pg_namespace_ownercheck(((Form_pg_type) GETSTRUCT(tup))->typnamespace, + GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, TypeNameToString(typename)); /* Check that this is actually a domain */ typtype = ((Form_pg_type) GETSTRUCT(tup))->typtype; |
