Clean up loose ends remaining from schema privileges discussion.
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 30 Apr 2002 01:26:26 +0000 (01:26 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 30 Apr 2002 01:26:26 +0000 (01:26 +0000)
I concluded that RENAME should require CREATE privilege on the namespace
as well as ownership of the table.

doc/src/sgml/ref/grant.sgml
src/backend/catalog/namespace.c
src/backend/tcop/utility.c
src/backend/utils/cache/lsyscache.c
src/include/utils/lsyscache.h

index 1697f91929a5ee4332cb928c2efe43f75b58147f..226db71d6838c99747760bc80254cca291a61353 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/ref/grant.sgml,v 1.24 2002/04/29 22:28:19 tgl Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/ref/grant.sgml,v 1.25 2002/04/30 01:26:25 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -161,6 +161,8 @@ GRANT { { CREATE | USAGE } [,...] | ALL [ PRIVILEGES ] }
       </para>
       <para>
        For schemas, allows new objects to be created within the schema.
+       To rename an existing object, you must own the object <emphasis>and</>
+       have this privilege for the containing schema.
       </para>
      </listitem>
     </varlistentry>
index 51ef7c3f8d9c54fdd50a3e691767f3e7de0cb76a..80ce60f8ab24643641d88fe71c03e3c8f5f4e99b 100644 (file)
@@ -13,7 +13,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.15 2002/04/29 22:15:07 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.16 2002/04/30 01:26:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -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 */
index 771f3d30cc8d2b5340184644c0440b619f76a554..9a9c062559e7a696eea76af281031cc2105cb297 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.152 2002/04/27 03:45:03 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.153 2002/04/30 01:26:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -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 */
index f6b98c5bee621132442e4b65f1c097907e035360..ca3bd80e8a7e58366a5ab4a0e4c1295984ebd73e 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.71 2002/04/27 03:45:03 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.72 2002/04/30 01:26:26 tgl Exp $
  *
  * NOTES
  *       Eventually, the index information should go through here, too.
@@ -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
  *
index f57219df119b5c6e495ddf7ef6b0c017be662b2e..9f8122567375f22ecfebc5e2b2ab94c957ab81c6 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: lsyscache.h,v 1.50 2002/04/27 03:45:03 tgl Exp $
+ * $Id: lsyscache.h,v 1.51 2002/04/30 01:26:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -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);