From: Tom Lane Date: Tue, 30 Apr 2002 01:26:26 +0000 (+0000) Subject: Clean up loose ends remaining from schema privileges discussion. X-Git-Url: http://git.postgresql.org/gitweb/static/gitweb.js?a=commitdiff_plain;h=2e2f71bc9f2c438c9b166a0ce752f9de0383f6af;p=users%2Fbernd%2Fpostgres.git Clean up loose ends remaining from schema privileges discussion. I concluded that RENAME should require CREATE privilege on the namespace as well as ownership of the table. --- diff --git a/doc/src/sgml/ref/grant.sgml b/doc/src/sgml/ref/grant.sgml index 0ef5caa89a..78435db7d8 100644 --- a/doc/src/sgml/ref/grant.sgml +++ b/doc/src/sgml/ref/grant.sgml @@ -161,6 +161,8 @@ GRANT { { CREATE | USAGE } [,...] | ALL [ PRIVILEGES ] } For schemas, allows new objects to be created within the schema. + To rename an existing object, you must own the object and + have this privilege for the containing schema. diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c index b06b23257f..6f0cc453b5 100644 --- a/src/backend/catalog/namespace.c +++ b/src/backend/catalog/namespace.c @@ -1161,7 +1161,12 @@ GetTempTableNamespace(void) { /* * First use of this temp namespace in this database; create it. - * The temp namespaces are always owned by the superuser. + * The temp namespaces are always owned by the superuser. We + * leave their permissions at default --- i.e., no access except to + * superuser --- to ensure that unprivileged users can't peek + * at other backends' temp tables. This works because the places + * that access the temp namespace for my own backend skip permissions + * checks on it. */ namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_USESYSID); /* Advance command counter to make namespace visible */ diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 04bbfc1e37..4133bba54c 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -374,25 +374,49 @@ ProcessUtility(Node *parsetree, case T_RenameStmt: { RenameStmt *stmt = (RenameStmt *) parsetree; + Oid relid; CheckOwnership(stmt->relation, true); + relid = RangeVarGetRelid(stmt->relation, false); + switch (stmt->renameType) { case RENAME_TABLE: - renamerel(RangeVarGetRelid(stmt->relation, false), - stmt->newname); + { + /* + * RENAME TABLE requires that we (still) hold CREATE + * rights on the containing namespace, as well as + * ownership of the table. But skip check for + * temp tables. + */ + Oid namespaceId = get_rel_namespace(relid); + + if (!isTempNamespace(namespaceId)) + { + AclResult aclresult; + + aclresult = pg_namespace_aclcheck(namespaceId, + GetUserId(), + ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, + get_namespace_name(namespaceId)); + } + + renamerel(relid, stmt->newname); break; + } case RENAME_COLUMN: - renameatt(RangeVarGetRelid(stmt->relation, false), - stmt->oldname, /* old att name */ - stmt->newname, /* new att name */ - interpretInhOption(stmt->relation->inhOpt)); /* recursive? */ + renameatt(relid, + stmt->oldname, /* old att name */ + stmt->newname, /* new att name */ + interpretInhOption(stmt->relation->inhOpt)); /* recursive? */ break; case RENAME_TRIGGER: - renametrig(RangeVarGetRelid(stmt->relation, false), - stmt->oldname, /* old att name */ - stmt->newname); /* new att name */ + renametrig(relid, + stmt->oldname, /* old att name */ + stmt->newname); /* new att name */ break; case RENAME_RULE: elog(ERROR, "ProcessUtility: Invalid target for RENAME: %d", @@ -410,6 +434,9 @@ ProcessUtility(Node *parsetree, case T_AlterTableStmt: { AlterTableStmt *stmt = (AlterTableStmt *) parsetree; + Oid relid; + + relid = RangeVarGetRelid(stmt->relation, false); /* * Some or all of these functions are recursive to cover @@ -422,7 +449,7 @@ ProcessUtility(Node *parsetree, * Recursively add column to table and, * if requested, to descendants */ - AlterTableAddColumn(RangeVarGetRelid(stmt->relation, false), + AlterTableAddColumn(relid, interpretInhOption(stmt->relation->inhOpt), (ColumnDef *) stmt->def); break; @@ -431,18 +458,18 @@ ProcessUtility(Node *parsetree, * Recursively alter column default for table and, * if requested, for descendants */ - AlterTableAlterColumnDefault(RangeVarGetRelid(stmt->relation, false), + AlterTableAlterColumnDefault(relid, interpretInhOption(stmt->relation->inhOpt), stmt->name, stmt->def); break; case 'N': /* ALTER COLUMN DROP NOT NULL */ - AlterTableAlterColumnDropNotNull(RangeVarGetRelid(stmt->relation, false), + AlterTableAlterColumnDropNotNull(relid, interpretInhOption(stmt->relation->inhOpt), stmt->name); break; case 'O': /* ALTER COLUMN SET NOT NULL */ - AlterTableAlterColumnSetNotNull(RangeVarGetRelid(stmt->relation, false), + AlterTableAlterColumnSetNotNull(relid, interpretInhOption(stmt->relation->inhOpt), stmt->name); break; @@ -452,7 +479,7 @@ ProcessUtility(Node *parsetree, * Recursively alter column statistics for table and, * if requested, for descendants */ - AlterTableAlterColumnFlags(RangeVarGetRelid(stmt->relation, false), + AlterTableAlterColumnFlags(relid, interpretInhOption(stmt->relation->inhOpt), stmt->name, stmt->def, @@ -464,7 +491,7 @@ ProcessUtility(Node *parsetree, * Recursively drop column from table and, * if requested, from descendants */ - AlterTableDropColumn(RangeVarGetRelid(stmt->relation, false), + AlterTableDropColumn(relid, interpretInhOption(stmt->relation->inhOpt), stmt->name, stmt->behavior); @@ -474,7 +501,7 @@ ProcessUtility(Node *parsetree, * Recursively add constraint to table and, * if requested, to descendants */ - AlterTableAddConstraint(RangeVarGetRelid(stmt->relation, false), + AlterTableAddConstraint(relid, interpretInhOption(stmt->relation->inhOpt), (List *) stmt->def); break; @@ -483,21 +510,20 @@ ProcessUtility(Node *parsetree, * Recursively drop constraint from table and, * if requested, from descendants */ - AlterTableDropConstraint(RangeVarGetRelid(stmt->relation, false), + AlterTableDropConstraint(relid, interpretInhOption(stmt->relation->inhOpt), stmt->name, stmt->behavior); break; case 'E': /* CREATE TOAST TABLE */ - AlterTableCreateToastTable(RangeVarGetRelid(stmt->relation, false), - false); + AlterTableCreateToastTable(relid, false); break; case 'U': /* ALTER OWNER */ /* check that we are the superuser */ if (!superuser()) elog(ERROR, "ALTER TABLE: permission denied"); /* get_usesysid raises an error if no such user */ - AlterTableOwner(RangeVarGetRelid(stmt->relation, false), + AlterTableOwner(relid, get_usesysid(stmt->name)); break; default: /* oops */ diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index b416337b07..a7b9ab40ce 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -708,6 +708,32 @@ get_rel_name(Oid relid) return NULL; } +/* + * get_rel_namespace + * + * Returns the pg_namespace OID associated with a given relation. + */ +Oid +get_rel_namespace(Oid relid) +{ + HeapTuple tp; + + tp = SearchSysCache(RELOID, + ObjectIdGetDatum(relid), + 0, 0, 0); + if (HeapTupleIsValid(tp)) + { + Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp); + Oid result; + + result = reltup->relnamespace; + ReleaseSysCache(tp); + return result; + } + else + return InvalidOid; +} + /* * get_rel_type_id * diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h index 81e53dbdaf..bfc3a6575e 100644 --- a/src/include/utils/lsyscache.h +++ b/src/include/utils/lsyscache.h @@ -42,6 +42,7 @@ extern Oid get_func_rettype(Oid funcid); extern char func_volatile(Oid funcid); extern Oid get_relname_relid(const char *relname, Oid relnamespace); extern char *get_rel_name(Oid relid); +extern Oid get_rel_namespace(Oid relid); extern Oid get_rel_type_id(Oid relid); extern bool get_typisdefined(Oid typid); extern int16 get_typlen(Oid typid);